blob: 7a86733483b2bfe1f19e665d900a983face1ae68 [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
Geoff Lang9d05b932018-07-27 15:47:18 -0400165Error 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 }
Geoff Lang9d05b932018-07-27 15:47:18 -0400177
178 return NoError();
Geoff Langa8406172015-07-21 16:53:39 -0400179}
180
Jamie Madill4928b7c2017-06-20 12:57:39 -0400181Image::~Image()
182{
Jamie Madill71c88b32017-09-14 22:20:29 -0400183 SafeDelete(mImplementation);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400184}
185
Geoff Lang75359662018-04-11 01:42:27 -0400186void Image::setLabel(EGLLabelKHR label)
187{
188 mState.label = label;
189}
190
191EGLLabelKHR Image::getLabel() const
192{
193 return mState.label;
194}
195
Geoff Langa8406172015-07-21 16:53:39 -0400196void Image::addTargetSibling(ImageSibling *sibling)
197{
Jamie Madill76b8f462017-04-21 12:23:40 -0400198 mState.targets.insert(sibling);
Geoff Langa8406172015-07-21 16:53:39 -0400199}
200
Jamie Madill4928b7c2017-06-20 12:57:39 -0400201gl::Error Image::orphanSibling(const gl::Context *context, ImageSibling *sibling)
Geoff Langa8406172015-07-21 16:53:39 -0400202{
Geoff Lang9d05b932018-07-27 15:47:18 -0400203 ASSERT(sibling != nullptr);
204
Geoff Langa8406172015-07-21 16:53:39 -0400205 // notify impl
Jamie Madill4928b7c2017-06-20 12:57:39 -0400206 ANGLE_TRY(mImplementation->orphan(context, sibling));
Geoff Langa8406172015-07-21 16:53:39 -0400207
Geoff Lang9d05b932018-07-27 15:47:18 -0400208 if (mState.source == sibling)
Geoff Langa8406172015-07-21 16:53:39 -0400209 {
210 // If the sibling is the source, it cannot be a target.
Jamie Madill76b8f462017-04-21 12:23:40 -0400211 ASSERT(mState.targets.find(sibling) == mState.targets.end());
Geoff Lang9d05b932018-07-27 15:47:18 -0400212 mState.source = nullptr;
Jamie Madill05b35b22017-10-03 09:01:44 -0400213 mOrphanedAndNeedsInit =
214 (sibling->initState(mState.imageIndex) == gl::InitState::MayNeedInit);
Geoff Langa8406172015-07-21 16:53:39 -0400215 }
216 else
217 {
Jamie Madill76b8f462017-04-21 12:23:40 -0400218 mState.targets.erase(sibling);
Geoff Langa8406172015-07-21 16:53:39 -0400219 }
220
Jamie Madill76b8f462017-04-21 12:23:40 -0400221 return gl::NoError();
Geoff Langa8406172015-07-21 16:53:39 -0400222}
223
Geoff Lang0bc81b62018-07-30 13:34:50 -0400224const gl::Format &Image::getFormat() const
Geoff Langa8406172015-07-21 16:53:39 -0400225{
Geoff Lang0bc81b62018-07-30 13:34:50 -0400226 return mState.format;
Geoff Langa8406172015-07-21 16:53:39 -0400227}
228
Yuly Novikov2eb54072018-08-22 16:41:26 -0400229bool Image::isRenderable(const gl::Context *context) const
230{
231 if (IsTextureTarget(mState.sourceType))
232 {
233 return mState.format.info->textureAttachmentSupport(context->getClientVersion(),
234 context->getExtensions());
235 }
236 if (IsRenderbufferTarget(mState.sourceType))
237 {
238 return mState.format.info->renderbufferSupport(context->getClientVersion(),
239 context->getExtensions());
240 }
241
242 UNREACHABLE();
243 return false;
244}
245
246bool Image::isTexturable(const gl::Context *context) const
247{
248 if (IsTextureTarget(mState.sourceType))
249 {
250 return mState.format.info->textureSupport(context->getClientVersion(),
251 context->getExtensions());
252 }
253 if (IsRenderbufferTarget(mState.sourceType))
254 {
255 return true;
256 }
257
258 UNREACHABLE();
259 return false;
260}
261
Geoff Langa8406172015-07-21 16:53:39 -0400262size_t Image::getWidth() const
263{
Geoff Lang0bc81b62018-07-30 13:34:50 -0400264 return mState.size.width;
Geoff Langa8406172015-07-21 16:53:39 -0400265}
266
267size_t Image::getHeight() const
268{
Geoff Lang0bc81b62018-07-30 13:34:50 -0400269 return mState.size.height;
Geoff Langa8406172015-07-21 16:53:39 -0400270}
271
272size_t Image::getSamples() const
273{
Geoff Lang0bc81b62018-07-30 13:34:50 -0400274 return mState.samples;
Geoff Langa8406172015-07-21 16:53:39 -0400275}
276
Jamie Madill76b8f462017-04-21 12:23:40 -0400277rx::ImageImpl *Image::getImplementation() const
Geoff Langa8406172015-07-21 16:53:39 -0400278{
279 return mImplementation;
280}
281
Geoff Langcd7cd2a2018-07-19 11:25:54 -0400282Error Image::initialize(const Display *display)
Geoff Langa8406172015-07-21 16:53:39 -0400283{
Geoff Langcd7cd2a2018-07-19 11:25:54 -0400284 return mImplementation->initialize(display);
Geoff Langa8406172015-07-21 16:53:39 -0400285}
Jamie Madill76b8f462017-04-21 12:23:40 -0400286
Jamie Madill05b35b22017-10-03 09:01:44 -0400287bool Image::orphaned() const
288{
Geoff Lang9d05b932018-07-27 15:47:18 -0400289 return (mState.source == nullptr);
Jamie Madill05b35b22017-10-03 09:01:44 -0400290}
291
292gl::InitState Image::sourceInitState() const
293{
294 if (orphaned())
295 {
296 return mOrphanedAndNeedsInit ? gl::InitState::MayNeedInit : gl::InitState::Initialized;
297 }
298
299 return mState.source->initState(mState.imageIndex);
300}
301
302void Image::setInitState(gl::InitState initState)
303{
304 if (orphaned())
305 {
306 mOrphanedAndNeedsInit = false;
307 }
308
309 return mState.source->setInitState(mState.imageIndex, initState);
310}
311
Jamie Madilla3944d42016-07-22 22:13:26 -0400312} // namespace egl