blob: 8ddaddd3b7df47d0aa64f13a9cf087def3e1a082 [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 Madill666818e2018-11-14 09:54:33 -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
140gl::Extents ExternalImageSibling::getAttachmentSize(const gl::ImageIndex &imageIndex) const
141{
142 return mImplementation->getSize();
143}
144
145gl::Format ExternalImageSibling::getAttachmentFormat(GLenum binding,
146 const gl::ImageIndex &imageIndex) const
147{
148 return mImplementation->getFormat();
149}
150
151GLsizei ExternalImageSibling::getAttachmentSamples(const gl::ImageIndex &imageIndex) const
152{
153 return mImplementation->getSamples();
154}
155
156bool ExternalImageSibling::isRenderable(const gl::Context *context,
157 GLenum binding,
158 const gl::ImageIndex &imageIndex) const
159{
160 return mImplementation->isRenderable(context);
161}
162
163bool ExternalImageSibling::isTextureable(const gl::Context *context) const
164{
165 return mImplementation->isTexturable(context);
166}
167
Jamie Madillb980c562018-11-27 11:34:27 -0500168void ExternalImageSibling::onAttach(const gl::Context *context) {}
Geoff Langc3ee7ec2018-09-21 16:15:03 -0400169
Jamie Madillb980c562018-11-27 11:34:27 -0500170void ExternalImageSibling::onDetach(const gl::Context *context) {}
Geoff Langc3ee7ec2018-09-21 16:15:03 -0400171
172GLuint ExternalImageSibling::getId() const
173{
174 UNREACHABLE();
175 return 0;
176}
177
178gl::InitState ExternalImageSibling::initState(const gl::ImageIndex &imageIndex) const
179{
180 return gl::InitState::Initialized;
181}
182
183void ExternalImageSibling::setInitState(const gl::ImageIndex &imageIndex, gl::InitState initState)
Jamie Madillb980c562018-11-27 11:34:27 -0500184{}
Geoff Langc3ee7ec2018-09-21 16:15:03 -0400185
186rx::ExternalImageSiblingImpl *ExternalImageSibling::getImplementation() const
187{
188 return mImplementation.get();
189}
190
191rx::FramebufferAttachmentObjectImpl *ExternalImageSibling::getAttachmentImpl() const
192{
193 return mImplementation.get();
194}
195
Jamie Madill76b8f462017-04-21 12:23:40 -0400196ImageState::ImageState(EGLenum target, ImageSibling *buffer, const AttributeMap &attribs)
Geoff Lang0bc81b62018-07-30 13:34:50 -0400197 : label(nullptr),
198 imageIndex(GetImageIndex(target, attribs)),
199 source(buffer),
200 targets(),
201 format(buffer->getAttachmentFormat(GL_NONE, imageIndex)),
202 size(buffer->getAttachmentSize(imageIndex)),
Yuly Novikov2eb54072018-08-22 16:41:26 -0400203 samples(buffer->getAttachmentSamples(imageIndex)),
204 sourceType(target)
Jamie Madillb980c562018-11-27 11:34:27 -0500205{}
Jamie Madill76b8f462017-04-21 12:23:40 -0400206
Jamie Madillb980c562018-11-27 11:34:27 -0500207ImageState::~ImageState() {}
Jamie Madillacf2f3a2017-11-21 19:22:44 -0500208
Jamie Madill76b8f462017-04-21 12:23:40 -0400209Image::Image(rx::EGLImplFactory *factory,
Geoff Langcd7cd2a2018-07-19 11:25:54 -0400210 const gl::Context *context,
Jamie Madill76b8f462017-04-21 12:23:40 -0400211 EGLenum target,
212 ImageSibling *buffer,
213 const AttributeMap &attribs)
Geoff Lang9d05b932018-07-27 15:47:18 -0400214 : mState(target, buffer, attribs),
Geoff Langcd7cd2a2018-07-19 11:25:54 -0400215 mImplementation(factory->createImage(mState, context, target, attribs)),
Jamie Madill05b35b22017-10-03 09:01:44 -0400216 mOrphanedAndNeedsInit(false)
Geoff Langa8406172015-07-21 16:53:39 -0400217{
218 ASSERT(mImplementation != nullptr);
219 ASSERT(buffer != nullptr);
220
Jamie Madill76b8f462017-04-21 12:23:40 -0400221 mState.source->addImageSource(this);
Geoff Langa8406172015-07-21 16:53:39 -0400222}
223
Jamie Madill1c7f08c2018-10-10 16:13:02 -0400224void Image::onDestroy(const Display *display)
Geoff Langa8406172015-07-21 16:53:39 -0400225{
Geoff Langa8406172015-07-21 16:53:39 -0400226 // All targets should hold a ref to the egl image and it should not be deleted until there are
227 // no siblings left.
Jamie Madill76b8f462017-04-21 12:23:40 -0400228 ASSERT(mState.targets.empty());
Geoff Langa8406172015-07-21 16:53:39 -0400229
230 // Tell the source that it is no longer used by this image
Geoff Lang9d05b932018-07-27 15:47:18 -0400231 if (mState.source != nullptr)
Geoff Langa8406172015-07-21 16:53:39 -0400232 {
Jamie Madill76b8f462017-04-21 12:23:40 -0400233 mState.source->removeImageSource(this);
Geoff Langc3ee7ec2018-09-21 16:15:03 -0400234
235 // If the source is an external object, delete it
236 if (IsExternalImageTarget(mState.sourceType))
237 {
238 delete mState.source;
239 }
240
Geoff Lang9d05b932018-07-27 15:47:18 -0400241 mState.source = nullptr;
Geoff Langa8406172015-07-21 16:53:39 -0400242 }
243}
244
Jamie Madill4928b7c2017-06-20 12:57:39 -0400245Image::~Image()
246{
Jamie Madill71c88b32017-09-14 22:20:29 -0400247 SafeDelete(mImplementation);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400248}
249
Geoff Lang75359662018-04-11 01:42:27 -0400250void Image::setLabel(EGLLabelKHR label)
251{
252 mState.label = label;
253}
254
255EGLLabelKHR Image::getLabel() const
256{
257 return mState.label;
258}
259
Geoff Langa8406172015-07-21 16:53:39 -0400260void Image::addTargetSibling(ImageSibling *sibling)
261{
Jamie Madill76b8f462017-04-21 12:23:40 -0400262 mState.targets.insert(sibling);
Geoff Langa8406172015-07-21 16:53:39 -0400263}
264
Jamie Madill666818e2018-11-14 09:54:33 -0500265angle::Result Image::orphanSibling(const gl::Context *context, ImageSibling *sibling)
Geoff Langa8406172015-07-21 16:53:39 -0400266{
Geoff Lang9d05b932018-07-27 15:47:18 -0400267 ASSERT(sibling != nullptr);
268
Geoff Langa8406172015-07-21 16:53:39 -0400269 // notify impl
Jamie Madill4928b7c2017-06-20 12:57:39 -0400270 ANGLE_TRY(mImplementation->orphan(context, sibling));
Geoff Langa8406172015-07-21 16:53:39 -0400271
Geoff Lang9d05b932018-07-27 15:47:18 -0400272 if (mState.source == sibling)
Geoff Langa8406172015-07-21 16:53:39 -0400273 {
Geoff Langc3ee7ec2018-09-21 16:15:03 -0400274 // The external source of an image cannot be redefined so it cannot be orpahend.
275 ASSERT(!IsExternalImageTarget(mState.sourceType));
276
Geoff Langa8406172015-07-21 16:53:39 -0400277 // If the sibling is the source, it cannot be a target.
Jamie Madill76b8f462017-04-21 12:23:40 -0400278 ASSERT(mState.targets.find(sibling) == mState.targets.end());
Geoff Lang9d05b932018-07-27 15:47:18 -0400279 mState.source = nullptr;
Jamie Madill05b35b22017-10-03 09:01:44 -0400280 mOrphanedAndNeedsInit =
281 (sibling->initState(mState.imageIndex) == gl::InitState::MayNeedInit);
Geoff Langa8406172015-07-21 16:53:39 -0400282 }
283 else
284 {
Jamie Madill76b8f462017-04-21 12:23:40 -0400285 mState.targets.erase(sibling);
Geoff Langa8406172015-07-21 16:53:39 -0400286 }
287
Jamie Madill666818e2018-11-14 09:54:33 -0500288 return angle::Result::Continue();
Geoff Langa8406172015-07-21 16:53:39 -0400289}
290
Geoff Lang0bc81b62018-07-30 13:34:50 -0400291const gl::Format &Image::getFormat() const
Geoff Langa8406172015-07-21 16:53:39 -0400292{
Geoff Lang0bc81b62018-07-30 13:34:50 -0400293 return mState.format;
Geoff Langa8406172015-07-21 16:53:39 -0400294}
295
Yuly Novikov2eb54072018-08-22 16:41:26 -0400296bool Image::isRenderable(const gl::Context *context) const
297{
298 if (IsTextureTarget(mState.sourceType))
299 {
300 return mState.format.info->textureAttachmentSupport(context->getClientVersion(),
301 context->getExtensions());
302 }
Geoff Langc3ee7ec2018-09-21 16:15:03 -0400303 else if (IsRenderbufferTarget(mState.sourceType))
Yuly Novikov2eb54072018-08-22 16:41:26 -0400304 {
305 return mState.format.info->renderbufferSupport(context->getClientVersion(),
306 context->getExtensions());
307 }
Geoff Langc3ee7ec2018-09-21 16:15:03 -0400308 else if (IsExternalImageTarget(mState.sourceType))
309 {
310 ASSERT(mState.source != nullptr);
311 return mState.source->isRenderable(context, GL_NONE, gl::ImageIndex());
312 }
Yuly Novikov2eb54072018-08-22 16:41:26 -0400313
314 UNREACHABLE();
315 return false;
316}
317
318bool Image::isTexturable(const gl::Context *context) const
319{
320 if (IsTextureTarget(mState.sourceType))
321 {
322 return mState.format.info->textureSupport(context->getClientVersion(),
323 context->getExtensions());
324 }
Geoff Langc3ee7ec2018-09-21 16:15:03 -0400325 else if (IsRenderbufferTarget(mState.sourceType))
Yuly Novikov2eb54072018-08-22 16:41:26 -0400326 {
327 return true;
328 }
Geoff Langc3ee7ec2018-09-21 16:15:03 -0400329 else if (IsExternalImageTarget(mState.sourceType))
330 {
331 ASSERT(mState.source != nullptr);
332 return rx::GetAs<ExternalImageSibling>(mState.source)->isTextureable(context);
333 }
Yuly Novikov2eb54072018-08-22 16:41:26 -0400334
335 UNREACHABLE();
336 return false;
337}
338
Geoff Langa8406172015-07-21 16:53:39 -0400339size_t Image::getWidth() const
340{
Geoff Lang0bc81b62018-07-30 13:34:50 -0400341 return mState.size.width;
Geoff Langa8406172015-07-21 16:53:39 -0400342}
343
344size_t Image::getHeight() const
345{
Geoff Lang0bc81b62018-07-30 13:34:50 -0400346 return mState.size.height;
Geoff Langa8406172015-07-21 16:53:39 -0400347}
348
349size_t Image::getSamples() const
350{
Geoff Lang0bc81b62018-07-30 13:34:50 -0400351 return mState.samples;
Geoff Langa8406172015-07-21 16:53:39 -0400352}
353
Jamie Madill76b8f462017-04-21 12:23:40 -0400354rx::ImageImpl *Image::getImplementation() const
Geoff Langa8406172015-07-21 16:53:39 -0400355{
356 return mImplementation;
357}
358
Geoff Langcd7cd2a2018-07-19 11:25:54 -0400359Error Image::initialize(const Display *display)
Geoff Langa8406172015-07-21 16:53:39 -0400360{
Geoff Langcd7cd2a2018-07-19 11:25:54 -0400361 return mImplementation->initialize(display);
Geoff Langa8406172015-07-21 16:53:39 -0400362}
Jamie Madill76b8f462017-04-21 12:23:40 -0400363
Jamie Madill05b35b22017-10-03 09:01:44 -0400364bool Image::orphaned() const
365{
Geoff Lang9d05b932018-07-27 15:47:18 -0400366 return (mState.source == nullptr);
Jamie Madill05b35b22017-10-03 09:01:44 -0400367}
368
369gl::InitState Image::sourceInitState() const
370{
371 if (orphaned())
372 {
373 return mOrphanedAndNeedsInit ? gl::InitState::MayNeedInit : gl::InitState::Initialized;
374 }
375
376 return mState.source->initState(mState.imageIndex);
377}
378
379void Image::setInitState(gl::InitState initState)
380{
381 if (orphaned())
382 {
383 mOrphanedAndNeedsInit = false;
384 }
385
386 return mState.source->setInitState(mState.imageIndex, initState);
387}
388
Jamie Madilla3944d42016-07-22 22:13:26 -0400389} // namespace egl