blob: 60c2d7eff5573db9a51194410744acf8d9167c4c [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{
Geoff Langc3ee7ec2018-09-21 16:15:03 -040028 if (!IsTextureTarget(eglTarget))
Jamie Madill76b8f462017-04-21 12:23:40 -040029 {
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
Jamie Madillb980c562018-11-27 11:34:27 -050055ImageSibling::ImageSibling() : FramebufferAttachmentObject(), mSourcesOf(), mTargetOf() {}
Geoff Langa8406172015-07-21 16:53:39 -040056
57ImageSibling::~ImageSibling()
58{
59 // EGL images should hold a ref to their targets and siblings, a Texture should not be deletable
60 // while it is attached to an EGL image.
Jamie Madill4928b7c2017-06-20 12:57:39 -040061 // Child class should orphan images before destruction.
Geoff Langa8406172015-07-21 16:53:39 -040062 ASSERT(mSourcesOf.empty());
Jamie Madill4928b7c2017-06-20 12:57:39 -040063 ASSERT(mTargetOf.get() == nullptr);
Geoff Langa8406172015-07-21 16:53:39 -040064}
65
Jamie Madill4928b7c2017-06-20 12:57:39 -040066void ImageSibling::setTargetImage(const gl::Context *context, egl::Image *imageTarget)
Geoff Langa8406172015-07-21 16:53:39 -040067{
68 ASSERT(imageTarget != nullptr);
Geoff Lang9d05b932018-07-27 15:47:18 -040069 mTargetOf.set(DisplayFromContext(context), imageTarget);
Geoff Langa8406172015-07-21 16:53:39 -040070 imageTarget->addTargetSibling(this);
71}
72
Jamie Madill666818e2018-11-14 09:54:33 -050073angle::Result ImageSibling::orphanImages(const gl::Context *context)
Geoff Langa8406172015-07-21 16:53:39 -040074{
75 if (mTargetOf.get() != nullptr)
76 {
77 // Can't be a target and have sources.
78 ASSERT(mSourcesOf.empty());
79
Jamie Madill4928b7c2017-06-20 12:57:39 -040080 ANGLE_TRY(mTargetOf->orphanSibling(context, this));
Geoff Lang9d05b932018-07-27 15:47:18 -040081 mTargetOf.set(DisplayFromContext(context), nullptr);
Geoff Langa8406172015-07-21 16:53:39 -040082 }
83 else
84 {
Geoff Lang9d05b932018-07-27 15:47:18 -040085 for (Image *sourceImage : mSourcesOf)
Geoff Langa8406172015-07-21 16:53:39 -040086 {
Jamie Madill4928b7c2017-06-20 12:57:39 -040087 ANGLE_TRY(sourceImage->orphanSibling(context, this));
Geoff Langa8406172015-07-21 16:53:39 -040088 }
89 mSourcesOf.clear();
90 }
91
Jamie Madill7c985f52018-11-29 18:16:17 -050092 return angle::Result::Continue;
Geoff Langa8406172015-07-21 16:53:39 -040093}
94
95void ImageSibling::addImageSource(egl::Image *imageSource)
96{
97 ASSERT(imageSource != nullptr);
98 mSourcesOf.insert(imageSource);
99}
100
101void ImageSibling::removeImageSource(egl::Image *imageSource)
102{
103 ASSERT(mSourcesOf.find(imageSource) != mSourcesOf.end());
104 mSourcesOf.erase(imageSource);
105}
106
Jamie Madill05b35b22017-10-03 09:01:44 -0400107bool ImageSibling::isEGLImageTarget() const
108{
109 return (mTargetOf.get() != nullptr);
110}
111
112gl::InitState ImageSibling::sourceEGLImageInitState() const
113{
114 ASSERT(isEGLImageTarget());
115 return mTargetOf->sourceInitState();
116}
117
118void ImageSibling::setSourceEGLImageInitState(gl::InitState initState) const
119{
120 ASSERT(isEGLImageTarget());
121 mTargetOf->setInitState(initState);
122}
123
Yuly Novikov2eb54072018-08-22 16:41:26 -0400124bool ImageSibling::isRenderable(const gl::Context *context,
125 GLenum binding,
126 const gl::ImageIndex &imageIndex) const
127{
128 ASSERT(isEGLImageTarget());
129 return mTargetOf->isRenderable(context);
130}
131
Geoff Langc3ee7ec2018-09-21 16:15:03 -0400132ExternalImageSibling::ExternalImageSibling(rx::EGLImplFactory *factory,
133 const gl::Context *context,
134 EGLenum target,
135 EGLClientBuffer buffer,
136 const AttributeMap &attribs)
137 : mImplementation(factory->createExternalImageSibling(context, target, buffer, attribs))
Jamie Madillb980c562018-11-27 11:34:27 -0500138{}
Geoff Langc3ee7ec2018-09-21 16:15:03 -0400139
Jamie Madillab2bfa82019-01-15 19:06:47 -0500140ExternalImageSibling::~ExternalImageSibling() = default;
141
Geoff Langc3ee7ec2018-09-21 16:15:03 -0400142gl::Extents ExternalImageSibling::getAttachmentSize(const gl::ImageIndex &imageIndex) const
143{
144 return mImplementation->getSize();
145}
146
147gl::Format ExternalImageSibling::getAttachmentFormat(GLenum binding,
148 const gl::ImageIndex &imageIndex) const
149{
150 return mImplementation->getFormat();
151}
152
153GLsizei ExternalImageSibling::getAttachmentSamples(const gl::ImageIndex &imageIndex) const
154{
155 return mImplementation->getSamples();
156}
157
158bool ExternalImageSibling::isRenderable(const gl::Context *context,
159 GLenum binding,
160 const gl::ImageIndex &imageIndex) const
161{
162 return mImplementation->isRenderable(context);
163}
164
165bool ExternalImageSibling::isTextureable(const gl::Context *context) const
166{
167 return mImplementation->isTexturable(context);
168}
169
Jamie Madillb980c562018-11-27 11:34:27 -0500170void ExternalImageSibling::onAttach(const gl::Context *context) {}
Geoff Langc3ee7ec2018-09-21 16:15:03 -0400171
Jamie Madillb980c562018-11-27 11:34:27 -0500172void ExternalImageSibling::onDetach(const gl::Context *context) {}
Geoff Langc3ee7ec2018-09-21 16:15:03 -0400173
174GLuint ExternalImageSibling::getId() const
175{
176 UNREACHABLE();
177 return 0;
178}
179
180gl::InitState ExternalImageSibling::initState(const gl::ImageIndex &imageIndex) const
181{
182 return gl::InitState::Initialized;
183}
184
185void ExternalImageSibling::setInitState(const gl::ImageIndex &imageIndex, gl::InitState initState)
Jamie Madillb980c562018-11-27 11:34:27 -0500186{}
Geoff Langc3ee7ec2018-09-21 16:15:03 -0400187
188rx::ExternalImageSiblingImpl *ExternalImageSibling::getImplementation() const
189{
190 return mImplementation.get();
191}
192
193rx::FramebufferAttachmentObjectImpl *ExternalImageSibling::getAttachmentImpl() const
194{
195 return mImplementation.get();
196}
197
Jamie Madill76b8f462017-04-21 12:23:40 -0400198ImageState::ImageState(EGLenum target, ImageSibling *buffer, const AttributeMap &attribs)
Geoff Lang0bc81b62018-07-30 13:34:50 -0400199 : label(nullptr),
Geoff Langfe59f6b2019-01-16 09:34:30 -0500200 target(target),
Geoff Lang0bc81b62018-07-30 13:34:50 -0400201 imageIndex(GetImageIndex(target, attribs)),
202 source(buffer),
203 targets(),
204 format(buffer->getAttachmentFormat(GL_NONE, imageIndex)),
205 size(buffer->getAttachmentSize(imageIndex)),
Yuly Novikov2eb54072018-08-22 16:41:26 -0400206 samples(buffer->getAttachmentSamples(imageIndex)),
207 sourceType(target)
Jamie Madillb980c562018-11-27 11:34:27 -0500208{}
Jamie Madill76b8f462017-04-21 12:23:40 -0400209
Jamie Madillb980c562018-11-27 11:34:27 -0500210ImageState::~ImageState() {}
Jamie Madillacf2f3a2017-11-21 19:22:44 -0500211
Jamie Madill76b8f462017-04-21 12:23:40 -0400212Image::Image(rx::EGLImplFactory *factory,
Geoff Langcd7cd2a2018-07-19 11:25:54 -0400213 const gl::Context *context,
Jamie Madill76b8f462017-04-21 12:23:40 -0400214 EGLenum target,
215 ImageSibling *buffer,
216 const AttributeMap &attribs)
Geoff Lang9d05b932018-07-27 15:47:18 -0400217 : mState(target, buffer, attribs),
Geoff Langcd7cd2a2018-07-19 11:25:54 -0400218 mImplementation(factory->createImage(mState, context, target, attribs)),
Jamie Madill05b35b22017-10-03 09:01:44 -0400219 mOrphanedAndNeedsInit(false)
Geoff Langa8406172015-07-21 16:53:39 -0400220{
221 ASSERT(mImplementation != nullptr);
222 ASSERT(buffer != nullptr);
223
Jamie Madill76b8f462017-04-21 12:23:40 -0400224 mState.source->addImageSource(this);
Geoff Langa8406172015-07-21 16:53:39 -0400225}
226
Jamie Madill1c7f08c2018-10-10 16:13:02 -0400227void Image::onDestroy(const Display *display)
Geoff Langa8406172015-07-21 16:53:39 -0400228{
Geoff Langa8406172015-07-21 16:53:39 -0400229 // All targets should hold a ref to the egl image and it should not be deleted until there are
230 // no siblings left.
Jamie Madill76b8f462017-04-21 12:23:40 -0400231 ASSERT(mState.targets.empty());
Geoff Langa8406172015-07-21 16:53:39 -0400232
233 // Tell the source that it is no longer used by this image
Geoff Lang9d05b932018-07-27 15:47:18 -0400234 if (mState.source != nullptr)
Geoff Langa8406172015-07-21 16:53:39 -0400235 {
Jamie Madill76b8f462017-04-21 12:23:40 -0400236 mState.source->removeImageSource(this);
Geoff Langc3ee7ec2018-09-21 16:15:03 -0400237
238 // If the source is an external object, delete it
239 if (IsExternalImageTarget(mState.sourceType))
240 {
241 delete mState.source;
242 }
243
Geoff Lang9d05b932018-07-27 15:47:18 -0400244 mState.source = nullptr;
Geoff Langa8406172015-07-21 16:53:39 -0400245 }
Geoff Langfe59f6b2019-01-16 09:34:30 -0500246
247 mImplementation->onDestroy(display);
Geoff Langa8406172015-07-21 16:53:39 -0400248}
249
Jamie Madill4928b7c2017-06-20 12:57:39 -0400250Image::~Image()
251{
Jamie Madill71c88b32017-09-14 22:20:29 -0400252 SafeDelete(mImplementation);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400253}
254
Geoff Lang75359662018-04-11 01:42:27 -0400255void Image::setLabel(EGLLabelKHR label)
256{
257 mState.label = label;
258}
259
260EGLLabelKHR Image::getLabel() const
261{
262 return mState.label;
263}
264
Geoff Langa8406172015-07-21 16:53:39 -0400265void Image::addTargetSibling(ImageSibling *sibling)
266{
Jamie Madill76b8f462017-04-21 12:23:40 -0400267 mState.targets.insert(sibling);
Geoff Langa8406172015-07-21 16:53:39 -0400268}
269
Jamie Madill666818e2018-11-14 09:54:33 -0500270angle::Result Image::orphanSibling(const gl::Context *context, ImageSibling *sibling)
Geoff Langa8406172015-07-21 16:53:39 -0400271{
Geoff Lang9d05b932018-07-27 15:47:18 -0400272 ASSERT(sibling != nullptr);
273
Geoff Langa8406172015-07-21 16:53:39 -0400274 // notify impl
Jamie Madill4928b7c2017-06-20 12:57:39 -0400275 ANGLE_TRY(mImplementation->orphan(context, sibling));
Geoff Langa8406172015-07-21 16:53:39 -0400276
Geoff Lang9d05b932018-07-27 15:47:18 -0400277 if (mState.source == sibling)
Geoff Langa8406172015-07-21 16:53:39 -0400278 {
Geoff Langc3ee7ec2018-09-21 16:15:03 -0400279 // The external source of an image cannot be redefined so it cannot be orpahend.
280 ASSERT(!IsExternalImageTarget(mState.sourceType));
281
Geoff Langa8406172015-07-21 16:53:39 -0400282 // If the sibling is the source, it cannot be a target.
Jamie Madill76b8f462017-04-21 12:23:40 -0400283 ASSERT(mState.targets.find(sibling) == mState.targets.end());
Geoff Lang9d05b932018-07-27 15:47:18 -0400284 mState.source = nullptr;
Jamie Madill05b35b22017-10-03 09:01:44 -0400285 mOrphanedAndNeedsInit =
286 (sibling->initState(mState.imageIndex) == gl::InitState::MayNeedInit);
Geoff Langa8406172015-07-21 16:53:39 -0400287 }
288 else
289 {
Jamie Madill76b8f462017-04-21 12:23:40 -0400290 mState.targets.erase(sibling);
Geoff Langa8406172015-07-21 16:53:39 -0400291 }
292
Jamie Madill7c985f52018-11-29 18:16:17 -0500293 return angle::Result::Continue;
Geoff Langa8406172015-07-21 16:53:39 -0400294}
295
Geoff Lang0bc81b62018-07-30 13:34:50 -0400296const gl::Format &Image::getFormat() const
Geoff Langa8406172015-07-21 16:53:39 -0400297{
Geoff Lang0bc81b62018-07-30 13:34:50 -0400298 return mState.format;
Geoff Langa8406172015-07-21 16:53:39 -0400299}
300
Yuly Novikov2eb54072018-08-22 16:41:26 -0400301bool Image::isRenderable(const gl::Context *context) const
302{
303 if (IsTextureTarget(mState.sourceType))
304 {
305 return mState.format.info->textureAttachmentSupport(context->getClientVersion(),
306 context->getExtensions());
307 }
Geoff Langc3ee7ec2018-09-21 16:15:03 -0400308 else if (IsRenderbufferTarget(mState.sourceType))
Yuly Novikov2eb54072018-08-22 16:41:26 -0400309 {
310 return mState.format.info->renderbufferSupport(context->getClientVersion(),
311 context->getExtensions());
312 }
Geoff Langc3ee7ec2018-09-21 16:15:03 -0400313 else if (IsExternalImageTarget(mState.sourceType))
314 {
315 ASSERT(mState.source != nullptr);
316 return mState.source->isRenderable(context, GL_NONE, gl::ImageIndex());
317 }
Yuly Novikov2eb54072018-08-22 16:41:26 -0400318
319 UNREACHABLE();
320 return false;
321}
322
323bool Image::isTexturable(const gl::Context *context) const
324{
325 if (IsTextureTarget(mState.sourceType))
326 {
327 return mState.format.info->textureSupport(context->getClientVersion(),
328 context->getExtensions());
329 }
Geoff Langc3ee7ec2018-09-21 16:15:03 -0400330 else if (IsRenderbufferTarget(mState.sourceType))
Yuly Novikov2eb54072018-08-22 16:41:26 -0400331 {
332 return true;
333 }
Geoff Langc3ee7ec2018-09-21 16:15:03 -0400334 else if (IsExternalImageTarget(mState.sourceType))
335 {
336 ASSERT(mState.source != nullptr);
337 return rx::GetAs<ExternalImageSibling>(mState.source)->isTextureable(context);
338 }
Yuly Novikov2eb54072018-08-22 16:41:26 -0400339
340 UNREACHABLE();
341 return false;
342}
343
Geoff Langa8406172015-07-21 16:53:39 -0400344size_t Image::getWidth() const
345{
Geoff Lang0bc81b62018-07-30 13:34:50 -0400346 return mState.size.width;
Geoff Langa8406172015-07-21 16:53:39 -0400347}
348
349size_t Image::getHeight() const
350{
Geoff Lang0bc81b62018-07-30 13:34:50 -0400351 return mState.size.height;
Geoff Langa8406172015-07-21 16:53:39 -0400352}
353
354size_t Image::getSamples() const
355{
Geoff Lang0bc81b62018-07-30 13:34:50 -0400356 return mState.samples;
Geoff Langa8406172015-07-21 16:53:39 -0400357}
358
Jamie Madill76b8f462017-04-21 12:23:40 -0400359rx::ImageImpl *Image::getImplementation() const
Geoff Langa8406172015-07-21 16:53:39 -0400360{
361 return mImplementation;
362}
363
Geoff Langcd7cd2a2018-07-19 11:25:54 -0400364Error Image::initialize(const Display *display)
Geoff Langa8406172015-07-21 16:53:39 -0400365{
Geoff Langcd7cd2a2018-07-19 11:25:54 -0400366 return mImplementation->initialize(display);
Geoff Langa8406172015-07-21 16:53:39 -0400367}
Jamie Madill76b8f462017-04-21 12:23:40 -0400368
Jamie Madill05b35b22017-10-03 09:01:44 -0400369bool Image::orphaned() const
370{
Geoff Lang9d05b932018-07-27 15:47:18 -0400371 return (mState.source == nullptr);
Jamie Madill05b35b22017-10-03 09:01:44 -0400372}
373
374gl::InitState Image::sourceInitState() const
375{
376 if (orphaned())
377 {
378 return mOrphanedAndNeedsInit ? gl::InitState::MayNeedInit : gl::InitState::Initialized;
379 }
380
381 return mState.source->initState(mState.imageIndex);
382}
383
384void Image::setInitState(gl::InitState initState)
385{
386 if (orphaned())
387 {
388 mOrphanedAndNeedsInit = false;
389 }
390
391 return mState.source->setInitState(mState.imageIndex, initState);
392}
393
Jamie Madilla3944d42016-07-22 22:13:26 -0400394} // namespace egl