1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 //    names, trademarks, service marks, or product names of the Licensor
11 //    and its affiliates, except as required to comply with Section 4(c) of
12 //    the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 //     http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #ifndef PXR_IMAGING_GLF_DRAW_TARGET_H
25 #define PXR_IMAGING_GLF_DRAW_TARGET_H
26 
27 /// \file glf/drawTarget.h
28 
29 #include "pxr/pxr.h"
30 #include "pxr/imaging/glf/api.h"
31 #include "pxr/imaging/glf/texture.h"
32 #include "pxr/imaging/garch/glApi.h"
33 
34 #include "pxr/base/gf/vec2i.h"
35 #include "pxr/base/gf/matrix4d.h"
36 #include "pxr/base/tf/declarePtrs.h"
37 #include "pxr/base/tf/refBase.h"
38 #include "pxr/base/tf/weakBase.h"
39 
40 #include <map>
41 #include <memory>
42 #include <set>
43 #include <string>
44 
45 
46 PXR_NAMESPACE_OPEN_SCOPE
47 
48 
49 TF_DECLARE_WEAK_AND_REF_PTRS(GlfDrawTarget);
50 typedef std::shared_ptr<class GlfGLContext> GlfGLContextSharedPtr;
51 
52 /// \class GlfDrawTarget
53 ///
54 /// A class representing a GL render target with mutliple image attachments.
55 ///
56 /// A DrawTarget is essentially a custom render pass into which several
57 /// arbitrary variables can be output into. These can later be used as
58 /// texture samplers by GLSL shaders.
59 ///
60 /// The DrawTarget maintains a map of named attachments that correspond
61 /// to GL_TEXTURE_2D mages. By default, DrawTargets also create a depth
62 /// component that is used both as a depth buffer during the draw pass,
63 /// and can later be accessed as a regular GL_TEXTURE_2D data. Stencils
64 /// are also available (by setting the format to GL_DEPTH_STENCIL and
65 /// the internalFormat to GL_DEPTH24_STENCIL8)
66 ///
67 class GlfDrawTarget : public TfRefBase, public TfWeakBase {
68 public:
69     typedef GlfDrawTarget This;
70 
71 public:
72 
73     /// Returns a new instance.
74     GLF_API
75     static GlfDrawTargetRefPtr New( GfVec2i const & size,
76                                     bool requestMSAA = false );
77 
78     /// Returns a new instance.
79     /// GL framebuffers cannot be shared across contexts, but texture
80     /// attachments can. In order to reflect this, GlfDrawTargets hold
81     /// onto their maps of attachments through a RefPtr that can be shared
82     /// by multiple GlfDrawTargets, one for each of the active GL contexts
83     /// (ex. one for each active QT viewer).
84     /// This constructor creates a new framebuffer, but populates its map of
85     /// attachments by sharing the RefPtr of the source GlfDrawTarget.
86     GLF_API
87     static GlfDrawTargetRefPtr New( GlfDrawTargetPtr const & drawtarget );
88 
89     class Attachment : public GlfTexture {
90     public:
91         typedef TfDeclarePtrs<class Attachment>::RefPtr AttachmentRefPtr;
92 
93         GLF_API
94         static AttachmentRefPtr New(int glIndex, GLenum format, GLenum type,
95                                     GLenum internalFormat, GfVec2i size,
96                                     unsigned int numSamples);
97 
98         GLF_API
99         ~Attachment() override;
100 
101         /// Returns the GL texture index (can be used as any regular GL texture)
102         GLuint GetGlTextureName() override;
103 
104         /// Returns the GL texture index multisampled of this attachment
GetGlTextureMSName()105         GLuint GetGlTextureMSName() const { return _textureNameMS; }
106 
107         /// Returns the GL format of the texture (GL_RGB, GL_DEPTH_COMPONENT...)
GetFormat()108         GLenum GetFormat() const { return _format; }
109 
110         /// Returns the GL type of the texture (GL_BYTE, GL_INT, GL_FLOAT...)
GetType()111         GLenum GetType() const { return _type; }
112 
113         /// Returns the GL internalFormat of the texture
GetInternalFormat()114         GLenum GetInternalFormat() const { return _internalFormat; }
115 
116         /// Returns the GL attachment point index in the framebuffer.
GetAttach()117         int GetAttach() const { return _glIndex; }
118 
119         /// Resize the attachment recreating the texture
120         GLF_API
121         void ResizeTexture(const GfVec2i &size);
122 
123         // GlfTexture overrides
124         GLF_API
125         BindingVector GetBindings(TfToken const & identifier,
126                                           GLuint samplerName) override;
127         GLF_API
128         VtDictionary GetTextureInfo(bool forceLoad) override;
129 
130         /// Updates the contents signature for the underlying texture
131         /// to allow downstream consumers to know that the texture image
132         /// data may have changed.
133         GLF_API
134         void TouchContents();
135 
136     private:
137         Attachment(int glIndex, GLenum format, GLenum type,
138                    GLenum internalFormat, GfVec2i size,
139                    unsigned int numSamples);
140 
141         void _GenTexture();
142         void _DeleteTexture();
143 
144         GLuint       _textureName;
145         GLuint       _textureNameMS;
146 
147         GLenum       _format,
148                      _type,
149                      _internalFormat;
150 
151         int          _glIndex;
152 
153         GfVec2i      _size;
154 
155         unsigned int _numSamples;
156     };
157 
158     typedef TfDeclarePtrs<class Attachment>::RefPtr AttachmentRefPtr;
159 
160     typedef std::map<std::string, AttachmentRefPtr> AttachmentsMap;
161 
162     /// Add an attachment to the DrawTarget.
163     GLF_API
164     void AddAttachment( std::string const & name,
165                         GLenum format, GLenum type, GLenum internalFormat );
166 
167     /// Removes the named attachment from the DrawTarget.
168     GLF_API
169     void DeleteAttachment( std::string const & name );
170 
171     /// Clears all the attachments for this DrawTarget.
172     GLF_API
173     void ClearAttachments();
174 
175     /// Copies the list of attachments from DrawTarget.
176     GLF_API
177     void CloneAttachments( GlfDrawTargetPtr const & drawtarget );
178 
179     /// Returns the list of Attachments for this DrawTarget.
180     GLF_API
181     AttachmentsMap const & GetAttachments() const;
182 
183     /// Returns the attachment with a given name or TfNullPtr;
184     GLF_API
185     AttachmentRefPtr GetAttachment(std::string const & name);
186 
187     /// Write the Attachment buffer to an image file (debugging).
188     GLF_API
189     bool WriteToFile(std::string const & name,
190                      std::string const & filename,
191                      GfMatrix4d const & viewMatrix = GfMatrix4d(1),
192                      GfMatrix4d const & projectionMatrix = GfMatrix4d(1));
193 
194     /// Resize the DrawTarget.
195     GLF_API
196     void SetSize( GfVec2i );
197 
198     /// Returns the size of the DrawTarget.
GetSize()199     GfVec2i const & GetSize() const { return _size; }
200 
201     /// Returns if the draw target uses msaa
HasMSAA()202     bool HasMSAA() const { return (_numSamples > 1); }
203 
204     /// Returns the framebuffer object Id.
205     GLF_API
206     GLuint GetFramebufferId() const;
207 
208     /// Returns the id of the framebuffer object with MSAA buffers.
209     GLF_API
210     GLuint GetFramebufferMSId() const;
211 
212     /// Binds the framebuffer.
213     GLF_API
214     void Bind();
215 
216     /// Unbinds the framebuffer.
217     GLF_API
218     void Unbind();
219 
220     /// Returns whether the framebuffer is currently bound.
221     GLF_API
222     bool IsBound() const;
223 
224     /// Resolve the MSAA framebuffer to a regular framebuffer. If there
225     /// is no MSAA enabled, this function does nothing.
226     GLF_API
227     void Resolve();
228 
229     /// Resolve several MSAA framebuffers at once. If any framebuffers don't
230     /// have MSAA enabled, nothing happens to them.
231     GLF_API
232     static void Resolve(const std::vector<GlfDrawTarget*>& drawTargets);
233 
234     /// Updates the contents signature for attached textures
235     /// to allow downstream consumers to know that the texture image
236     /// data may have changed.
237     GLF_API
238     void TouchContents();
239 
240     /// Returns whether the enclosed framebuffer object is complete.
241     /// If \a reason is non-NULL, and this framebuffer is not valid,
242     /// sets \a reason to the reason why not.
243     GLF_API
244     bool IsValid(std::string * reason = NULL);
245 
246 protected:
247 
248     /// Weak/Ref-based container for the the map of texture attachments.
249     /// Multiple GlfDrawTargets can jointly share their attachment textures :
250     /// this construction allows the use of a RefPtr on the map of attachments.
251     class AttachmentsContainer : public TfRefBase, public TfWeakBase {
252     public:
253         AttachmentsMap attachments;
254     };
255 
256     GLF_API
257     GlfDrawTarget( GfVec2i const & size, bool requestMSAA );
258 
259     GLF_API
260     GlfDrawTarget( GlfDrawTargetPtr const & drawtarget );
261 
262     GLF_API
263     virtual ~GlfDrawTarget();
264 
265 private:
266     void _GenFrameBuffer();
267 
268     void _BindAttachment( GlfDrawTarget::AttachmentRefPtr const & a );
269 
270     GLuint _AllocAttachment( GLenum format, GLenum type );
271 
272     AttachmentsMap & _GetAttachments() const;
273 
274     void _DeleteAttachments( );
275 
276     void _AllocDepth( );
277 
278     bool _Validate(std::string * reason = NULL);
279 
280     void _SaveBindingState();
281 
282     void _RestoreBindingState();
283 
284     void _Resolve();
285 
286     GLuint _framebuffer;
287     GLuint _framebufferMS;
288 
289     GLuint _unbindRestoreReadFB,
290            _unbindRestoreDrawFB;
291 
292     int _bindDepth;
293 
294     GfVec2i _size;
295 
296     unsigned int _numSamples;
297 
298     TfRefPtr<AttachmentsContainer> _attachmentsPtr;
299     GlfGLContextSharedPtr _owningContext;
300 };
301 
302 
303 PXR_NAMESPACE_CLOSE_SCOPE
304 
305 #endif  // GLF_DRAW_TARGET_H
306