blob: bfdb9267cd426067ce4fb7857023e9cb9843ed9f [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"
13#include "libANGLE/angletypes.h"
Jamie Madilla3944d42016-07-22 22:13:26 -040014#include "libANGLE/formatutils.h"
Geoff Langa8406172015-07-21 16:53:39 -040015#include "libANGLE/Texture.h"
16#include "libANGLE/Renderbuffer.h"
Jamie Madill76b8f462017-04-21 12:23:40 -040017#include "libANGLE/renderer/EGLImplFactory.h"
Geoff Langa8406172015-07-21 16:53:39 -040018#include "libANGLE/renderer/ImageImpl.h"
19
20namespace egl
21{
Jamie Madill76b8f462017-04-21 12:23:40 -040022
23namespace
24{
25gl::ImageIndex GetImageIndex(EGLenum eglTarget, const egl::AttributeMap &attribs)
26{
27 if (eglTarget == EGL_GL_RENDERBUFFER)
28 {
Jamie Madillcc129372018-04-12 09:13:18 -040029 return gl::ImageIndex();
Jamie Madill76b8f462017-04-21 12:23:40 -040030 }
31
Corentin Wallezf0e89be2017-11-08 14:00:32 -080032 gl::TextureTarget target = egl_gl::EGLImageTargetToTextureTarget(eglTarget);
Jamie Madill76b8f462017-04-21 12:23:40 -040033 GLint mip = static_cast<GLint>(attribs.get(EGL_GL_TEXTURE_LEVEL_KHR, 0));
34 GLint layer = static_cast<GLint>(attribs.get(EGL_GL_TEXTURE_ZOFFSET_KHR, 0));
35
Corentin Wallezf0e89be2017-11-08 14:00:32 -080036 if (target == gl::TextureTarget::_3D)
Jamie Madill76b8f462017-04-21 12:23:40 -040037 {
38 return gl::ImageIndex::Make3D(mip, layer);
39 }
40 else
41 {
42 ASSERT(layer == 0);
Jamie Madillcc129372018-04-12 09:13:18 -040043 return gl::ImageIndex::MakeFromTarget(target, mip);
Jamie Madill76b8f462017-04-21 12:23:40 -040044 }
45}
46} // anonymous namespace
47
Jamie Madill05b35b22017-10-03 09:01:44 -040048ImageSibling::ImageSibling(GLuint id)
49 : RefCountObject(id), FramebufferAttachmentObject(), mSourcesOf(), mTargetOf()
Geoff Langa8406172015-07-21 16:53:39 -040050{
51}
52
53ImageSibling::~ImageSibling()
54{
55 // EGL images should hold a ref to their targets and siblings, a Texture should not be deletable
56 // while it is attached to an EGL image.
Jamie Madill4928b7c2017-06-20 12:57:39 -040057 // Child class should orphan images before destruction.
Geoff Langa8406172015-07-21 16:53:39 -040058 ASSERT(mSourcesOf.empty());
Jamie Madill4928b7c2017-06-20 12:57:39 -040059 ASSERT(mTargetOf.get() == nullptr);
Geoff Langa8406172015-07-21 16:53:39 -040060}
61
Jamie Madill4928b7c2017-06-20 12:57:39 -040062void ImageSibling::setTargetImage(const gl::Context *context, egl::Image *imageTarget)
Geoff Langa8406172015-07-21 16:53:39 -040063{
64 ASSERT(imageTarget != nullptr);
Jamie Madill4928b7c2017-06-20 12:57:39 -040065 mTargetOf.set(context, imageTarget);
Geoff Langa8406172015-07-21 16:53:39 -040066 imageTarget->addTargetSibling(this);
67}
68
Jamie Madill4928b7c2017-06-20 12:57:39 -040069gl::Error ImageSibling::orphanImages(const gl::Context *context)
Geoff Langa8406172015-07-21 16:53:39 -040070{
71 if (mTargetOf.get() != nullptr)
72 {
73 // Can't be a target and have sources.
74 ASSERT(mSourcesOf.empty());
75
Jamie Madill4928b7c2017-06-20 12:57:39 -040076 ANGLE_TRY(mTargetOf->orphanSibling(context, this));
77 mTargetOf.set(context, nullptr);
Geoff Langa8406172015-07-21 16:53:39 -040078 }
79 else
80 {
Jamie Madillacf2f3a2017-11-21 19:22:44 -050081 for (egl::Image *sourceImage : mSourcesOf)
Geoff Langa8406172015-07-21 16:53:39 -040082 {
Jamie Madill4928b7c2017-06-20 12:57:39 -040083 ANGLE_TRY(sourceImage->orphanSibling(context, this));
Geoff Langa8406172015-07-21 16:53:39 -040084 }
85 mSourcesOf.clear();
86 }
87
He Yunchaoacd18982017-01-04 10:46:42 +080088 return gl::NoError();
Geoff Langa8406172015-07-21 16:53:39 -040089}
90
91void ImageSibling::addImageSource(egl::Image *imageSource)
92{
93 ASSERT(imageSource != nullptr);
94 mSourcesOf.insert(imageSource);
95}
96
97void ImageSibling::removeImageSource(egl::Image *imageSource)
98{
99 ASSERT(mSourcesOf.find(imageSource) != mSourcesOf.end());
100 mSourcesOf.erase(imageSource);
101}
102
Jamie Madill05b35b22017-10-03 09:01:44 -0400103bool ImageSibling::isEGLImageTarget() const
104{
105 return (mTargetOf.get() != nullptr);
106}
107
108gl::InitState ImageSibling::sourceEGLImageInitState() const
109{
110 ASSERT(isEGLImageTarget());
111 return mTargetOf->sourceInitState();
112}
113
114void ImageSibling::setSourceEGLImageInitState(gl::InitState initState) const
115{
116 ASSERT(isEGLImageTarget());
117 mTargetOf->setInitState(initState);
118}
119
Jamie Madill76b8f462017-04-21 12:23:40 -0400120ImageState::ImageState(EGLenum target, ImageSibling *buffer, const AttributeMap &attribs)
Jamie Madill4928b7c2017-06-20 12:57:39 -0400121 : imageIndex(GetImageIndex(target, attribs)), source(buffer), targets()
Jamie Madill76b8f462017-04-21 12:23:40 -0400122{
Jamie Madill76b8f462017-04-21 12:23:40 -0400123}
124
Jamie Madillacf2f3a2017-11-21 19:22:44 -0500125ImageState::~ImageState()
126{
127}
128
Jamie Madill76b8f462017-04-21 12:23:40 -0400129Image::Image(rx::EGLImplFactory *factory,
130 EGLenum target,
131 ImageSibling *buffer,
132 const AttributeMap &attribs)
Geoff Langa8406172015-07-21 16:53:39 -0400133 : RefCountObject(0),
Jamie Madill76b8f462017-04-21 12:23:40 -0400134 mState(target, buffer, attribs),
Jamie Madill05b35b22017-10-03 09:01:44 -0400135 mImplementation(factory->createImage(mState, target, attribs)),
136 mOrphanedAndNeedsInit(false)
Geoff Langa8406172015-07-21 16:53:39 -0400137{
138 ASSERT(mImplementation != nullptr);
139 ASSERT(buffer != nullptr);
140
Jamie Madill76b8f462017-04-21 12:23:40 -0400141 mState.source->addImageSource(this);
Geoff Langa8406172015-07-21 16:53:39 -0400142}
143
Jamie Madill71c88b32017-09-14 22:20:29 -0400144gl::Error Image::onDestroy(const gl::Context *context)
Geoff Langa8406172015-07-21 16:53:39 -0400145{
Geoff Langa8406172015-07-21 16:53:39 -0400146 // All targets should hold a ref to the egl image and it should not be deleted until there are
147 // no siblings left.
Jamie Madill76b8f462017-04-21 12:23:40 -0400148 ASSERT(mState.targets.empty());
Geoff Langa8406172015-07-21 16:53:39 -0400149
150 // Tell the source that it is no longer used by this image
Jamie Madill76b8f462017-04-21 12:23:40 -0400151 if (mState.source.get() != nullptr)
Geoff Langa8406172015-07-21 16:53:39 -0400152 {
Jamie Madill76b8f462017-04-21 12:23:40 -0400153 mState.source->removeImageSource(this);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400154 mState.source.set(context, nullptr);
Geoff Langa8406172015-07-21 16:53:39 -0400155 }
Jamie Madill71c88b32017-09-14 22:20:29 -0400156 return gl::NoError();
Geoff Langa8406172015-07-21 16:53:39 -0400157}
158
Jamie Madill4928b7c2017-06-20 12:57:39 -0400159Image::~Image()
160{
Jamie Madill71c88b32017-09-14 22:20:29 -0400161 SafeDelete(mImplementation);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400162}
163
Geoff Langa8406172015-07-21 16:53:39 -0400164void Image::addTargetSibling(ImageSibling *sibling)
165{
Jamie Madill76b8f462017-04-21 12:23:40 -0400166 mState.targets.insert(sibling);
Geoff Langa8406172015-07-21 16:53:39 -0400167}
168
Jamie Madill4928b7c2017-06-20 12:57:39 -0400169gl::Error Image::orphanSibling(const gl::Context *context, ImageSibling *sibling)
Geoff Langa8406172015-07-21 16:53:39 -0400170{
171 // notify impl
Jamie Madill4928b7c2017-06-20 12:57:39 -0400172 ANGLE_TRY(mImplementation->orphan(context, sibling));
Geoff Langa8406172015-07-21 16:53:39 -0400173
Jamie Madill76b8f462017-04-21 12:23:40 -0400174 if (mState.source.get() == sibling)
Geoff Langa8406172015-07-21 16:53:39 -0400175 {
176 // If the sibling is the source, it cannot be a target.
Jamie Madill76b8f462017-04-21 12:23:40 -0400177 ASSERT(mState.targets.find(sibling) == mState.targets.end());
Jamie Madill4928b7c2017-06-20 12:57:39 -0400178 mState.source.set(context, nullptr);
Jamie Madill05b35b22017-10-03 09:01:44 -0400179 mOrphanedAndNeedsInit =
180 (sibling->initState(mState.imageIndex) == gl::InitState::MayNeedInit);
Geoff Langa8406172015-07-21 16:53:39 -0400181 }
182 else
183 {
Jamie Madill76b8f462017-04-21 12:23:40 -0400184 mState.targets.erase(sibling);
Geoff Langa8406172015-07-21 16:53:39 -0400185 }
186
Jamie Madill76b8f462017-04-21 12:23:40 -0400187 return gl::NoError();
Geoff Langa8406172015-07-21 16:53:39 -0400188}
189
Jamie Madilla3944d42016-07-22 22:13:26 -0400190const gl::Format &Image::getFormat() const
Geoff Langa8406172015-07-21 16:53:39 -0400191{
Jamie Madilld75dd262017-04-20 17:01:19 -0400192 return mState.source->getAttachmentFormat(GL_NONE, mState.imageIndex);
Geoff Langa8406172015-07-21 16:53:39 -0400193}
194
195size_t Image::getWidth() const
196{
Jamie Madilld75dd262017-04-20 17:01:19 -0400197 return mState.source->getAttachmentSize(mState.imageIndex).width;
Geoff Langa8406172015-07-21 16:53:39 -0400198}
199
200size_t Image::getHeight() const
201{
Jamie Madilld75dd262017-04-20 17:01:19 -0400202 return mState.source->getAttachmentSize(mState.imageIndex).height;
Geoff Langa8406172015-07-21 16:53:39 -0400203}
204
205size_t Image::getSamples() const
206{
Jamie Madilld75dd262017-04-20 17:01:19 -0400207 return mState.source->getAttachmentSamples(mState.imageIndex);
Geoff Langa8406172015-07-21 16:53:39 -0400208}
209
Jamie Madill76b8f462017-04-21 12:23:40 -0400210rx::ImageImpl *Image::getImplementation() const
Geoff Langa8406172015-07-21 16:53:39 -0400211{
212 return mImplementation;
213}
214
Jamie Madill76b8f462017-04-21 12:23:40 -0400215Error Image::initialize()
Geoff Langa8406172015-07-21 16:53:39 -0400216{
Jamie Madill76b8f462017-04-21 12:23:40 -0400217 return mImplementation->initialize();
Geoff Langa8406172015-07-21 16:53:39 -0400218}
Jamie Madill76b8f462017-04-21 12:23:40 -0400219
Jamie Madill05b35b22017-10-03 09:01:44 -0400220bool Image::orphaned() const
221{
222 return (mState.source.get() == nullptr);
223}
224
225gl::InitState Image::sourceInitState() const
226{
227 if (orphaned())
228 {
229 return mOrphanedAndNeedsInit ? gl::InitState::MayNeedInit : gl::InitState::Initialized;
230 }
231
232 return mState.source->initState(mState.imageIndex);
233}
234
235void Image::setInitState(gl::InitState initState)
236{
237 if (orphaned())
238 {
239 mOrphanedAndNeedsInit = false;
240 }
241
242 return mState.source->setInitState(mState.imageIndex, initState);
243}
244
Jamie Madilla3944d42016-07-22 22:13:26 -0400245} // namespace egl