blob: 5cbdf5a4ded23916053c896cb3677205856ead3f [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
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
Geoff Langc3ee7ec2018-09-21 16:15:03 -0400134ExternalImageSibling::ExternalImageSibling(rx::EGLImplFactory *factory,
135 const gl::Context *context,
136 EGLenum target,
137 EGLClientBuffer buffer,
138 const AttributeMap &attribs)
139 : mImplementation(factory->createExternalImageSibling(context, target, buffer, attribs))
140{
141}
142
143gl::Extents ExternalImageSibling::getAttachmentSize(const gl::ImageIndex &imageIndex) const
144{
145 return mImplementation->getSize();
146}
147
148gl::Format ExternalImageSibling::getAttachmentFormat(GLenum binding,
149 const gl::ImageIndex &imageIndex) const
150{
151 return mImplementation->getFormat();
152}
153
154GLsizei ExternalImageSibling::getAttachmentSamples(const gl::ImageIndex &imageIndex) const
155{
156 return mImplementation->getSamples();
157}
158
159bool ExternalImageSibling::isRenderable(const gl::Context *context,
160 GLenum binding,
161 const gl::ImageIndex &imageIndex) const
162{
163 return mImplementation->isRenderable(context);
164}
165
166bool ExternalImageSibling::isTextureable(const gl::Context *context) const
167{
168 return mImplementation->isTexturable(context);
169}
170
171void ExternalImageSibling::onAttach(const gl::Context *context)
172{
173}
174
175void ExternalImageSibling::onDetach(const gl::Context *context)
176{
177}
178
179GLuint ExternalImageSibling::getId() const
180{
181 UNREACHABLE();
182 return 0;
183}
184
185gl::InitState ExternalImageSibling::initState(const gl::ImageIndex &imageIndex) const
186{
187 return gl::InitState::Initialized;
188}
189
190void ExternalImageSibling::setInitState(const gl::ImageIndex &imageIndex, gl::InitState initState)
191{
192}
193
194rx::ExternalImageSiblingImpl *ExternalImageSibling::getImplementation() const
195{
196 return mImplementation.get();
197}
198
199rx::FramebufferAttachmentObjectImpl *ExternalImageSibling::getAttachmentImpl() const
200{
201 return mImplementation.get();
202}
203
Jamie Madill76b8f462017-04-21 12:23:40 -0400204ImageState::ImageState(EGLenum target, ImageSibling *buffer, const AttributeMap &attribs)
Geoff Lang0bc81b62018-07-30 13:34:50 -0400205 : label(nullptr),
206 imageIndex(GetImageIndex(target, attribs)),
207 source(buffer),
208 targets(),
209 format(buffer->getAttachmentFormat(GL_NONE, imageIndex)),
210 size(buffer->getAttachmentSize(imageIndex)),
Yuly Novikov2eb54072018-08-22 16:41:26 -0400211 samples(buffer->getAttachmentSamples(imageIndex)),
212 sourceType(target)
Jamie Madill76b8f462017-04-21 12:23:40 -0400213{
Jamie Madill76b8f462017-04-21 12:23:40 -0400214}
215
Jamie Madillacf2f3a2017-11-21 19:22:44 -0500216ImageState::~ImageState()
217{
218}
219
Jamie Madill76b8f462017-04-21 12:23:40 -0400220Image::Image(rx::EGLImplFactory *factory,
Geoff Langcd7cd2a2018-07-19 11:25:54 -0400221 const gl::Context *context,
Jamie Madill76b8f462017-04-21 12:23:40 -0400222 EGLenum target,
223 ImageSibling *buffer,
224 const AttributeMap &attribs)
Geoff Lang9d05b932018-07-27 15:47:18 -0400225 : mState(target, buffer, attribs),
Geoff Langcd7cd2a2018-07-19 11:25:54 -0400226 mImplementation(factory->createImage(mState, context, target, attribs)),
Jamie Madill05b35b22017-10-03 09:01:44 -0400227 mOrphanedAndNeedsInit(false)
Geoff Langa8406172015-07-21 16:53:39 -0400228{
229 ASSERT(mImplementation != nullptr);
230 ASSERT(buffer != nullptr);
231
Jamie Madill76b8f462017-04-21 12:23:40 -0400232 mState.source->addImageSource(this);
Geoff Langa8406172015-07-21 16:53:39 -0400233}
234
Jamie Madill1c7f08c2018-10-10 16:13:02 -0400235void Image::onDestroy(const Display *display)
Geoff Langa8406172015-07-21 16:53:39 -0400236{
Geoff Langa8406172015-07-21 16:53:39 -0400237 // All targets should hold a ref to the egl image and it should not be deleted until there are
238 // no siblings left.
Jamie Madill76b8f462017-04-21 12:23:40 -0400239 ASSERT(mState.targets.empty());
Geoff Langa8406172015-07-21 16:53:39 -0400240
241 // Tell the source that it is no longer used by this image
Geoff Lang9d05b932018-07-27 15:47:18 -0400242 if (mState.source != nullptr)
Geoff Langa8406172015-07-21 16:53:39 -0400243 {
Jamie Madill76b8f462017-04-21 12:23:40 -0400244 mState.source->removeImageSource(this);
Geoff Langc3ee7ec2018-09-21 16:15:03 -0400245
246 // If the source is an external object, delete it
247 if (IsExternalImageTarget(mState.sourceType))
248 {
249 delete mState.source;
250 }
251
Geoff Lang9d05b932018-07-27 15:47:18 -0400252 mState.source = nullptr;
Geoff Langa8406172015-07-21 16:53:39 -0400253 }
254}
255
Jamie Madill4928b7c2017-06-20 12:57:39 -0400256Image::~Image()
257{
Jamie Madill71c88b32017-09-14 22:20:29 -0400258 SafeDelete(mImplementation);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400259}
260
Geoff Lang75359662018-04-11 01:42:27 -0400261void Image::setLabel(EGLLabelKHR label)
262{
263 mState.label = label;
264}
265
266EGLLabelKHR Image::getLabel() const
267{
268 return mState.label;
269}
270
Geoff Langa8406172015-07-21 16:53:39 -0400271void Image::addTargetSibling(ImageSibling *sibling)
272{
Jamie Madill76b8f462017-04-21 12:23:40 -0400273 mState.targets.insert(sibling);
Geoff Langa8406172015-07-21 16:53:39 -0400274}
275
Jamie Madill4928b7c2017-06-20 12:57:39 -0400276gl::Error Image::orphanSibling(const gl::Context *context, ImageSibling *sibling)
Geoff Langa8406172015-07-21 16:53:39 -0400277{
Geoff Lang9d05b932018-07-27 15:47:18 -0400278 ASSERT(sibling != nullptr);
279
Geoff Langa8406172015-07-21 16:53:39 -0400280 // notify impl
Jamie Madill4928b7c2017-06-20 12:57:39 -0400281 ANGLE_TRY(mImplementation->orphan(context, sibling));
Geoff Langa8406172015-07-21 16:53:39 -0400282
Geoff Lang9d05b932018-07-27 15:47:18 -0400283 if (mState.source == sibling)
Geoff Langa8406172015-07-21 16:53:39 -0400284 {
Geoff Langc3ee7ec2018-09-21 16:15:03 -0400285 // The external source of an image cannot be redefined so it cannot be orpahend.
286 ASSERT(!IsExternalImageTarget(mState.sourceType));
287
Geoff Langa8406172015-07-21 16:53:39 -0400288 // If the sibling is the source, it cannot be a target.
Jamie Madill76b8f462017-04-21 12:23:40 -0400289 ASSERT(mState.targets.find(sibling) == mState.targets.end());
Geoff Lang9d05b932018-07-27 15:47:18 -0400290 mState.source = nullptr;
Jamie Madill05b35b22017-10-03 09:01:44 -0400291 mOrphanedAndNeedsInit =
292 (sibling->initState(mState.imageIndex) == gl::InitState::MayNeedInit);
Geoff Langa8406172015-07-21 16:53:39 -0400293 }
294 else
295 {
Jamie Madill76b8f462017-04-21 12:23:40 -0400296 mState.targets.erase(sibling);
Geoff Langa8406172015-07-21 16:53:39 -0400297 }
298
Jamie Madill76b8f462017-04-21 12:23:40 -0400299 return gl::NoError();
Geoff Langa8406172015-07-21 16:53:39 -0400300}
301
Geoff Lang0bc81b62018-07-30 13:34:50 -0400302const gl::Format &Image::getFormat() const
Geoff Langa8406172015-07-21 16:53:39 -0400303{
Geoff Lang0bc81b62018-07-30 13:34:50 -0400304 return mState.format;
Geoff Langa8406172015-07-21 16:53:39 -0400305}
306
Yuly Novikov2eb54072018-08-22 16:41:26 -0400307bool Image::isRenderable(const gl::Context *context) const
308{
309 if (IsTextureTarget(mState.sourceType))
310 {
311 return mState.format.info->textureAttachmentSupport(context->getClientVersion(),
312 context->getExtensions());
313 }
Geoff Langc3ee7ec2018-09-21 16:15:03 -0400314 else if (IsRenderbufferTarget(mState.sourceType))
Yuly Novikov2eb54072018-08-22 16:41:26 -0400315 {
316 return mState.format.info->renderbufferSupport(context->getClientVersion(),
317 context->getExtensions());
318 }
Geoff Langc3ee7ec2018-09-21 16:15:03 -0400319 else if (IsExternalImageTarget(mState.sourceType))
320 {
321 ASSERT(mState.source != nullptr);
322 return mState.source->isRenderable(context, GL_NONE, gl::ImageIndex());
323 }
Yuly Novikov2eb54072018-08-22 16:41:26 -0400324
325 UNREACHABLE();
326 return false;
327}
328
329bool Image::isTexturable(const gl::Context *context) const
330{
331 if (IsTextureTarget(mState.sourceType))
332 {
333 return mState.format.info->textureSupport(context->getClientVersion(),
334 context->getExtensions());
335 }
Geoff Langc3ee7ec2018-09-21 16:15:03 -0400336 else if (IsRenderbufferTarget(mState.sourceType))
Yuly Novikov2eb54072018-08-22 16:41:26 -0400337 {
338 return true;
339 }
Geoff Langc3ee7ec2018-09-21 16:15:03 -0400340 else if (IsExternalImageTarget(mState.sourceType))
341 {
342 ASSERT(mState.source != nullptr);
343 return rx::GetAs<ExternalImageSibling>(mState.source)->isTextureable(context);
344 }
Yuly Novikov2eb54072018-08-22 16:41:26 -0400345
346 UNREACHABLE();
347 return false;
348}
349
Geoff Langa8406172015-07-21 16:53:39 -0400350size_t Image::getWidth() const
351{
Geoff Lang0bc81b62018-07-30 13:34:50 -0400352 return mState.size.width;
Geoff Langa8406172015-07-21 16:53:39 -0400353}
354
355size_t Image::getHeight() const
356{
Geoff Lang0bc81b62018-07-30 13:34:50 -0400357 return mState.size.height;
Geoff Langa8406172015-07-21 16:53:39 -0400358}
359
360size_t Image::getSamples() const
361{
Geoff Lang0bc81b62018-07-30 13:34:50 -0400362 return mState.samples;
Geoff Langa8406172015-07-21 16:53:39 -0400363}
364
Jamie Madill76b8f462017-04-21 12:23:40 -0400365rx::ImageImpl *Image::getImplementation() const
Geoff Langa8406172015-07-21 16:53:39 -0400366{
367 return mImplementation;
368}
369
Geoff Langcd7cd2a2018-07-19 11:25:54 -0400370Error Image::initialize(const Display *display)
Geoff Langa8406172015-07-21 16:53:39 -0400371{
Geoff Langcd7cd2a2018-07-19 11:25:54 -0400372 return mImplementation->initialize(display);
Geoff Langa8406172015-07-21 16:53:39 -0400373}
Jamie Madill76b8f462017-04-21 12:23:40 -0400374
Jamie Madill05b35b22017-10-03 09:01:44 -0400375bool Image::orphaned() const
376{
Geoff Lang9d05b932018-07-27 15:47:18 -0400377 return (mState.source == nullptr);
Jamie Madill05b35b22017-10-03 09:01:44 -0400378}
379
380gl::InitState Image::sourceInitState() const
381{
382 if (orphaned())
383 {
384 return mOrphanedAndNeedsInit ? gl::InitState::MayNeedInit : gl::InitState::Initialized;
385 }
386
387 return mState.source->initState(mState.imageIndex);
388}
389
390void Image::setInitState(gl::InitState initState)
391{
392 if (orphaned())
393 {
394 mOrphanedAndNeedsInit = false;
395 }
396
397 return mState.source->setInitState(mState.imageIndex, initState);
398}
399
Jamie Madilla3944d42016-07-22 22:13:26 -0400400} // namespace egl