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