1 //
2 // Copyright 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.h: Defines the egl::Image class representing the EGLimage object.
8 
9 #ifndef LIBANGLE_IMAGE_H_
10 #define LIBANGLE_IMAGE_H_
11 
12 #include "common/angleutils.h"
13 #include "libANGLE/AttributeMap.h"
14 #include "libANGLE/Debug.h"
15 #include "libANGLE/Error.h"
16 #include "libANGLE/FramebufferAttachment.h"
17 #include "libANGLE/RefCountObject.h"
18 #include "libANGLE/formatutils.h"
19 
20 #include <set>
21 
22 namespace rx
23 {
24 class EGLImplFactory;
25 class ImageImpl;
26 class ExternalImageSiblingImpl;
27 
28 // Used for distinguishing dirty bit messages from gl::Texture/rx::TexureImpl/gl::Image.
29 constexpr size_t kTextureImageImplObserverMessageIndex = 0;
30 constexpr size_t kTextureImageSiblingMessageIndex      = 1;
31 }  // namespace rx
32 
33 namespace egl
34 {
35 class Image;
36 class Display;
37 
38 // Only currently Renderbuffers and Textures can be bound with images. This makes the relationship
39 // explicit, and also ensures that an image sibling can determine if it's been initialized or not,
40 // which is important for the robust resource init extension with Textures and EGLImages.
41 class ImageSibling : public gl::FramebufferAttachmentObject
42 {
43   public:
44     ImageSibling();
45     ~ImageSibling() override;
46 
47     bool isEGLImageTarget() const;
48     gl::InitState sourceEGLImageInitState() const;
49     void setSourceEGLImageInitState(gl::InitState initState) const;
50 
51     bool isRenderable(const gl::Context *context,
52                       GLenum binding,
53                       const gl::ImageIndex &imageIndex) const override;
54     bool isYUV() const override;
55 
56   protected:
57     // Set the image target of this sibling
58     void setTargetImage(const gl::Context *context, egl::Image *imageTarget);
59 
60     // Orphan all EGL image sources and targets
61     angle::Result orphanImages(const gl::Context *context);
62 
63     void notifySiblings(angle::SubjectMessage message);
64 
65   private:
66     friend class Image;
67 
68     // Called from Image only to add a new source image
69     void addImageSource(egl::Image *imageSource);
70 
71     // Called from Image only to remove a source image when the Image is being deleted
72     void removeImageSource(egl::Image *imageSource);
73 
74     std::set<Image *> mSourcesOf;
75     BindingPointer<Image> mTargetOf;
76 };
77 
78 // Wrapper for EGLImage sources that are not owned by ANGLE, these often have to do
79 // platform-specific queries for format and size information.
80 class ExternalImageSibling : public ImageSibling
81 {
82   public:
83     ExternalImageSibling(rx::EGLImplFactory *factory,
84                          const gl::Context *context,
85                          EGLenum target,
86                          EGLClientBuffer buffer,
87                          const AttributeMap &attribs);
88     ~ExternalImageSibling() override;
89 
90     void onDestroy(const egl::Display *display);
91 
92     Error initialize(const Display *display);
93 
94     gl::Extents getAttachmentSize(const gl::ImageIndex &imageIndex) const override;
95     gl::Format getAttachmentFormat(GLenum binding, const gl::ImageIndex &imageIndex) const override;
96     GLsizei getAttachmentSamples(const gl::ImageIndex &imageIndex) const override;
97     bool isRenderable(const gl::Context *context,
98                       GLenum binding,
99                       const gl::ImageIndex &imageIndex) const override;
100     bool isTextureable(const gl::Context *context) const;
101     bool isYUV() const override;
102 
103     void onAttach(const gl::Context *context, rx::Serial framebufferSerial) override;
104     void onDetach(const gl::Context *context, rx::Serial framebufferSerial) override;
105     GLuint getId() const override;
106 
107     gl::InitState initState(const gl::ImageIndex &imageIndex) const override;
108     void setInitState(const gl::ImageIndex &imageIndex, gl::InitState initState) override;
109 
110     rx::ExternalImageSiblingImpl *getImplementation() const;
111 
112   protected:
113     rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const override;
114 
115   private:
116     // ObserverInterface implementation.
117     void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
118 
119     std::unique_ptr<rx::ExternalImageSiblingImpl> mImplementation;
120     angle::ObserverBinding mImplObserverBinding;
121 };
122 
123 struct ImageState : private angle::NonCopyable
124 {
125     ImageState(EGLenum target, ImageSibling *buffer, const AttributeMap &attribs);
126     ~ImageState();
127 
128     EGLLabelKHR label;
129     EGLenum target;
130     gl::ImageIndex imageIndex;
131     ImageSibling *source;
132     std::set<ImageSibling *> targets;
133 
134     gl::Format format;
135     bool yuv;
136     gl::Extents size;
137     size_t samples;
138     EGLenum sourceType;
139     EGLenum colorspace;
140 };
141 
142 class Image final : public RefCountObject, public LabeledObject
143 {
144   public:
145     Image(rx::EGLImplFactory *factory,
146           const gl::Context *context,
147           EGLenum target,
148           ImageSibling *buffer,
149           const AttributeMap &attribs);
150 
151     void onDestroy(const Display *display) override;
152     ~Image() override;
153 
154     void setLabel(EGLLabelKHR label) override;
155     EGLLabelKHR getLabel() const override;
156 
157     const gl::Format &getFormat() const;
158     bool isRenderable(const gl::Context *context) const;
159     bool isTexturable(const gl::Context *context) const;
160     bool isYUV() const;
161     size_t getWidth() const;
162     size_t getHeight() const;
163     bool isLayered() const;
164     size_t getSamples() const;
165 
166     Error initialize(const Display *display);
167 
168     rx::ImageImpl *getImplementation() const;
169 
170     bool orphaned() const;
171     gl::InitState sourceInitState() const;
172     void setInitState(gl::InitState initState);
173 
174   private:
175     friend class ImageSibling;
176 
177     // Called from ImageSibling only notify the image that a new target sibling exists for state
178     // tracking.
179     void addTargetSibling(ImageSibling *sibling);
180 
181     // Called from ImageSibling only to notify the image that a sibling (source or target) has
182     // been respecified and state tracking should be updated.
183     angle::Result orphanSibling(const gl::Context *context, ImageSibling *sibling);
184 
185     void notifySiblings(const ImageSibling *notifier, angle::SubjectMessage message);
186 
187     ImageState mState;
188     rx::ImageImpl *mImplementation;
189     bool mOrphanedAndNeedsInit;
190 };
191 }  // namespace egl
192 
193 #endif  // LIBANGLE_IMAGE_H_
194