blob: 34e8d7ac1b42e6057c4fb1040583fe5697ea12c9 [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 Lang75359662018-04-11 01:42:27 -0400121 : label(nullptr), 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 Lang75359662018-04-11 01:42:27 -0400164void Image::setLabel(EGLLabelKHR label)
165{
166 mState.label = label;
167}
168
169EGLLabelKHR Image::getLabel() const
170{
171 return mState.label;
172}
173
Geoff Langa8406172015-07-21 16:53:39 -0400174void Image::addTargetSibling(ImageSibling *sibling)
175{
Jamie Madill76b8f462017-04-21 12:23:40 -0400176 mState.targets.insert(sibling);
Geoff Langa8406172015-07-21 16:53:39 -0400177}
178
Jamie Madill4928b7c2017-06-20 12:57:39 -0400179gl::Error Image::orphanSibling(const gl::Context *context, ImageSibling *sibling)
Geoff Langa8406172015-07-21 16:53:39 -0400180{
181 // notify impl
Jamie Madill4928b7c2017-06-20 12:57:39 -0400182 ANGLE_TRY(mImplementation->orphan(context, sibling));
Geoff Langa8406172015-07-21 16:53:39 -0400183
Jamie Madill76b8f462017-04-21 12:23:40 -0400184 if (mState.source.get() == sibling)
Geoff Langa8406172015-07-21 16:53:39 -0400185 {
186 // If the sibling is the source, it cannot be a target.
Jamie Madill76b8f462017-04-21 12:23:40 -0400187 ASSERT(mState.targets.find(sibling) == mState.targets.end());
Jamie Madill4928b7c2017-06-20 12:57:39 -0400188 mState.source.set(context, nullptr);
Jamie Madill05b35b22017-10-03 09:01:44 -0400189 mOrphanedAndNeedsInit =
190 (sibling->initState(mState.imageIndex) == gl::InitState::MayNeedInit);
Geoff Langa8406172015-07-21 16:53:39 -0400191 }
192 else
193 {
Jamie Madill76b8f462017-04-21 12:23:40 -0400194 mState.targets.erase(sibling);
Geoff Langa8406172015-07-21 16:53:39 -0400195 }
196
Jamie Madill76b8f462017-04-21 12:23:40 -0400197 return gl::NoError();
Geoff Langa8406172015-07-21 16:53:39 -0400198}
199
Jiawei Shaoa8802472018-05-28 11:17:47 +0800200gl::Format Image::getFormat() const
Geoff Langa8406172015-07-21 16:53:39 -0400201{
Jamie Madilld75dd262017-04-20 17:01:19 -0400202 return mState.source->getAttachmentFormat(GL_NONE, mState.imageIndex);
Geoff Langa8406172015-07-21 16:53:39 -0400203}
204
205size_t Image::getWidth() const
206{
Jamie Madilld75dd262017-04-20 17:01:19 -0400207 return mState.source->getAttachmentSize(mState.imageIndex).width;
Geoff Langa8406172015-07-21 16:53:39 -0400208}
209
210size_t Image::getHeight() const
211{
Jamie Madilld75dd262017-04-20 17:01:19 -0400212 return mState.source->getAttachmentSize(mState.imageIndex).height;
Geoff Langa8406172015-07-21 16:53:39 -0400213}
214
215size_t Image::getSamples() const
216{
Jamie Madilld75dd262017-04-20 17:01:19 -0400217 return mState.source->getAttachmentSamples(mState.imageIndex);
Geoff Langa8406172015-07-21 16:53:39 -0400218}
219
Jamie Madill76b8f462017-04-21 12:23:40 -0400220rx::ImageImpl *Image::getImplementation() const
Geoff Langa8406172015-07-21 16:53:39 -0400221{
222 return mImplementation;
223}
224
Jamie Madill76b8f462017-04-21 12:23:40 -0400225Error Image::initialize()
Geoff Langa8406172015-07-21 16:53:39 -0400226{
Jamie Madill76b8f462017-04-21 12:23:40 -0400227 return mImplementation->initialize();
Geoff Langa8406172015-07-21 16:53:39 -0400228}
Jamie Madill76b8f462017-04-21 12:23:40 -0400229
Jamie Madill05b35b22017-10-03 09:01:44 -0400230bool Image::orphaned() const
231{
232 return (mState.source.get() == nullptr);
233}
234
235gl::InitState Image::sourceInitState() const
236{
237 if (orphaned())
238 {
239 return mOrphanedAndNeedsInit ? gl::InitState::MayNeedInit : gl::InitState::Initialized;
240 }
241
242 return mState.source->initState(mState.imageIndex);
243}
244
245void Image::setInitState(gl::InitState initState)
246{
247 if (orphaned())
248 {
249 mOrphanedAndNeedsInit = false;
250 }
251
252 return mState.source->setInitState(mState.imageIndex, initState);
253}
254
Jamie Madilla3944d42016-07-22 22:13:26 -0400255} // namespace egl