blob: 1a393043576c9656b27fd10e4e7b47f34b3d5a35 [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
Corentin Wallez51706ea2015-08-07 14:39:22 -040048ImageSibling::ImageSibling(GLuint id) : RefCountObject(id), mSourcesOf(), mTargetOf()
Geoff Langa8406172015-07-21 16:53:39 -040049{
50}
51
52ImageSibling::~ImageSibling()
53{
54 // EGL images should hold a ref to their targets and siblings, a Texture should not be deletable
55 // while it is attached to an EGL image.
56 ASSERT(mSourcesOf.empty());
57 orphanImages();
58}
59
60void ImageSibling::setTargetImage(egl::Image *imageTarget)
61{
62 ASSERT(imageTarget != nullptr);
63 mTargetOf.set(imageTarget);
64 imageTarget->addTargetSibling(this);
65}
66
67gl::Error ImageSibling::orphanImages()
68{
69 if (mTargetOf.get() != nullptr)
70 {
71 // Can't be a target and have sources.
72 ASSERT(mSourcesOf.empty());
73
Jamie Madill76b8f462017-04-21 12:23:40 -040074 ANGLE_TRY(mTargetOf->orphanSibling(this));
Geoff Langa8406172015-07-21 16:53:39 -040075 mTargetOf.set(nullptr);
76 }
77 else
78 {
79 for (auto &sourceImage : mSourcesOf)
80 {
Jamie Madill76b8f462017-04-21 12:23:40 -040081 ANGLE_TRY(sourceImage->orphanSibling(this));
Geoff Langa8406172015-07-21 16:53:39 -040082 }
83 mSourcesOf.clear();
84 }
85
He Yunchaoacd18982017-01-04 10:46:42 +080086 return gl::NoError();
Geoff Langa8406172015-07-21 16:53:39 -040087}
88
89void ImageSibling::addImageSource(egl::Image *imageSource)
90{
91 ASSERT(imageSource != nullptr);
92 mSourcesOf.insert(imageSource);
93}
94
95void ImageSibling::removeImageSource(egl::Image *imageSource)
96{
97 ASSERT(mSourcesOf.find(imageSource) != mSourcesOf.end());
98 mSourcesOf.erase(imageSource);
99}
100
Jamie Madill76b8f462017-04-21 12:23:40 -0400101ImageState::ImageState(EGLenum target, ImageSibling *buffer, const AttributeMap &attribs)
102 : imageIndex(GetImageIndex(target, attribs)), source(), targets()
103{
104 source.set(buffer);
105}
106
107Image::Image(rx::EGLImplFactory *factory,
108 EGLenum target,
109 ImageSibling *buffer,
110 const AttributeMap &attribs)
Geoff Langa8406172015-07-21 16:53:39 -0400111 : RefCountObject(0),
Jamie Madill76b8f462017-04-21 12:23:40 -0400112 mState(target, buffer, attribs),
113 mImplementation(factory->createImage(mState, target, attribs)),
Jamie Madilla3944d42016-07-22 22:13:26 -0400114 mFormat(gl::Format::Invalid()),
Geoff Langa8406172015-07-21 16:53:39 -0400115 mWidth(0),
116 mHeight(0),
Jamie Madill76b8f462017-04-21 12:23:40 -0400117 mSamples(0)
Geoff Langa8406172015-07-21 16:53:39 -0400118{
119 ASSERT(mImplementation != nullptr);
120 ASSERT(buffer != nullptr);
121
Jamie Madill76b8f462017-04-21 12:23:40 -0400122 mState.source->addImageSource(this);
Geoff Langa8406172015-07-21 16:53:39 -0400123
124 if (IsTextureTarget(target))
125 {
Jamie Madill76b8f462017-04-21 12:23:40 -0400126 gl::Texture *texture = rx::GetAs<gl::Texture>(mState.source.get());
Geoff Langa8406172015-07-21 16:53:39 -0400127 GLenum textureTarget = egl_gl::EGLImageTargetToGLTextureTarget(target);
128 size_t level = attribs.get(EGL_GL_TEXTURE_LEVEL_KHR, 0);
Jamie Madilla3944d42016-07-22 22:13:26 -0400129 mFormat = texture->getFormat(textureTarget, level);
Geoff Langa8406172015-07-21 16:53:39 -0400130 mWidth = texture->getWidth(textureTarget, level);
131 mHeight = texture->getHeight(textureTarget, level);
132 mSamples = 0;
133 }
134 else if (IsRenderbufferTarget(target))
135 {
Jamie Madill76b8f462017-04-21 12:23:40 -0400136 gl::Renderbuffer *renderbuffer = rx::GetAs<gl::Renderbuffer>(mState.source.get());
Jamie Madilla3944d42016-07-22 22:13:26 -0400137 mFormat = renderbuffer->getFormat();
Geoff Langa8406172015-07-21 16:53:39 -0400138 mWidth = renderbuffer->getWidth();
139 mHeight = renderbuffer->getHeight();
140 mSamples = renderbuffer->getSamples();
141 }
142 else
143 {
144 UNREACHABLE();
145 }
146}
147
148Image::~Image()
149{
150 SafeDelete(mImplementation);
151
152 // All targets should hold a ref to the egl image and it should not be deleted until there are
153 // no siblings left.
Jamie Madill76b8f462017-04-21 12:23:40 -0400154 ASSERT(mState.targets.empty());
Geoff Langa8406172015-07-21 16:53:39 -0400155
156 // Tell the source that it is no longer used by this image
Jamie Madill76b8f462017-04-21 12:23:40 -0400157 if (mState.source.get() != nullptr)
Geoff Langa8406172015-07-21 16:53:39 -0400158 {
Jamie Madill76b8f462017-04-21 12:23:40 -0400159 mState.source->removeImageSource(this);
160 mState.source.set(nullptr);
Geoff Langa8406172015-07-21 16:53:39 -0400161 }
162}
163
164void Image::addTargetSibling(ImageSibling *sibling)
165{
Jamie Madill76b8f462017-04-21 12:23:40 -0400166 mState.targets.insert(sibling);
Geoff Langa8406172015-07-21 16:53:39 -0400167}
168
169gl::Error Image::orphanSibling(ImageSibling *sibling)
170{
171 // notify impl
Jamie Madill76b8f462017-04-21 12:23:40 -0400172 ANGLE_TRY(mImplementation->orphan(sibling));
Geoff Langa8406172015-07-21 16:53:39 -0400173
Jamie Madill76b8f462017-04-21 12:23:40 -0400174 if (mState.source.get() == sibling)
Geoff Langa8406172015-07-21 16:53:39 -0400175 {
176 // If the sibling is the source, it cannot be a target.
Jamie Madill76b8f462017-04-21 12:23:40 -0400177 ASSERT(mState.targets.find(sibling) == mState.targets.end());
178 mState.source.set(nullptr);
Geoff Langa8406172015-07-21 16:53:39 -0400179 }
180 else
181 {
Jamie Madill76b8f462017-04-21 12:23:40 -0400182 mState.targets.erase(sibling);
Geoff Langa8406172015-07-21 16:53:39 -0400183 }
184
Jamie Madill76b8f462017-04-21 12:23:40 -0400185 return gl::NoError();
Geoff Langa8406172015-07-21 16:53:39 -0400186}
187
Jamie Madilla3944d42016-07-22 22:13:26 -0400188const gl::Format &Image::getFormat() const
Geoff Langa8406172015-07-21 16:53:39 -0400189{
Jamie Madilla3944d42016-07-22 22:13:26 -0400190 return mFormat;
Geoff Langa8406172015-07-21 16:53:39 -0400191}
192
193size_t Image::getWidth() const
194{
195 return mWidth;
196}
197
198size_t Image::getHeight() const
199{
200 return mHeight;
201}
202
203size_t Image::getSamples() const
204{
205 return mSamples;
206}
207
Jamie Madill76b8f462017-04-21 12:23:40 -0400208rx::ImageImpl *Image::getImplementation() const
Geoff Langa8406172015-07-21 16:53:39 -0400209{
210 return mImplementation;
211}
212
Jamie Madill76b8f462017-04-21 12:23:40 -0400213Error Image::initialize()
Geoff Langa8406172015-07-21 16:53:39 -0400214{
Jamie Madill76b8f462017-04-21 12:23:40 -0400215 return mImplementation->initialize();
Geoff Langa8406172015-07-21 16:53:39 -0400216}
Jamie Madill76b8f462017-04-21 12:23:40 -0400217
Jamie Madilla3944d42016-07-22 22:13:26 -0400218} // namespace egl