0024001: Stereographic rendering support
[occt.git] / src / OpenGl / OpenGl_Context.hxx
1 // Created on: 2012-01-26
2 // Created by: Kirill GAVRILOV
3 // Copyright (c) 2012-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and / or modify it
8 // under the terms of the GNU Lesser General Public version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #ifndef _OpenGl_Context_H__
17 #define _OpenGl_Context_H__
18
19 #include <Aspect_Handle.hxx>
20 #include <Aspect_Drawable.hxx>
21 #include <Aspect_Display.hxx>
22 #include <Aspect_RenderingContext.hxx>
23 #include <Handle_OpenGl_Context.hxx>
24 #include <Handle_OpenGl_ShaderManager.hxx>
25 #include <NCollection_DataMap.hxx>
26 #include <NCollection_Map.hxx>
27 #include <NCollection_Handle.hxx>
28 #include <NCollection_Queue.hxx>
29 #include <Message.hxx>
30 #include <OpenGl_Caps.hxx>
31 #include <OpenGl_Resource.hxx>
32 #include <Standard_Transient.hxx>
33 #include <TCollection_AsciiString.hxx>
34 #include <Handle_OpenGl_Context.hxx>
35 #include <OpenGl_Clipping.hxx>
36 #include <OpenGl_GlCore11.hxx>
37
38 //! Forward declarations
39 struct OpenGl_GlCore12;
40 struct OpenGl_GlCore13;
41 struct OpenGl_GlCore14;
42 struct OpenGl_GlCore15;
43 struct OpenGl_GlCore20;
44 struct OpenGl_ArbVBO;
45 struct OpenGl_ArbTBO;
46 struct OpenGl_ArbIns;
47 struct OpenGl_ArbDbg;
48 struct OpenGl_ExtFBO;
49 struct OpenGl_ExtGS;
50
51 //! This class generalize access to the GL context and available extensions.
52 //!
53 //! Functions are grouped into structures and accessed as fields.
54 //! You should check the group for NULL before usage (if group is not NULL
55 //! then all functions are available):
56 //! @code
57 //!   if (myContext->core20 != NULL)
58 //!   {
59 //!     myGlProgram = myContext->core20->glCreateProgram();
60 //!     .. do more stuff ..
61 //!   }
62 //!   else
63 //!   {
64 //!     .. compatibility with outdated configurations ..
65 //!   }
66 //! @endcode
67 //!
68 //! Current implementation provide access to OpenGL core functionality up to 2.0 version
69 //! (core12, core13, core14, core15, fields core20).
70 //! within several extensions (arbVBO, extFBO, etc.).
71 //!
72 //! Simplified extensions classification:
73 //!  - prefixed with NV, AMD, ATI are vendor-specific (however may be provided by other vendors in some cases);
74 //!  - prefixed with EXT are accepted by 2+ vendors;
75 //!  - prefixed with ARB are accepted by Architecture Review Board and are candidates
76 //!    for inclusion into GL core functionality.
77 //! Some functionality can be represented in several extensions simultaneously.
78 //! In this case developer should be careful because different specification may differ
79 //! in aspects (like enumeration values and error-handling).
80 //!
81 //! Notice that some systems provide mechanisms to simultaneously incorporate with GL contexts
82 //! with different capabilities. Thats why OpenGl_Context should be initialized and used
83 //! for each GL context individually.
84 class OpenGl_Context : public Standard_Transient
85 {
86 public:
87
88   //! Function for getting power of to number larger or equal to input number.
89   //! @param theNumber    number to 'power of two'
90   //! @param theThreshold upper threshold
91   //! @return power of two number
92   inline static Standard_Integer GetPowerOfTwo (const Standard_Integer theNumber,
93                                                 const Standard_Integer theThreshold)
94   {
95     for (Standard_Integer p2 = 2; p2 <= theThreshold; p2 <<= 1)
96     {
97       if (theNumber <= p2)
98       {
99         return p2;
100       }
101     }
102     return theThreshold;
103   }
104
105 public:
106
107   //! Empty constructor. You should call Init() to perform initialization with bound GL context.
108   Standard_EXPORT OpenGl_Context (const Handle(OpenGl_Caps)& theCaps = NULL);
109
110   //! Destructor.
111   Standard_EXPORT virtual ~OpenGl_Context();
112
113   //! Share GL context resources.
114   //! theShareCtx - handle to context to retrieve handles to shared resources.
115   Standard_EXPORT void Share (const Handle(OpenGl_Context)& theShareCtx);
116
117   //! Initialize class from currently bound OpenGL context. Method should be called only once.
118   //! @return false if no GL context is bound to the current thread
119   Standard_EXPORT Standard_Boolean Init();
120
121   //! @return true if this context is valid (has been initialized)
122   inline Standard_Boolean IsValid() const
123   {
124     return myIsInitialized;
125   }
126
127 #if defined(_WIN32)
128   //! Initialize class from specified window and rendering context. Method should be called only once.
129   //! @return false if OpenGL context can not be bound to specified window
130   Standard_EXPORT Standard_Boolean Init (const Aspect_Handle           theWindow,
131                                          const Aspect_Handle           theWindowDC,
132                                          const Aspect_RenderingContext theGContext);
133
134   //! @return the window handle (HWND) currently bound to this OpenGL context
135   inline Aspect_Handle Window() const
136   {
137     return myWindow;
138   }
139
140 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
141   //! Initialize class from specified OpenGL context (NSOpenGLContext). Method should be called only once.
142   Standard_EXPORT Standard_Boolean Init (const void*                   theGContext);
143 #else
144   //! Initialize class from specified window and rendering context. Method should be called only once.
145   //! @return false if OpenGL context can not be bound to specified window
146   Standard_EXPORT Standard_Boolean Init (const Aspect_Drawable         theWindow,
147                                          const Aspect_Display          theDisplay,
148                                          const Aspect_RenderingContext theGContext);
149
150   //! @return the window handle (GLXDrawable) currently bound to this OpenGL context
151   inline Aspect_Drawable Window() const
152   {
153     return myWindow;
154   }
155 #endif
156
157   //! Check if theExtName extension is supported by active GL context.
158   Standard_EXPORT Standard_Boolean CheckExtension (const char* theExtName) const;
159
160   //! Check if theExtName extension is in extensions string.
161   Standard_EXPORT static Standard_Boolean CheckExtension (const char* theExtString,
162                                                           const char* theExtName);
163
164   //! Auxiliary template to retrieve GL function pointer.
165   //! Pointer to function retrieved from library is statically casted
166   //! to requested type - there no way to check real signature of exported function.
167   //! The context should be bound before call.
168   template <typename FuncType_t>
169   Standard_Boolean FindProc (const char* theFuncName,
170                              FuncType_t& theFuncPtr)
171   {
172     theFuncPtr = (FuncType_t )findProc (theFuncName);
173     return (theFuncPtr != NULL);
174   }
175
176   //! @return true if detected GL version is greater or equal to requested one.
177   inline Standard_Boolean IsGlGreaterEqual (const Standard_Integer theVerMajor,
178                                             const Standard_Integer theVerMinor) const
179   {
180     return (myGlVerMajor >  theVerMajor)
181         || (myGlVerMajor == theVerMajor && myGlVerMinor >= theVerMinor);
182   }
183
184   //! Clean up errors stack for this GL context (glGetError() in loop).
185   Standard_EXPORT void ResetErrors();
186
187   //! This method uses system-dependent API to retrieve information
188   //! about GL context bound to the current thread.
189   //! @return true if current thread is bound to this GL context
190   Standard_EXPORT Standard_Boolean IsCurrent() const;
191
192   //! Activates current context.
193   //! Class should be initialized with appropriate info.
194   Standard_EXPORT Standard_Boolean MakeCurrent();
195
196   //! Swap front/back buffers for this GL context (should be activated before!).
197   Standard_EXPORT void SwapBuffers();
198
199   //! Return true if active mode is GL_RENDER (cached state)
200   Standard_Boolean IsRender() const
201   {
202     return myRenderMode == GL_RENDER;
203   }
204
205   //! Return true if active mode is GL_FEEDBACK (cached state)
206   Standard_Boolean IsFeedback() const
207   {
208     return myRenderMode == GL_FEEDBACK;
209   }
210
211   //! This function retrieves information from GL about free GPU memory that is:
212   //!  - OS-dependent. On some OS it is per-process and on others - for entire system.
213   //!  - Vendor-dependent. Currently available only on NVIDIA and AMD/ATi drivers only.
214   //!  - Numbers meaning may vary.
215   //! You should use this info only for diagnostics purposes.
216   //! @return free GPU dedicated memory in bytes.
217   Standard_EXPORT Standard_Size AvailableMemory() const;
218
219   //! This function retrieves information from GL about GPU memory
220   //! and contains more vendor-specific values than AvailableMemory().
221   Standard_EXPORT TCollection_AsciiString MemoryInfo() const;
222
223   //! Access shared resource by its name.
224   //! @param  theKey - unique identifier;
225   //! @return handle to shared resource or NULL.
226   Standard_EXPORT const Handle(OpenGl_Resource)& GetResource (const TCollection_AsciiString& theKey) const;
227
228   //! Access shared resource by its name.
229   //! @param  theKey   - unique identifier;
230   //! @param  theValue - handle to fill;
231   //! @return true if resource was shared.
232   template<typename TheHandleType>
233   Standard_Boolean GetResource (const TCollection_AsciiString& theKey,
234                                 TheHandleType&                 theValue) const
235   {
236     const Handle(OpenGl_Resource)& aResource = GetResource (theKey);
237     if (aResource.IsNull())
238     {
239       return Standard_False;
240     }
241
242     theValue = TheHandleType::DownCast (aResource);
243     return !theValue.IsNull();
244   }
245
246   //! Register shared resource.
247   //! Notice that after registration caller shouldn't release it by himself -
248   //! it will be automatically released on context destruction.
249   //! @param theKey      - unique identifier, shouldn't be empty;
250   //! @param theResource - new resource to register, shouldn't be NULL.
251   Standard_EXPORT Standard_Boolean ShareResource (const TCollection_AsciiString& theKey,
252                                                   const Handle(OpenGl_Resource)& theResource);
253
254   //! Release shared resource.
255   //! If there are more than one reference to this resource
256   //! (also used by some other existing object) then call will be ignored.
257   //! This means that current object itself should nullify handle before this call.
258   //! Notice that this is unrecommended operation at all and should be used
259   //! only in case of fat resources to release memory for other needs.
260   //! @param theKey     unique identifier
261   //! @param theToDelay postpone release until next redraw call
262   Standard_EXPORT void ReleaseResource (const TCollection_AsciiString& theKey,
263                                         const Standard_Boolean         theToDelay = Standard_False);
264
265   //! Append resource to queue for delayed clean up.
266   //! Resources in this queue will be released at next redraw call.
267   Standard_EXPORT void DelayedRelease (Handle(OpenGl_Resource)& theResource);
268
269   //! Clean up the delayed release queue.
270   Standard_EXPORT void ReleaseDelayed();
271
272   //! @return tool for management of clippings within this context.
273   inline OpenGl_Clipping& ChangeClipping() { return myClippingState; }
274
275   //! @return tool for management of clippings within this context.
276   inline const OpenGl_Clipping& Clipping() const { return myClippingState; }
277
278   //! @return tool for management of shader programs within this context.
279   inline const Handle(OpenGl_ShaderManager)& ShaderManager() const { return myShaderManager; }
280
281 public:
282
283   //! @return maximum degree of anisotropy texture filter
284   Standard_EXPORT Standard_Integer MaxDegreeOfAnisotropy() const;
285
286   //! @return value for GL_MAX_TEXTURE_SIZE
287   Standard_EXPORT Standard_Integer MaxTextureSize() const;
288
289   //! Get maximum number of clip planes supported by OpenGl.
290   //! This value is implementation dependent. At least 6
291   //! planes should be supported by OpenGl (see specs).
292   //! @return value for GL_MAX_CLIP_PLANES
293   Standard_EXPORT Standard_Integer MaxClipPlanes() const;
294
295 public:
296
297   //! @return messenger instance
298   inline const Handle_Message_Messenger& Messenger() const
299   {
300     return ::Message::DefaultMessenger();
301   }
302
303   //! Callback for GL_ARB_debug_output extension
304   //! @param theSource   message source   within GL_DEBUG_SOURCE_   enumeration
305   //! @param theType     message type     within GL_DEBUG_TYPE_     enumeration
306   //! @param theId       message ID       within source
307   //! @param theSeverity message severity within GL_DEBUG_SEVERITY_ enumeration
308   //! @param theMessage  the message itself
309   Standard_EXPORT void PushMessage (const unsigned int theSource,
310                                     const unsigned int theType,
311                                     const unsigned int theId,
312                                     const unsigned int theSeverity,
313                                     const TCollection_ExtendedString& theMessage);
314
315
316
317   //! @return true if OpenGl context supports left and
318   //! right rendering buffers.
319   Standard_Boolean HasStereoBuffers() const
320   {
321     return myIsStereoBuffers;
322   }
323
324   //! Switch to left stereographic rendering buffer.
325   //! This method can be used to keep unchanged choise
326   //! of front/back/both buffer rendering.
327   Standard_EXPORT void SetDrawBufferLeft();
328
329   //! Switch to right stereographic rendering buffer.
330   //! This method can be used to keep unchanged choise
331   //! of front/back/both buffer rendering.
332   Standard_EXPORT void SetDrawBufferRight();
333
334   //! Switch to non-stereographic rendering buffer.
335   //! This method can be used to keep unchanged choise
336   //! of front/back/both buffer rendering.
337   Standard_EXPORT void SetDrawBufferMono();
338
339   //! Fetch OpenGl context state. This class tracks value of several OpenGl
340   //! state variables. Consulting the cached values is quicker than
341   //! doing the same via OpenGl API. Call this method if any of the controlled
342   //! OpenGl state variables has a possibility of being out-of-date.
343   Standard_EXPORT void FetchState();
344
345 private:
346
347   //! Wrapper to system function to retrieve GL function pointer by name.
348   Standard_EXPORT void* findProc (const char* theFuncName);
349
350   //! Read OpenGL version information from active context.
351   Standard_EXPORT void readGlVersion();
352
353   //! Private initialization function that should be called only once.
354   Standard_EXPORT void init();
355
356 public: // core profiles
357
358   OpenGl_GlCore12* core12;
359   OpenGl_GlCore13* core13;
360   OpenGl_GlCore14* core14;
361   OpenGl_GlCore15* core15;
362   OpenGl_GlCore20* core20;
363
364   Handle(OpenGl_Caps) caps; //!< context options
365
366 public: // extensions
367
368   Standard_Boolean arbNPTW; //!< GL_ARB_texture_non_power_of_two
369   OpenGl_ArbVBO*   arbVBO;  //!< GL_ARB_vertex_buffer_object
370   OpenGl_ArbTBO*   arbTBO;  //!< GL_ARB_texture_buffer_object
371   OpenGl_ArbIns*   arbIns;  //!< GL_ARB_draw_instanced
372   OpenGl_ArbDbg*   arbDbg;  //!< GL_ARB_debug_output
373   OpenGl_ExtFBO*   extFBO;  //!< GL_EXT_framebuffer_object
374   OpenGl_ExtGS*    extGS;   //!< GL_EXT_geometry_shader4
375   Standard_Boolean extBgra; //!< GL_EXT_bgra
376   Standard_Boolean extAnis; //!< GL_EXT_texture_filter_anisotropic
377   Standard_Boolean extPDS;  //!< GL_EXT_packed_depth_stencil
378   Standard_Boolean atiMem;  //!< GL_ATI_meminfo
379   Standard_Boolean nvxMem;  //!< GL_NVX_gpu_memory_info
380
381 private: // system-dependent fields
382
383 #if defined(_WIN32)
384   Aspect_Handle           myWindow;   //!< window handle (owner of GL context) : HWND
385   Aspect_Handle           myWindowDC; //!< Device Descriptor handle : HDC
386   Aspect_RenderingContext myGContext; //!< Rendering Context handle : HGLRC
387 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
388   void*                   myGContext; //!< Rendering Context handle : NSOpenGLContext
389 #else
390   Aspect_Drawable         myWindow;   //!< window handle (owner of GL context) : GLXDrawable
391   Aspect_Display          myDisplay;  //!< connection to the X-server : Display*
392   Aspect_RenderingContext myGContext; //!< X-GLX rendering context : GLXContext
393 #endif
394
395 private: // context info
396
397   typedef NCollection_DataMap<TCollection_AsciiString, Standard_Integer> OpenGl_DelayReleaseMap;
398   typedef NCollection_Handle<OpenGl_DelayReleaseMap> Handle(OpenGl_DelayReleaseMap);
399   typedef NCollection_DataMap<TCollection_AsciiString, Handle(OpenGl_Resource)> OpenGl_ResourcesMap;
400   typedef NCollection_Handle<OpenGl_ResourcesMap> Handle(OpenGl_ResourcesMap);
401   typedef NCollection_Queue<Handle(OpenGl_Resource)> OpenGl_ResourcesQueue;
402   typedef NCollection_Handle<OpenGl_ResourcesQueue> Handle(OpenGl_ResourcesQueue);
403
404   Handle(OpenGl_ResourcesMap)    mySharedResources; //!< shared resources with unique identification key
405   Handle(OpenGl_DelayReleaseMap) myDelayed;         //!< shared resources for delayed release
406   Handle(OpenGl_ResourcesQueue)  myReleaseQueue;    //!< queue of resources for delayed clean up
407
408   OpenGl_Clipping myClippingState; //!< state of clip planes
409
410   void*            myGlLibHandle;     //!< optional handle to GL library
411   OpenGl_GlCore20* myGlCore20;        //!< common structure for GL core functions upto 2.0
412   Standard_Integer myAnisoMax;        //!< maximum level of anisotropy texture filter
413   Standard_Integer myMaxTexDim;       //!< value for GL_MAX_TEXTURE_SIZE
414   Standard_Integer myMaxClipPlanes;   //!< value for GL_MAX_CLIP_PLANES
415   Standard_Integer myGlVerMajor;      //!< cached GL version major number
416   Standard_Integer myGlVerMinor;      //!< cached GL version minor number
417   Standard_Integer myRenderMode;      //!< value for active rendering mode
418   Standard_Boolean myIsInitialized;   //!< flag indicates initialization state
419   Standard_Boolean myIsStereoBuffers; //!< context supports stereo buffering
420   Standard_Integer myDrawBuffer;      //!< current draw buffer.
421
422   Handle(OpenGl_ShaderManager) myShaderManager; //! support object for managing shader programs
423
424 private:
425
426   //! Copying allowed only within Handles
427   OpenGl_Context            (const OpenGl_Context& );
428   OpenGl_Context& operator= (const OpenGl_Context& );
429
430 public:
431
432   DEFINE_STANDARD_RTTI(OpenGl_Context) // Type definition
433
434   friend class OpenGl_Window;
435
436 };
437
438 #endif // _OpenGl_Context_H__