blob: 69c7cb29fc7c15e94cddaa71211f3a53c5789cbd [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
Jamie Madill76b8f462017-04-21 12:23:40 -0400126ImageState::ImageState(EGLenum target, ImageSibling *buffer, const AttributeMap &attribs)
Geoff Lang0bc81b62018-07-30 13:34:50 -0400127 : label(nullptr),
128 imageIndex(GetImageIndex(target, attribs)),
129 source(buffer),
130 targets(),
131 format(buffer->getAttachmentFormat(GL_NONE, imageIndex)),
132 size(buffer->getAttachmentSize(imageIndex)),
133 samples(buffer->getAttachmentSamples(imageIndex))
Jamie Madill76b8f462017-04-21 12:23:40 -0400134{
Jamie Madill76b8f462017-04-21 12:23:40 -0400135}
136
Jamie Madillacf2f3a2017-11-21 19:22:44 -0500137ImageState::~ImageState()
138{
139}
140
Jamie Madill76b8f462017-04-21 12:23:40 -0400141Image::Image(rx::EGLImplFactory *factory,
Geoff Langcd7cd2a2018-07-19 11:25:54 -0400142 const gl::Context *context,
Jamie Madill76b8f462017-04-21 12:23:40 -0400143 EGLenum target,
144 ImageSibling *buffer,
145 const AttributeMap &attribs)
Geoff Lang9d05b932018-07-27 15:47:18 -0400146 : mState(target, buffer, attribs),
Geoff Langcd7cd2a2018-07-19 11:25:54 -0400147 mImplementation(factory->createImage(mState, context, target, attribs)),
Jamie Madill05b35b22017-10-03 09:01:44 -0400148 mOrphanedAndNeedsInit(false)
Geoff Langa8406172015-07-21 16:53:39 -0400149{
150 ASSERT(mImplementation != nullptr);
151 ASSERT(buffer != nullptr);
152
Jamie Madill76b8f462017-04-21 12:23:40 -0400153 mState.source->addImageSource(this);
Geoff Langa8406172015-07-21 16:53:39 -0400154}
155
Geoff Lang9d05b932018-07-27 15:47:18 -0400156Error Image::onDestroy(const Display *display)
Geoff Langa8406172015-07-21 16:53:39 -0400157{
Geoff Langa8406172015-07-21 16:53:39 -0400158 // All targets should hold a ref to the egl image and it should not be deleted until there are
159 // no siblings left.
Jamie Madill76b8f462017-04-21 12:23:40 -0400160 ASSERT(mState.targets.empty());
Geoff Langa8406172015-07-21 16:53:39 -0400161
162 // Tell the source that it is no longer used by this image
Geoff Lang9d05b932018-07-27 15:47:18 -0400163 if (mState.source != nullptr)
Geoff Langa8406172015-07-21 16:53:39 -0400164 {
Jamie Madill76b8f462017-04-21 12:23:40 -0400165 mState.source->removeImageSource(this);
Geoff Lang9d05b932018-07-27 15:47:18 -0400166 mState.source = nullptr;
Geoff Langa8406172015-07-21 16:53:39 -0400167 }
Geoff Lang9d05b932018-07-27 15:47:18 -0400168
169 return NoError();
Geoff Langa8406172015-07-21 16:53:39 -0400170}
171
Jamie Madill4928b7c2017-06-20 12:57:39 -0400172Image::~Image()
173{
Jamie Madill71c88b32017-09-14 22:20:29 -0400174 SafeDelete(mImplementation);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400175}
176
Geoff Lang75359662018-04-11 01:42:27 -0400177void Image::setLabel(EGLLabelKHR label)
178{
179 mState.label = label;
180}
181
182EGLLabelKHR Image::getLabel() const
183{
184 return mState.label;
185}
186
Geoff Langa8406172015-07-21 16:53:39 -0400187void Image::addTargetSibling(ImageSibling *sibling)
188{
Jamie Madill76b8f462017-04-21 12:23:40 -0400189 mState.targets.insert(sibling);
Geoff Langa8406172015-07-21 16:53:39 -0400190}
191
Jamie Madill4928b7c2017-06-20 12:57:39 -0400192gl::Error Image::orphanSibling(const gl::Context *context, ImageSibling *sibling)
Geoff Langa8406172015-07-21 16:53:39 -0400193{
Geoff Lang9d05b932018-07-27 15:47:18 -0400194 ASSERT(sibling != nullptr);
195
Geoff Langa8406172015-07-21 16:53:39 -0400196 // notify impl
Jamie Madill4928b7c2017-06-20 12:57:39 -0400197 ANGLE_TRY(mImplementation->orphan(context, sibling));
Geoff Langa8406172015-07-21 16:53:39 -0400198
Geoff Lang9d05b932018-07-27 15:47:18 -0400199 if (mState.source == sibling)
Geoff Langa8406172015-07-21 16:53:39 -0400200 {
201 // If the sibling is the source, it cannot be a target.
Jamie Madill76b8f462017-04-21 12:23:40 -0400202 ASSERT(mState.targets.find(sibling) == mState.targets.end());
Geoff Lang9d05b932018-07-27 15:47:18 -0400203 mState.source = nullptr;
Jamie Madill05b35b22017-10-03 09:01:44 -0400204 mOrphanedAndNeedsInit =
205 (sibling->initState(mState.imageIndex) == gl::InitState::MayNeedInit);
Geoff Langa8406172015-07-21 16:53:39 -0400206 }
207 else
208 {
Jamie Madill76b8f462017-04-21 12:23:40 -0400209 mState.targets.erase(sibling);
Geoff Langa8406172015-07-21 16:53:39 -0400210 }
211
Jamie Madill76b8f462017-04-21 12:23:40 -0400212 return gl::NoError();
Geoff Langa8406172015-07-21 16:53:39 -0400213}
214
Geoff Lang0bc81b62018-07-30 13:34:50 -0400215const gl::Format &Image::getFormat() const
Geoff Langa8406172015-07-21 16:53:39 -0400216{
Geoff Lang0bc81b62018-07-30 13:34:50 -0400217 return mState.format;
Geoff Langa8406172015-07-21 16:53:39 -0400218}
219
220size_t Image::getWidth() const
221{
Geoff Lang0bc81b62018-07-30 13:34:50 -0400222 return mState.size.width;
Geoff Langa8406172015-07-21 16:53:39 -0400223}
224
225size_t Image::getHeight() const
226{
Geoff Lang0bc81b62018-07-30 13:34:50 -0400227 return mState.size.height;
Geoff Langa8406172015-07-21 16:53:39 -0400228}
229
230size_t Image::getSamples() const
231{
Geoff Lang0bc81b62018-07-30 13:34:50 -0400232 return mState.samples;
Geoff Langa8406172015-07-21 16:53:39 -0400233}
234
Jamie Madill76b8f462017-04-21 12:23:40 -0400235rx::ImageImpl *Image::getImplementation() const
Geoff Langa8406172015-07-21 16:53:39 -0400236{
237 return mImplementation;
238}
239
Geoff Langcd7cd2a2018-07-19 11:25:54 -0400240Error Image::initialize(const Display *display)
Geoff Langa8406172015-07-21 16:53:39 -0400241{
Geoff Langcd7cd2a2018-07-19 11:25:54 -0400242 return mImplementation->initialize(display);
Geoff Langa8406172015-07-21 16:53:39 -0400243}
Jamie Madill76b8f462017-04-21 12:23:40 -0400244
Jamie Madill05b35b22017-10-03 09:01:44 -0400245bool Image::orphaned() const
246{
Geoff Lang9d05b932018-07-27 15:47:18 -0400247 return (mState.source == nullptr);
Jamie Madill05b35b22017-10-03 09:01:44 -0400248}
249
250gl::InitState Image::sourceInitState() const
251{
252 if (orphaned())
253 {
254 return mOrphanedAndNeedsInit ? gl::InitState::MayNeedInit : gl::InitState::Initialized;
255 }
256
257 return mState.source->initState(mState.imageIndex);
258}
259
260void Image::setInitState(gl::InitState initState)
261{
262 if (orphaned())
263 {
264 mOrphanedAndNeedsInit = false;
265 }
266
267 return mState.source->setInitState(mState.imageIndex, initState);
268}
269
Jamie Madilla3944d42016-07-22 22:13:26 -0400270} // namespace egl