HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
glContext.h
Go to the documentation of this file.
1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 #ifndef PXR_IMAGING_GLF_GL_CONTEXT_H
8 #define PXR_IMAGING_GLF_GL_CONTEXT_H
9 
10 #include "pxr/pxr.h"
11 #include "pxr/imaging/glf/api.h"
12 #include "pxr/base/arch/threads.h"
13 
14 #include <memory>
15 
17 
18 
19 typedef std::shared_ptr<class GlfGLContext> GlfGLContextSharedPtr;
20 
21 /// \class GlfGLContext
22 ///
23 /// Provides window system independent access to GL contexts.
24 ///
25 /// All OpenGL operation occurs within a current GL Context. The GL
26 /// contexts used by an application are allocated and managed by the window
27 /// system interface layer, i.e. Qt, GLUT, GLX, etc.
28 ///
29 /// This class provides a way for lower-level OpenGL framework code to
30 /// get useful information about the GL contexts in use by the application.
31 ///
32 /// This mechanism depends on the application code registering callbacks to
33 /// provide access to its GL contexts.
34 ///
36 {
37 public:
38  GLF_API
39  virtual ~GlfGLContext();
40 
41  // Disallow copies
42  GlfGLContext(const GlfGLContext&) = delete;
43  GlfGLContext& operator=(const GlfGLContext&) = delete;
44 
45  /// Returns an instance for the current GL context.
46  GLF_API
48 
49  /// Returns an instance for the shared GL context.
50  GLF_API
52 
53  /// Makes \p context current if valid, otherwise makes no context current.
54  GLF_API
55  static void MakeCurrent(const GlfGLContextSharedPtr& context);
56 
57  /// Returns \c true if \a context1 and \a context2 are sharing.
58  GLF_API
59  static bool AreSharing(GlfGLContextSharedPtr const & context1,
60  GlfGLContextSharedPtr const & context2);
61 
62  /// Returns whether this interface has been initialized.
63  GLF_API
64  static bool IsInitialized();
65 
66  /// Returns \c true if this context is current.
67  GLF_API
68  bool IsCurrent() const;
69 
70 private:
71  /// Makes this context current.
72  ///
73  /// If the context is not valid this does nothing.
74  void MakeCurrent();
75 
76 public:
77  /// Makes no context current.
78  GLF_API
79  static void DoneCurrent();
80 
81  /// Returns \c true if this context is sharing with \a otherContext.
82  GLF_API
83  bool IsSharing(GlfGLContextSharedPtr const & otherContext);
84 
85  /// Returns \c true if this context is valid.
86  virtual bool IsValid() const = 0;
87 
88  /// Creates a new GlfContext that shares GL resources with this context.
89  /// The purpose of this function is to be able to create a new GL context
90  /// on a second thread that shares with the context on the main-thread.
91  /// If the GlfContext implementation does not support sharing contexts
92  /// null is returned. Example usage:
93  /// Main-thread:
94  /// RegisterGLContextCallbacks();
95  /// GlfGLContext::MakeCurrent(...);
96  /// Second-thread:
97  /// s = GetCurrentGLContext();
98  /// c = s->CreateSharingContext();
99  virtual GlfGLContextSharedPtr CreateSharingContext() {return nullptr;}
100 
101 protected:
102  GLF_API
103  GlfGLContext();
104 
105  /// Makes this context current.
106  virtual void _MakeCurrent() = 0;
107 
108  /// Returns \c true if this context is sharing with \a rhs.
109  virtual bool _IsSharing(const GlfGLContextSharedPtr& rhs) const = 0;
110 
111  /// Returns \c true if this context is equal to \p rhs.
112  virtual bool _IsEqual(const GlfGLContextSharedPtr& rhs) const = 0;
113 };
114 
115 /// \class GlfGLContextScopeHolder
116 ///
117 /// Helper class to make a GL context current.
118 ///
119 /// It is often useful to wrap a dynamic GL resource with a class interface.
120 ///
121 /// In addition to providing API to make it more convenient to use the
122 /// underlying GL resource, the lifetime of the underlying resource can
123 /// be tied to the lifetime of a wrapper object instance, e.g. allocate
124 /// the GL resource during construction, delete the GL resource during
125 /// destruction.
126 ///
127 /// While the construction and use of these kinds of wrapper objects is
128 /// usually pretty safe and straightforward, it can be more difficult to
129 /// manage destruction. Specifically, it can be hard to guarantee that
130 /// a suitable GL context is current at the time that a wrapper object
131 /// instance is destroyed. If a suitable context is not current, then
132 /// it will not be possible to delete the underlying resource, which
133 /// may cause the resource to remain allocated, which will then result
134 /// in a resource leak.
135 ///
136 /// Typically, these GL resources are allocated from contexts which are
137 /// sharing the GL resources. In which case it is sufficient for any one
138 /// one of the sharing contexts to be current in order to be able to safely
139 /// delete the GL resource from the destructor of a wrapper object.
140 ///
141 /// GlfGLContext and GlfGLContextScopeHolder can help.
142 ///
143 /// When GlfGLContext has been initialized, i.e. when suitable context
144 /// callbacks have been registered, we can use GlfGLContext to make
145 /// a GL context current.
146 ///
147 /// GlfGLContextScopeHolder does this automatically for the duration
148 /// of a code block.
149 ///
150 /// The underlying calls to make GL contexts current can be moderately
151 /// expensive. So, this mechanism should be used carefully.
152 ///
154 {
155 public:
156  /// Make the given context current and restore the current context
157  /// when this object is destroyed.
158  GLF_API
159  explicit GlfGLContextScopeHolder(const GlfGLContextSharedPtr& newContext);
160 
161  GLF_API
163 
164  GlfGLContextScopeHolder(const GlfGLContextScopeHolder&) = delete;
165  GlfGLContextScopeHolder& operator=(const GlfGLContextScopeHolder) = delete;
166 
167 protected:
168  GLF_API
169  void _MakeNewContextCurrent();
170  GLF_API
171  void _RestoreOldContext();
172 
173 private:
174  GlfGLContextSharedPtr _newContext;
175  GlfGLContextSharedPtr _oldContext;
176 };
177 
178 /// \class GlfSharedGLContextScopeHolder
179 ///
180 /// Helper class to make the shared GL context current.
181 ///
182 /// Example:
183 ///
184 /// \code
185 /// class MyTexture {
186 /// public:
187 /// MyTexture() : _textureId(0) {
188 /// // allocate from the shared context pool.
189 /// GlfSharedGLContextScopeHolder sharedContextScopeHolder;
190 /// glGenTextures(1, &_textureId);
191 /// }
192 ///
193 /// ~MyTexture() {
194 /// // delete from the shared context pool.
195 /// GlfSharedGLContextScopeHolder sharedContextScopeHolder;
196 /// glDeleteTextures(1, &_texureId);
197 /// _textureId = 0;
198 /// }
199 ///
200 /// // The caller is responsible for making sure that a suitable
201 /// // GL context is current before calling other methods.
202 ///
203 /// void Bind() {
204 /// glBindTexture(GL_TEXTURE_2D, _textureId);
205 /// }
206 ///
207 /// void Unbind() {
208 /// glBindTexture(GL_TEXTURE_2D, 0);
209 /// }
210 ///
211 /// ...
212 ///
213 /// private:
214 /// GLuint _textureId;
215 ///
216 /// };
217 /// \endcode
218 ///
220 {
221 public:
223  GlfGLContextScopeHolder(_GetSharedContext())
224  {
225  // Do nothing
226  }
227 
228 private:
229  static GlfGLContextSharedPtr _GetSharedContext()
230  {
233  }
234  return GlfGLContextSharedPtr();
235  }
236 };
237 
238 #define API_GLF_HAS_ANY_GL_CONTEXT_SCOPE_HOLDER 1
239 
240 /// \class GlfAnyGLContextScopeHolder
241 ///
242 /// Helper class to make the shared GL context current if there is no
243 /// valid current context, or when the current context isn't sharing with the
244 /// shared context.
245 /// This mechanism lets us skip context switches to the shared context (see
246 /// GlfSharedGLContextScopeHolder) when possible, while ensuring that we have a
247 /// valid GL context prior to any resource allocation or destruction.
248 ///
249 /// Example:
250 ///
251 /// \code
252 /// class MyTexture {
253 /// public:
254 /// MyTexture() : _textureId(0) {
255 /// // Ensure we have valid GL context to allocate
256 /// GlfAnyGLContextScopeHolder anyContextScopeHolder;
257 /// glGenTextures(1, &_textureId);
258 /// }
259 ///
260 /// ~MyTexture() {
261 /// // Ensure we have valid GL context to delete
262 /// GlfAnyGLContextScopeHolder anyContextScopeHolder;
263 /// glDeleteTextures(1, &_texureId);
264 /// _textureId = 0;
265 /// }
266 ///
267 /// // The caller is responsible for making sure that a suitable
268 /// // GL context is current before calling other methods.
269 ///
270 /// void Bind() {
271 /// glBindTexture(GL_TEXTURE_2D, _textureId);
272 /// }
273 ///
274 /// void Unbind() {
275 /// glBindTexture(GL_TEXTURE_2D, 0);
276 /// }
277 ///
278 /// ...
279 ///
280 /// private:
281 /// GLuint _textureId;
282 ///
283 /// };
284 /// \endcode
285 ///
287 {
288 public:
290  GlfGLContextScopeHolder(_GetAnyContext())
291  {
292  // Do nothing
293  }
294 
295 private:
296  static GlfGLContextSharedPtr _GetAnyContext()
297  {
299  GlfGLContextSharedPtr const current =
301  if (!(current &&
302  current->IsValid() &&
303  current->IsSharing(GlfGLContext::GetSharedGLContext()))) {
305  }
306  }
307  return GlfGLContextSharedPtr();
308  }
309 };
310 
311 /// \class GlfGLContextRegistrationInterface
312 ///
313 /// Interface for registering a GlfGLContext system.
314 ///
315 /// If you subclass GlfGLContext you should subclass this type and
316 /// instantiate an instance on the heap. It will be cleaned up
317 /// automatically.
319 {
320 public:
321  GLF_API
323 
324  // Disallow copies
326  const GlfGLContextRegistrationInterface&) = delete;
328  const GlfGLContextRegistrationInterface&) = delete;
329 
330  /// If this GLContext system supports a shared context this should
331  /// return it. This will be called at most once.
332  virtual GlfGLContextSharedPtr GetShared() = 0;
333 
334  /// Whatever your GLContext system thinks is the current GL context
335  /// may not really be the current context if another system has since
336  /// changed the context. This method should return what it thinks is
337  /// the current context. If it thinks there is no current context it
338  /// should return \c NULL.
339  virtual GlfGLContextSharedPtr GetCurrent() = 0;
340 
341 protected:
342  GLF_API
344 };
345 
346 
348 
349 #endif
GlfGLContext & operator=(const GlfGLContext &)=delete
static GLF_API bool IsInitialized()
Returns whether this interface has been initialized.
#define GLF_API
Definition: api.h:23
GLF_API GlfGLContext()
virtual void _MakeCurrent()=0
Makes this context current.
static GLF_API void DoneCurrent()
Makes no context current.
static GLF_API GlfGLContextSharedPtr GetSharedGLContext()
Returns an instance for the shared GL context.
virtual GLF_API ~GlfGLContext()
GLF_API void _MakeNewContextCurrent()
virtual bool IsValid() const =0
Returns true if this context is valid.
GlfGLContextScopeHolder & operator=(const GlfGLContextScopeHolder)=delete
virtual bool _IsEqual(const GlfGLContextSharedPtr &rhs) const =0
Returns true if this context is equal to rhs.
GLF_API bool IsCurrent() const
Returns true if this context is current.
GLF_API bool IsSharing(GlfGLContextSharedPtr const &otherContext)
Returns true if this context is sharing with otherContext.
virtual GLF_API ~GlfGLContextRegistrationInterface()
PXR_NAMESPACE_OPEN_SCOPE ARCH_API bool ArchIsMainThread()
std::shared_ptr< class GlfGLContext > GlfGLContextSharedPtr
Definition: drawTarget.h:33
virtual GlfGLContextSharedPtr CreateSharingContext()
Definition: glContext.h:99
static GLF_API bool AreSharing(GlfGLContextSharedPtr const &context1, GlfGLContextSharedPtr const &context2)
Returns true if context1 and context2 are sharing.
static GLF_API void MakeCurrent(const GlfGLContextSharedPtr &context)
Makes context current if valid, otherwise makes no context current.
GLF_API void _RestoreOldContext()
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1425
GLF_API GlfGLContextScopeHolder(const GlfGLContextSharedPtr &newContext)
PXR_NAMESPACE_OPEN_SCOPE typedef std::shared_ptr< class GlfGLContext > GlfGLContextSharedPtr
Definition: glContext.h:19
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
GlfGLContextRegistrationInterface & operator=(const GlfGLContextRegistrationInterface &)=delete
virtual bool _IsSharing(const GlfGLContextSharedPtr &rhs) const =0
Returns true if this context is sharing with rhs.
static GLF_API GlfGLContextSharedPtr GetCurrentGLContext()
Returns an instance for the current GL context.
virtual GlfGLContextSharedPtr GetShared()=0
GLF_API ~GlfGLContextScopeHolder()
virtual GlfGLContextSharedPtr GetCurrent()=0