blob: dc2467b3e4ff5e47fcd9c39a0dbafb11db96fafd [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 Lange1a057e2018-06-07 15:09:00 -040013#include "libANGLE/Renderbuffer.h"
14#include "libANGLE/Texture.h"
Geoff Langa8406172015-07-21 16:53:39 -040015#include "libANGLE/angletypes.h"
Jamie Madilla3944d42016-07-22 22:13:26 -040016#include "libANGLE/formatutils.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);
Geoff Lange1a057e2018-06-07 15:09:00 -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));
Jamie Madill76b8f462017-04-21 12:23:40 -040035
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)
Geoff Lang0bc81b62018-07-30 13:34:50 -0400121 : label(nullptr),
122 imageIndex(GetImageIndex(target, attribs)),
123 source(buffer),
124 targets(),
125 format(buffer->getAttachmentFormat(GL_NONE, imageIndex)),
126 size(buffer->getAttachmentSize(imageIndex)),
127 samples(buffer->getAttachmentSamples(imageIndex))
Jamie Madill76b8f462017-04-21 12:23:40 -0400128{
Jamie Madill76b8f462017-04-21 12:23:40 -0400129}
130
Jamie Madillacf2f3a2017-11-21 19:22:44 -0500131ImageState::~ImageState()
132{
133}
134
Jamie Madill76b8f462017-04-21 12:23:40 -0400135Image::Image(rx::EGLImplFactory *factory,
Geoff Langcd7cd2a2018-07-19 11:25:54 -0400136 const gl::Context *context,
Jamie Madill76b8f462017-04-21 12:23:40 -0400137 EGLenum target,
138 ImageSibling *buffer,
139 const AttributeMap &attribs)
Geoff Langa8406172015-07-21 16:53:39 -0400140 : RefCountObject(0),
Jamie Madill76b8f462017-04-21 12:23:40 -0400141 mState(target, buffer, attribs),
Geoff Langcd7cd2a2018-07-19 11:25:54 -0400142 mImplementation(factory->createImage(mState, context, target, attribs)),
Jamie Madill05b35b22017-10-03 09:01:44 -0400143 mOrphanedAndNeedsInit(false)
Geoff Langa8406172015-07-21 16:53:39 -0400144{
145 ASSERT(mImplementation != nullptr);
146 ASSERT(buffer != nullptr);
147
Jamie Madill76b8f462017-04-21 12:23:40 -0400148 mState.source->addImageSource(this);
Geoff Langa8406172015-07-21 16:53:39 -0400149}
150
Jamie Madill71c88b32017-09-14 22:20:29 -0400151gl::Error Image::onDestroy(const gl::Context *context)
Geoff Langa8406172015-07-21 16:53:39 -0400152{
Geoff Langa8406172015-07-21 16:53:39 -0400153 // All targets should hold a ref to the egl image and it should not be deleted until there are
154 // no siblings left.
Jamie Madill76b8f462017-04-21 12:23:40 -0400155 ASSERT(mState.targets.empty());
Geoff Langa8406172015-07-21 16:53:39 -0400156
157 // Tell the source that it is no longer used by this image
Jamie Madill76b8f462017-04-21 12:23:40 -0400158 if (mState.source.get() != nullptr)
Geoff Langa8406172015-07-21 16:53:39 -0400159 {
Jamie Madill76b8f462017-04-21 12:23:40 -0400160 mState.source->removeImageSource(this);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400161 mState.source.set(context, nullptr);
Geoff Langa8406172015-07-21 16:53:39 -0400162 }
Jamie Madill71c88b32017-09-14 22:20:29 -0400163 return gl::NoError();
Geoff Langa8406172015-07-21 16:53:39 -0400164}
165
Jamie Madill4928b7c2017-06-20 12:57:39 -0400166Image::~Image()
167{
Jamie Madill71c88b32017-09-14 22:20:29 -0400168 SafeDelete(mImplementation);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400169}
170
Geoff Lang75359662018-04-11 01:42:27 -0400171void Image::setLabel(EGLLabelKHR label)
172{
173 mState.label = label;
174}
175
176EGLLabelKHR Image::getLabel() const
177{
178 return mState.label;
179}
180
Geoff Langa8406172015-07-21 16:53:39 -0400181void Image::addTargetSibling(ImageSibling *sibling)
182{
Jamie Madill76b8f462017-04-21 12:23:40 -0400183 mState.targets.insert(sibling);
Geoff Langa8406172015-07-21 16:53:39 -0400184}
185
Jamie Madill4928b7c2017-06-20 12:57:39 -0400186gl::Error Image::orphanSibling(const gl::Context *context, ImageSibling *sibling)
Geoff Langa8406172015-07-21 16:53:39 -0400187{
188 // notify impl
Jamie Madill4928b7c2017-06-20 12:57:39 -0400189 ANGLE_TRY(mImplementation->orphan(context, sibling));
Geoff Langa8406172015-07-21 16:53:39 -0400190
Jamie Madill76b8f462017-04-21 12:23:40 -0400191 if (mState.source.get() == sibling)
Geoff Langa8406172015-07-21 16:53:39 -0400192 {
193 // If the sibling is the source, it cannot be a target.
Jamie Madill76b8f462017-04-21 12:23:40 -0400194 ASSERT(mState.targets.find(sibling) == mState.targets.end());
Jamie Madill4928b7c2017-06-20 12:57:39 -0400195 mState.source.set(context, nullptr);
Jamie Madill05b35b22017-10-03 09:01:44 -0400196 mOrphanedAndNeedsInit =
197 (sibling->initState(mState.imageIndex) == gl::InitState::MayNeedInit);
Geoff Langa8406172015-07-21 16:53:39 -0400198 }
199 else
200 {
Jamie Madill76b8f462017-04-21 12:23:40 -0400201 mState.targets.erase(sibling);
Geoff Langa8406172015-07-21 16:53:39 -0400202 }
203
Jamie Madill76b8f462017-04-21 12:23:40 -0400204 return gl::NoError();
Geoff Langa8406172015-07-21 16:53:39 -0400205}
206
Geoff Lang0bc81b62018-07-30 13:34:50 -0400207const gl::Format &Image::getFormat() const
Geoff Langa8406172015-07-21 16:53:39 -0400208{
Geoff Lang0bc81b62018-07-30 13:34:50 -0400209 return mState.format;
Geoff Langa8406172015-07-21 16:53:39 -0400210}
211
212size_t Image::getWidth() const
213{
Geoff Lang0bc81b62018-07-30 13:34:50 -0400214 return mState.size.width;
Geoff Langa8406172015-07-21 16:53:39 -0400215}
216
217size_t Image::getHeight() const
218{
Geoff Lang0bc81b62018-07-30 13:34:50 -0400219 return mState.size.height;
Geoff Langa8406172015-07-21 16:53:39 -0400220}
221
222size_t Image::getSamples() const
223{
Geoff Lang0bc81b62018-07-30 13:34:50 -0400224 return mState.samples;
Geoff Langa8406172015-07-21 16:53:39 -0400225}
226
Jamie Madill76b8f462017-04-21 12:23:40 -0400227rx::ImageImpl *Image::getImplementation() const
Geoff Langa8406172015-07-21 16:53:39 -0400228{
229 return mImplementation;
230}
231
Geoff Langcd7cd2a2018-07-19 11:25:54 -0400232Error Image::initialize(const Display *display)
Geoff Langa8406172015-07-21 16:53:39 -0400233{
Geoff Langcd7cd2a2018-07-19 11:25:54 -0400234 return mImplementation->initialize(display);
Geoff Langa8406172015-07-21 16:53:39 -0400235}
Jamie Madill76b8f462017-04-21 12:23:40 -0400236
Jamie Madill05b35b22017-10-03 09:01:44 -0400237bool Image::orphaned() const
238{
239 return (mState.source.get() == nullptr);
240}
241
242gl::InitState Image::sourceInitState() const
243{
244 if (orphaned())
245 {
246 return mOrphanedAndNeedsInit ? gl::InitState::MayNeedInit : gl::InitState::Initialized;
247 }
248
249 return mState.source->initState(mState.imageIndex);
250}
251
252void Image::setInitState(gl::InitState initState)
253{
254 if (orphaned())
255 {
256 mOrphanedAndNeedsInit = false;
257 }
258
259 return mState.source->setInitState(mState.imageIndex, initState);
260}
261
Jamie Madilla3944d42016-07-22 22:13:26 -0400262} // namespace egl