blob: 471bc763c66c118d36e1412282fd535d92817427 [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"
14#include "libANGLE/Texture.h"
15#include "libANGLE/Renderbuffer.h"
16#include "libANGLE/renderer/ImageImpl.h"
17
18namespace egl
19{
Corentin Wallez00204262015-08-12 19:07:29 -070020ImageSibling::ImageSibling(GLuint id)
21 : gl::FramebufferAttachmentObject(id), mSourcesOf(), mTargetOf()
Geoff Langa8406172015-07-21 16:53:39 -040022{
23}
24
25ImageSibling::~ImageSibling()
26{
27 // EGL images should hold a ref to their targets and siblings, a Texture should not be deletable
28 // while it is attached to an EGL image.
29 ASSERT(mSourcesOf.empty());
30 orphanImages();
31}
32
33void ImageSibling::setTargetImage(egl::Image *imageTarget)
34{
35 ASSERT(imageTarget != nullptr);
36 mTargetOf.set(imageTarget);
37 imageTarget->addTargetSibling(this);
38}
39
40gl::Error ImageSibling::orphanImages()
41{
42 if (mTargetOf.get() != nullptr)
43 {
44 // Can't be a target and have sources.
45 ASSERT(mSourcesOf.empty());
46
47 gl::Error error = mTargetOf->orphanSibling(this);
48 if (error.isError())
49 {
50 return error;
51 }
52
53 mTargetOf.set(nullptr);
54 }
55 else
56 {
57 for (auto &sourceImage : mSourcesOf)
58 {
59 gl::Error error = sourceImage->orphanSibling(this);
60 if (error.isError())
61 {
62 return error;
63 }
64 }
65 mSourcesOf.clear();
66 }
67
68 return gl::Error(GL_NO_ERROR);
69}
70
71void ImageSibling::addImageSource(egl::Image *imageSource)
72{
73 ASSERT(imageSource != nullptr);
74 mSourcesOf.insert(imageSource);
75}
76
77void ImageSibling::removeImageSource(egl::Image *imageSource)
78{
79 ASSERT(mSourcesOf.find(imageSource) != mSourcesOf.end());
80 mSourcesOf.erase(imageSource);
81}
82
83Image::Image(rx::ImageImpl *impl, EGLenum target, ImageSibling *buffer, const AttributeMap &attribs)
84 : RefCountObject(0),
85 mImplementation(impl),
86 mInternalFormat(GL_NONE),
87 mWidth(0),
88 mHeight(0),
89 mSamples(0),
90 mSource(),
91 mTargets()
92{
93 ASSERT(mImplementation != nullptr);
94 ASSERT(buffer != nullptr);
95
96 mSource.set(buffer);
97 mSource->addImageSource(this);
98
99 if (IsTextureTarget(target))
100 {
101 gl::Texture *texture = rx::GetAs<gl::Texture>(mSource.get());
102 GLenum textureTarget = egl_gl::EGLImageTargetToGLTextureTarget(target);
103 size_t level = attribs.get(EGL_GL_TEXTURE_LEVEL_KHR, 0);
104 mInternalFormat = texture->getInternalFormat(textureTarget, level);
105 mWidth = texture->getWidth(textureTarget, level);
106 mHeight = texture->getHeight(textureTarget, level);
107 mSamples = 0;
108 }
109 else if (IsRenderbufferTarget(target))
110 {
111 gl::Renderbuffer *renderbuffer = rx::GetAs<gl::Renderbuffer>(mSource.get());
112 mInternalFormat = renderbuffer->getInternalFormat();
113 mWidth = renderbuffer->getWidth();
114 mHeight = renderbuffer->getHeight();
115 mSamples = renderbuffer->getSamples();
116 }
117 else
118 {
119 UNREACHABLE();
120 }
121}
122
123Image::~Image()
124{
125 SafeDelete(mImplementation);
126
127 // All targets should hold a ref to the egl image and it should not be deleted until there are
128 // no siblings left.
129 ASSERT(mTargets.empty());
130
131 // Tell the source that it is no longer used by this image
132 if (mSource.get() != nullptr)
133 {
134 mSource->removeImageSource(this);
135 mSource.set(nullptr);
136 }
137}
138
139void Image::addTargetSibling(ImageSibling *sibling)
140{
141 mTargets.insert(sibling);
142}
143
144gl::Error Image::orphanSibling(ImageSibling *sibling)
145{
146 // notify impl
147 gl::Error error = mImplementation->orphan(sibling);
148
149 if (mSource.get() == sibling)
150 {
151 // If the sibling is the source, it cannot be a target.
152 ASSERT(mTargets.find(sibling) == mTargets.end());
153
154 mSource.set(nullptr);
155 }
156 else
157 {
158 mTargets.erase(sibling);
159 }
160
161 return error;
162}
163
164GLenum Image::getInternalFormat() const
165{
166 return mInternalFormat;
167}
168
169size_t Image::getWidth() const
170{
171 return mWidth;
172}
173
174size_t Image::getHeight() const
175{
176 return mHeight;
177}
178
179size_t Image::getSamples() const
180{
181 return mSamples;
182}
183
184rx::ImageImpl *Image::getImplementation()
185{
186 return mImplementation;
187}
188
189const rx::ImageImpl *Image::getImplementation() const
190{
191 return mImplementation;
192}
193}