blob: 2753f2f245ab024dddab11c30c40dfe6579a444f [file] [log] [blame]
Geoff Langa8406172015-07-21 16:53:39 -04001//
2// Copyright (c) 2015 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
7// Image.cpp: Implements the egl::Image class representing the EGLimage object.
8
9#include "libANGLE/Image.h"
10
11#include "common/debug.h"
12#include "common/utilities.h"
Geoff Lang9d05b932018-07-27 15:47:18 -040013#include "libANGLE/Context.h"
Geoff Lange1a057e2018-06-07 15:09:00 -040014#include "libANGLE/Renderbuffer.h"
15#include "libANGLE/Texture.h"
Geoff Langa8406172015-07-21 16:53:39 -040016#include "libANGLE/angletypes.h"
Jamie Madilla3944d42016-07-22 22:13:26 -040017#include "libANGLE/formatutils.h"
Jamie Madill76b8f462017-04-21 12:23:40 -040018#include "libANGLE/renderer/EGLImplFactory.h"
Geoff Langa8406172015-07-21 16:53:39 -040019#include "libANGLE/renderer/ImageImpl.h"
20
21namespace egl
22{
Jamie Madill76b8f462017-04-21 12:23:40 -040023
24namespace
25{
26gl::ImageIndex GetImageIndex(EGLenum eglTarget, const egl::AttributeMap &attribs)
27{
28 if (eglTarget == EGL_GL_RENDERBUFFER)
29 {
Jamie Madillcc129372018-04-12 09:13:18 -040030 return gl::ImageIndex();
Jamie Madill76b8f462017-04-21 12:23:40 -040031 }
32
Corentin Wallezf0e89be2017-11-08 14:00:32 -080033 gl::TextureTarget target = egl_gl::EGLImageTargetToTextureTarget(eglTarget);
Geoff Lange1a057e2018-06-07 15:09:00 -040034 GLint mip = static_cast<GLint>(attribs.get(EGL_GL_TEXTURE_LEVEL_KHR, 0));
35 GLint layer = static_cast<GLint>(attribs.get(EGL_GL_TEXTURE_ZOFFSET_KHR, 0));
Jamie Madill76b8f462017-04-21 12:23:40 -040036
Corentin Wallezf0e89be2017-11-08 14:00:32 -080037 if (target == gl::TextureTarget::_3D)
Jamie Madill76b8f462017-04-21 12:23:40 -040038 {
39 return gl::ImageIndex::Make3D(mip, layer);
40 }
41 else
42 {
43 ASSERT(layer == 0);
Jamie Madillcc129372018-04-12 09:13:18 -040044 return gl::ImageIndex::MakeFromTarget(target, mip);
Jamie Madill76b8f462017-04-21 12:23:40 -040045 }
46}
Geoff Lang9d05b932018-07-27 15:47:18 -040047
48const Display *DisplayFromContext(const gl::Context *context)
49{
50 return (context ? context->getCurrentDisplay() : nullptr);
51}
52
Jamie Madill76b8f462017-04-21 12:23:40 -040053} // anonymous namespace
54
Geoff Lang9d05b932018-07-27 15:47:18 -040055ImageSibling::ImageSibling() : FramebufferAttachmentObject(), mSourcesOf(), mTargetOf()
Geoff Langa8406172015-07-21 16:53:39 -040056{
57}
58
59ImageSibling::~ImageSibling()
60{
61 // EGL images should hold a ref to their targets and siblings, a Texture should not be deletable
62 // while it is attached to an EGL image.
Jamie Madill4928b7c2017-06-20 12:57:39 -040063 // Child class should orphan images before destruction.
Geoff Langa8406172015-07-21 16:53:39 -040064 ASSERT(mSourcesOf.empty());
Jamie Madill4928b7c2017-06-20 12:57:39 -040065 ASSERT(mTargetOf.get() == nullptr);
Geoff Langa8406172015-07-21 16:53:39 -040066}
67
Jamie Madill4928b7c2017-06-20 12:57:39 -040068void ImageSibling::setTargetImage(const gl::Context *context, egl::Image *imageTarget)
Geoff Langa8406172015-07-21 16:53:39 -040069{
70 ASSERT(imageTarget != nullptr);
Geoff Lang9d05b932018-07-27 15:47:18 -040071 mTargetOf.set(DisplayFromContext(context), imageTarget);
Geoff Langa8406172015-07-21 16:53:39 -040072 imageTarget->addTargetSibling(this);
73}
74
Jamie Madill4928b7c2017-06-20 12:57:39 -040075gl::Error ImageSibling::orphanImages(const gl::Context *context)
Geoff Langa8406172015-07-21 16:53:39 -040076{
77 if (mTargetOf.get() != nullptr)
78 {
79 // Can't be a target and have sources.
80 ASSERT(mSourcesOf.empty());
81
Jamie Madill4928b7c2017-06-20 12:57:39 -040082 ANGLE_TRY(mTargetOf->orphanSibling(context, this));
Geoff Lang9d05b932018-07-27 15:47:18 -040083 mTargetOf.set(DisplayFromContext(context), nullptr);
Geoff Langa8406172015-07-21 16:53:39 -040084 }
85 else
86 {
Geoff Lang9d05b932018-07-27 15:47:18 -040087 for (Image *sourceImage : mSourcesOf)
Geoff Langa8406172015-07-21 16:53:39 -040088 {
Jamie Madill4928b7c2017-06-20 12:57:39 -040089 ANGLE_TRY(sourceImage->orphanSibling(context, this));
Geoff Langa8406172015-07-21 16:53:39 -040090 }
91 mSourcesOf.clear();
92 }
93
He Yunchaoacd18982017-01-04 10:46:42 +080094 return gl::NoError();
Geoff Langa8406172015-07-21 16:53:39 -040095}
96
97void ImageSibling::addImageSource(egl::Image *imageSource)
98{
99 ASSERT(imageSource != nullptr);
100 mSourcesOf.insert(imageSource);
101}
102
103void ImageSibling::removeImageSource(egl::Image *imageSource)
104{
105 ASSERT(mSourcesOf.find(imageSource) != mSourcesOf.end());
106 mSourcesOf.erase(imageSource);
107}
108
Jamie Madill05b35b22017-10-03 09:01:44 -0400109bool ImageSibling::isEGLImageTarget() const
110{
111 return (mTargetOf.get() != nullptr);
112}
113
114gl::InitState ImageSibling::sourceEGLImageInitState() const
115{
116 ASSERT(isEGLImageTarget());
117 return mTargetOf->sourceInitState();
118}
119
120void ImageSibling::setSourceEGLImageInitState(gl::InitState initState) const
121{
122 ASSERT(isEGLImageTarget());
123 mTargetOf->setInitState(initState);
124}
125
Yuly Novikov2eb54072018-08-22 16:41:26 -0400126bool ImageSibling::isRenderable(const gl::Context *context,
127 GLenum binding,
128 const gl::ImageIndex &imageIndex) const
129{
130 ASSERT(isEGLImageTarget());
131 return mTargetOf->isRenderable(context);
132}
133
Jamie Madill76b8f462017-04-21 12:23:40 -0400134ImageState::ImageState(EGLenum target, ImageSibling *buffer, const AttributeMap &attribs)
Geoff Lang0bc81b62018-07-30 13:34:50 -0400135 : label(nullptr),
136 imageIndex(GetImageIndex(target, attribs)),
137 source(buffer),
138 targets(),
139 format(buffer->getAttachmentFormat(GL_NONE, imageIndex)),
140 size(buffer->getAttachmentSize(imageIndex)),
Yuly Novikov2eb54072018-08-22 16:41:26 -0400141 samples(buffer->getAttachmentSamples(imageIndex)),
142 sourceType(target)
Jamie Madill76b8f462017-04-21 12:23:40 -0400143{
Jamie Madill76b8f462017-04-21 12:23:40 -0400144}
145
Jamie Madillacf2f3a2017-11-21 19:22:44 -0500146ImageState::~ImageState()
147{
148}
149
Jamie Madill76b8f462017-04-21 12:23:40 -0400150Image::Image(rx::EGLImplFactory *factory,
Geoff Langcd7cd2a2018-07-19 11:25:54 -0400151 const gl::Context *context,
Jamie Madill76b8f462017-04-21 12:23:40 -0400152 EGLenum target,
153 ImageSibling *buffer,
154 const AttributeMap &attribs)
Geoff Lang9d05b932018-07-27 15:47:18 -0400155 : mState(target, buffer, attribs),
Geoff Langcd7cd2a2018-07-19 11:25:54 -0400156 mImplementation(factory->createImage(mState, context, target, attribs)),
Jamie Madill05b35b22017-10-03 09:01:44 -0400157 mOrphanedAndNeedsInit(false)
Geoff Langa8406172015-07-21 16:53:39 -0400158{
159 ASSERT(mImplementation != nullptr);
160 ASSERT(buffer != nullptr);
161
Jamie Madill76b8f462017-04-21 12:23:40 -0400162 mState.source->addImageSource(this);
Geoff Langa8406172015-07-21 16:53:39 -0400163}
164
Jamie Madill1c7f08c2018-10-10 16:13:02 -0400165void Image::onDestroy(const Display *display)
Geoff Langa8406172015-07-21 16:53:39 -0400166{
Geoff Langa8406172015-07-21 16:53:39 -0400167 // All targets should hold a ref to the egl image and it should not be deleted until there are
168 // no siblings left.
Jamie Madill76b8f462017-04-21 12:23:40 -0400169 ASSERT(mState.targets.empty());
Geoff Langa8406172015-07-21 16:53:39 -0400170
171 // Tell the source that it is no longer used by this image
Geoff Lang9d05b932018-07-27 15:47:18 -0400172 if (mState.source != nullptr)
Geoff Langa8406172015-07-21 16:53:39 -0400173 {
Jamie Madill76b8f462017-04-21 12:23:40 -0400174 mState.source->removeImageSource(this);
Geoff Lang9d05b932018-07-27 15:47:18 -0400175 mState.source = nullptr;
Geoff Langa8406172015-07-21 16:53:39 -0400176 }
177}
178
Jamie Madill4928b7c2017-06-20 12:57:39 -0400179Image::~Image()
180{
Jamie Madill71c88b32017-09-14 22:20:29 -0400181 SafeDelete(mImplementation);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400182}
183
Geoff Lang75359662018-04-11 01:42:27 -0400184void Image::setLabel(EGLLabelKHR label)
185{
186 mState.label = label;
187}
188
189EGLLabelKHR Image::getLabel() const
190{
191 return mState.label;
192}
193
Geoff Langa8406172015-07-21 16:53:39 -0400194void Image::addTargetSibling(ImageSibling *sibling)
195{
Jamie Madill76b8f462017-04-21 12:23:40 -0400196 mState.targets.insert(sibling);
Geoff Langa8406172015-07-21 16:53:39 -0400197}
198
Jamie Madill4928b7c2017-06-20 12:57:39 -0400199gl::Error Image::orphanSibling(const gl::Context *context, ImageSibling *sibling)
Geoff Langa8406172015-07-21 16:53:39 -0400200{
Geoff Lang9d05b932018-07-27 15:47:18 -0400201 ASSERT(sibling != nullptr);
202
Geoff Langa8406172015-07-21 16:53:39 -0400203 // notify impl
Jamie Madill4928b7c2017-06-20 12:57:39 -0400204 ANGLE_TRY(mImplementation->orphan(context, sibling));
Geoff Langa8406172015-07-21 16:53:39 -0400205
Geoff Lang9d05b932018-07-27 15:47:18 -0400206 if (mState.source == sibling)
Geoff Langa8406172015-07-21 16:53:39 -0400207 {
208 // If the sibling is the source, it cannot be a target.
Jamie Madill76b8f462017-04-21 12:23:40 -0400209 ASSERT(mState.targets.find(sibling) == mState.targets.end());
Geoff Lang9d05b932018-07-27 15:47:18 -0400210 mState.source = nullptr;
Jamie Madill05b35b22017-10-03 09:01:44 -0400211 mOrphanedAndNeedsInit =
212 (sibling->initState(mState.imageIndex) == gl::InitState::MayNeedInit);
Geoff Langa8406172015-07-21 16:53:39 -0400213 }
214 else
215 {
Jamie Madill76b8f462017-04-21 12:23:40 -0400216 mState.targets.erase(sibling);
Geoff Langa8406172015-07-21 16:53:39 -0400217 }
218
Jamie Madill76b8f462017-04-21 12:23:40 -0400219 return gl::NoError();
Geoff Langa8406172015-07-21 16:53:39 -0400220}
221
Geoff Lang0bc81b62018-07-30 13:34:50 -0400222const gl::Format &Image::getFormat() const
Geoff Langa8406172015-07-21 16:53:39 -0400223{
Geoff Lang0bc81b62018-07-30 13:34:50 -0400224 return mState.format;
Geoff Langa8406172015-07-21 16:53:39 -0400225}
226
Yuly Novikov2eb54072018-08-22 16:41:26 -0400227bool Image::isRenderable(const gl::Context *context) const
228{
229 if (IsTextureTarget(mState.sourceType))
230 {
231 return mState.format.info->textureAttachmentSupport(context->getClientVersion(),
232 context->getExtensions());
233 }
234 if (IsRenderbufferTarget(mState.sourceType))
235 {
236 return mState.format.info->renderbufferSupport(context->getClientVersion(),
237 context->getExtensions());
238 }
239
240 UNREACHABLE();
241 return false;
242}
243
244bool Image::isTexturable(const gl::Context *context) const
245{
246 if (IsTextureTarget(mState.sourceType))
247 {
248 return mState.format.info->textureSupport(context->getClientVersion(),
249 context->getExtensions());
250 }
251 if (IsRenderbufferTarget(mState.sourceType))
252 {
253 return true;
254 }
255
256 UNREACHABLE();
257 return false;
258}
259
Geoff Langa8406172015-07-21 16:53:39 -0400260size_t Image::getWidth() const
261{
Geoff Lang0bc81b62018-07-30 13:34:50 -0400262 return mState.size.width;
Geoff Langa8406172015-07-21 16:53:39 -0400263}
264
265size_t Image::getHeight() const
266{
Geoff Lang0bc81b62018-07-30 13:34:50 -0400267 return mState.size.height;
Geoff Langa8406172015-07-21 16:53:39 -0400268}
269
270size_t Image::getSamples() const
271{
Geoff Lang0bc81b62018-07-30 13:34:50 -0400272 return mState.samples;
Geoff Langa8406172015-07-21 16:53:39 -0400273}
274
Jamie Madill76b8f462017-04-21 12:23:40 -0400275rx::ImageImpl *Image::getImplementation() const
Geoff Langa8406172015-07-21 16:53:39 -0400276{
277 return mImplementation;
278}
279
Geoff Langcd7cd2a2018-07-19 11:25:54 -0400280Error Image::initialize(const Display *display)
Geoff Langa8406172015-07-21 16:53:39 -0400281{
Geoff Langcd7cd2a2018-07-19 11:25:54 -0400282 return mImplementation->initialize(display);
Geoff Langa8406172015-07-21 16:53:39 -0400283}
Jamie Madill76b8f462017-04-21 12:23:40 -0400284
Jamie Madill05b35b22017-10-03 09:01:44 -0400285bool Image::orphaned() const
286{
Geoff Lang9d05b932018-07-27 15:47:18 -0400287 return (mState.source == nullptr);
Jamie Madill05b35b22017-10-03 09:01:44 -0400288}
289
290gl::InitState Image::sourceInitState() const
291{
292 if (orphaned())
293 {
294 return mOrphanedAndNeedsInit ? gl::InitState::MayNeedInit : gl::InitState::Initialized;
295 }
296
297 return mState.source->initState(mState.imageIndex);
298}
299
300void Image::setInitState(gl::InitState initState)
301{
302 if (orphaned())
303 {
304 mOrphanedAndNeedsInit = false;
305 }
306
307 return mState.source->setInitState(mState.imageIndex, initState);
308}
309
Jamie Madilla3944d42016-07-22 22:13:26 -0400310} // namespace egl