blob: 5612b9bbdc7c905e3d6187a99c5191bc092e74f4 [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 {
29 return gl::ImageIndex::MakeInvalid();
30 }
31
32 GLenum target = egl_gl::EGLImageTargetToGLTextureTarget(eglTarget);
33 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
36 if (target == GL_TEXTURE_3D)
37 {
38 return gl::ImageIndex::Make3D(mip, layer);
39 }
40 else
41 {
42 ASSERT(layer == 0);
43 return gl::ImageIndex::MakeGeneric(target, mip);
44 }
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 {
81 for (auto &sourceImage : mSourcesOf)
82 {
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
125Image::Image(rx::EGLImplFactory *factory,
126 EGLenum target,
127 ImageSibling *buffer,
128 const AttributeMap &attribs)
Geoff Langa8406172015-07-21 16:53:39 -0400129 : RefCountObject(0),
Jamie Madill76b8f462017-04-21 12:23:40 -0400130 mState(target, buffer, attribs),
Jamie Madill05b35b22017-10-03 09:01:44 -0400131 mImplementation(factory->createImage(mState, target, attribs)),
132 mOrphanedAndNeedsInit(false)
Geoff Langa8406172015-07-21 16:53:39 -0400133{
134 ASSERT(mImplementation != nullptr);
135 ASSERT(buffer != nullptr);
136
Jamie Madill76b8f462017-04-21 12:23:40 -0400137 mState.source->addImageSource(this);
Geoff Langa8406172015-07-21 16:53:39 -0400138}
139
Jamie Madill71c88b32017-09-14 22:20:29 -0400140gl::Error Image::onDestroy(const gl::Context *context)
Geoff Langa8406172015-07-21 16:53:39 -0400141{
Geoff Langa8406172015-07-21 16:53:39 -0400142 // All targets should hold a ref to the egl image and it should not be deleted until there are
143 // no siblings left.
Jamie Madill76b8f462017-04-21 12:23:40 -0400144 ASSERT(mState.targets.empty());
Geoff Langa8406172015-07-21 16:53:39 -0400145
146 // Tell the source that it is no longer used by this image
Jamie Madill76b8f462017-04-21 12:23:40 -0400147 if (mState.source.get() != nullptr)
Geoff Langa8406172015-07-21 16:53:39 -0400148 {
Jamie Madill76b8f462017-04-21 12:23:40 -0400149 mState.source->removeImageSource(this);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400150 mState.source.set(context, nullptr);
Geoff Langa8406172015-07-21 16:53:39 -0400151 }
Jamie Madill71c88b32017-09-14 22:20:29 -0400152 return gl::NoError();
Geoff Langa8406172015-07-21 16:53:39 -0400153}
154
Jamie Madill4928b7c2017-06-20 12:57:39 -0400155Image::~Image()
156{
Jamie Madill71c88b32017-09-14 22:20:29 -0400157 SafeDelete(mImplementation);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400158}
159
Geoff Langa8406172015-07-21 16:53:39 -0400160void Image::addTargetSibling(ImageSibling *sibling)
161{
Jamie Madill76b8f462017-04-21 12:23:40 -0400162 mState.targets.insert(sibling);
Geoff Langa8406172015-07-21 16:53:39 -0400163}
164
Jamie Madill4928b7c2017-06-20 12:57:39 -0400165gl::Error Image::orphanSibling(const gl::Context *context, ImageSibling *sibling)
Geoff Langa8406172015-07-21 16:53:39 -0400166{
167 // notify impl
Jamie Madill4928b7c2017-06-20 12:57:39 -0400168 ANGLE_TRY(mImplementation->orphan(context, sibling));
Geoff Langa8406172015-07-21 16:53:39 -0400169
Jamie Madill76b8f462017-04-21 12:23:40 -0400170 if (mState.source.get() == sibling)
Geoff Langa8406172015-07-21 16:53:39 -0400171 {
172 // If the sibling is the source, it cannot be a target.
Jamie Madill76b8f462017-04-21 12:23:40 -0400173 ASSERT(mState.targets.find(sibling) == mState.targets.end());
Jamie Madill4928b7c2017-06-20 12:57:39 -0400174 mState.source.set(context, nullptr);
Jamie Madill05b35b22017-10-03 09:01:44 -0400175 mOrphanedAndNeedsInit =
176 (sibling->initState(mState.imageIndex) == gl::InitState::MayNeedInit);
Geoff Langa8406172015-07-21 16:53:39 -0400177 }
178 else
179 {
Jamie Madill76b8f462017-04-21 12:23:40 -0400180 mState.targets.erase(sibling);
Geoff Langa8406172015-07-21 16:53:39 -0400181 }
182
Jamie Madill76b8f462017-04-21 12:23:40 -0400183 return gl::NoError();
Geoff Langa8406172015-07-21 16:53:39 -0400184}
185
Jamie Madilla3944d42016-07-22 22:13:26 -0400186const gl::Format &Image::getFormat() const
Geoff Langa8406172015-07-21 16:53:39 -0400187{
Jamie Madilld75dd262017-04-20 17:01:19 -0400188 return mState.source->getAttachmentFormat(GL_NONE, mState.imageIndex);
Geoff Langa8406172015-07-21 16:53:39 -0400189}
190
191size_t Image::getWidth() const
192{
Jamie Madilld75dd262017-04-20 17:01:19 -0400193 return mState.source->getAttachmentSize(mState.imageIndex).width;
Geoff Langa8406172015-07-21 16:53:39 -0400194}
195
196size_t Image::getHeight() const
197{
Jamie Madilld75dd262017-04-20 17:01:19 -0400198 return mState.source->getAttachmentSize(mState.imageIndex).height;
Geoff Langa8406172015-07-21 16:53:39 -0400199}
200
201size_t Image::getSamples() const
202{
Jamie Madilld75dd262017-04-20 17:01:19 -0400203 return mState.source->getAttachmentSamples(mState.imageIndex);
Geoff Langa8406172015-07-21 16:53:39 -0400204}
205
Jamie Madill76b8f462017-04-21 12:23:40 -0400206rx::ImageImpl *Image::getImplementation() const
Geoff Langa8406172015-07-21 16:53:39 -0400207{
208 return mImplementation;
209}
210
Jamie Madill76b8f462017-04-21 12:23:40 -0400211Error Image::initialize()
Geoff Langa8406172015-07-21 16:53:39 -0400212{
Jamie Madill76b8f462017-04-21 12:23:40 -0400213 return mImplementation->initialize();
Geoff Langa8406172015-07-21 16:53:39 -0400214}
Jamie Madill76b8f462017-04-21 12:23:40 -0400215
Jamie Madill05b35b22017-10-03 09:01:44 -0400216bool Image::orphaned() const
217{
218 return (mState.source.get() == nullptr);
219}
220
221gl::InitState Image::sourceInitState() const
222{
223 if (orphaned())
224 {
225 return mOrphanedAndNeedsInit ? gl::InitState::MayNeedInit : gl::InitState::Initialized;
226 }
227
228 return mState.source->initState(mState.imageIndex);
229}
230
231void Image::setInitState(gl::InitState initState)
232{
233 if (orphaned())
234 {
235 mOrphanedAndNeedsInit = false;
236 }
237
238 return mState.source->setInitState(mState.imageIndex, initState);
239}
240
Jamie Madilla3944d42016-07-22 22:13:26 -0400241} // namespace egl