1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkOpenGLRenderWindow.h
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 /**
16  * @class   vtkOpenGLRenderWindow
17  * @brief   OpenGL rendering window
18  *
19  * vtkOpenGLRenderWindow is a concrete implementation of the abstract class
20  * vtkRenderWindow. vtkOpenGLRenderer interfaces to the OpenGL graphics
21  * library. Application programmers should normally use vtkRenderWindow
22  * instead of the OpenGL specific version.
23 */
24 
25 #ifndef vtkOpenGLRenderWindow_h
26 #define vtkOpenGLRenderWindow_h
27 
28 #include "vtkRect.h" // for vtkRecti
29 #include "vtkRenderWindow.h"
30 #include "vtkRenderingOpenGL2Module.h" // For export macro
31 #include "vtkType.h"                   // for ivar
32 #include <map>                         // for ivar
33 #include <set>                         // for ivar
34 #include <string>                      // for ivar
35 
36 class vtkIdList;
37 class vtkOpenGLBufferObject;
38 class vtkOpenGLHardwareSupport;
39 class vtkOpenGLShaderCache;
40 class vtkOpenGLVertexBufferObjectCache;
41 class vtkOpenGLVertexArrayObject;
42 class vtkShaderProgram;
43 class vtkStdString;
44 class vtkTexture;
45 class vtkTextureObject;
46 class vtkTextureUnitManager;
47 class vtkGenericOpenGLResourceFreeCallback;
48 class vtkOpenGLState;
49 
50 class VTKRENDERINGOPENGL2_EXPORT vtkOpenGLRenderWindow : public vtkRenderWindow
51 {
52 public:
53   vtkTypeMacro(vtkOpenGLRenderWindow, vtkRenderWindow);
54   void PrintSelf(ostream& os, vtkIndent indent) override;
55 
56   /**
57    * What rendering backend has the user requested
58    */
59   const char *GetRenderingBackend() override;
60 
61   //@{
62   /**
63    * Set/Get the maximum number of multisamples
64    */
65   static void SetGlobalMaximumNumberOfMultiSamples(int val);
66   static int  GetGlobalMaximumNumberOfMultiSamples();
67   //@}
68 
69   //@{
70   /**
71    * Set/Get the pixel data of an image, transmitted as RGBRGB...
72    */
73   unsigned char *GetPixelData(int x,int y,int x2,int y2,int front,int right)
74                              override;
75   int GetPixelData(int x,int y,int x2,int y2, int front,
76                    vtkUnsignedCharArray *data, int right) override;
77   int SetPixelData(int x,int y,int x2,int y2,unsigned char *data,
78                    int front, int right) override;
79   int SetPixelData(int x,int y,int x2,int y2,
80                    vtkUnsignedCharArray *data, int front, int right)
81                    override;
82   //@}
83 
84   //@{
85   /**
86    * Set/Get the pixel data of an image, transmitted as RGBARGBA...
87    */
88   float *GetRGBAPixelData(int x,int y,int x2,int y2,int front,int right=0)
89                          override;
90   int GetRGBAPixelData(int x,int y,int x2,int y2, int front,
91                        vtkFloatArray* data, int right=0) override;
92   int SetRGBAPixelData(int x,int y,int x2,int y2, float *data,
93                        int front, int blend=0, int right=0) override;
94   int SetRGBAPixelData(int x,int y,int x2,int y2, vtkFloatArray *data,
95                        int front, int blend=0, int right=0) override;
96   void ReleaseRGBAPixelData(float *data) override;
97   unsigned char *GetRGBACharPixelData(int x,int y,int x2,int y2,
98                                       int front, int right=0) override;
99   int GetRGBACharPixelData(int x,int y,int x2,int y2, int front,
100                            vtkUnsignedCharArray *data, int right=0)
101                           override;
102   int SetRGBACharPixelData(int x, int y, int x2, int y2,
103                            unsigned char *data, int front,
104                            int blend=0, int right=0) override;
105   int SetRGBACharPixelData(int x,int y,int x2,int y2,
106                            vtkUnsignedCharArray *data, int front,
107                            int blend=0,int right=0) override;
108   //@}
109 
110   //@{
111   /**
112    * Set/Get the zbuffer data from an image
113    */
114   float *GetZbufferData( int x1, int y1, int x2, int y2 ) override;
115   int GetZbufferData( int x1, int y1, int x2, int y2, float* z ) override;
116   int GetZbufferData( int x1, int y1, int x2, int y2,
117                               vtkFloatArray* z ) override;
118   int SetZbufferData( int x1, int y1, int x2, int y2, float *buffer ) override;
119   int SetZbufferData( int x1, int y1, int x2, int y2,
120                               vtkFloatArray *buffer ) override;
121   //@}
122 
123 
124   /**
125    * Activate a texture unit for this texture
126    */
127   void ActivateTexture(vtkTextureObject *);
128 
129   /**
130    * Deactivate a previously activated texture
131    */
132   void DeactivateTexture(vtkTextureObject *);
133 
134   /**
135    * Get the texture unit for a given texture object
136    */
137   int GetTextureUnitForTexture(vtkTextureObject *);
138 
139   /**
140    * Get the size of the depth buffer.
141    */
142   int GetDepthBufferSize() override;
143 
144   /**
145    * Is this window/fo in sRGB colorspace
146    */
147   bool GetUsingSRGBColorSpace();
148 
149   /**
150    * Get the size of the color buffer.
151    * Returns 0 if not able to determine otherwise sets R G B and A into buffer.
152    */
153   int GetColorBufferSizes(int *rgba) override;
154 
155   /**
156    * Get the internal format of current attached texture or render buffer.
157    * attachmentPoint is the index of attachment.
158    * Returns 0 if not able to determine.
159    */
160   int GetColorBufferInternalFormat(int attachmentPoint);
161 
162   //@{
163   /**
164    * Set the size of the window in screen coordinates in pixels.
165    */
166   void SetSize(int a[2]) override;
167   void SetSize(int,int) override;
168   //@}
169 
170   /**
171    * Initialize OpenGL for this window.
172    */
173   virtual void OpenGLInit();
174 
175   // Initialize the state of OpenGL that VTK wants for this window
176   virtual void OpenGLInitState();
177 
178   // Initialize VTK for rendering in a new OpenGL context
179   virtual void OpenGLInitContext();
180 
181   /**
182    * Get the major and minor version numbers of the OpenGL context we are using
183    * ala 3.2, 3.3, 4.0, etc... returns 0,0 if opengl has not been initialized
184    * yet
185    */
186   void GetOpenGLVersion(int &major, int &minor);
187 
188   /**
189    * Return the OpenGL name of the back left buffer.
190    * It is GL_BACK_LEFT if GL is bound to the window-system-provided
191    * framebuffer. It is vtkgl::COLOR_ATTACHMENT0_EXT if GL is bound to an
192    * application-created framebuffer object (GPU-based offscreen rendering)
193    * It is used by vtkOpenGLCamera.
194    */
195   unsigned int GetBackLeftBuffer();
196 
197   /**
198    * Return the OpenGL name of the back right buffer.
199    * It is GL_BACK_RIGHT if GL is bound to the window-system-provided
200    * framebuffer. It is vtkgl::COLOR_ATTACHMENT0_EXT+1 if GL is bound to an
201    * application-created framebuffer object (GPU-based offscreen rendering)
202    * It is used by vtkOpenGLCamera.
203    */
204   unsigned int GetBackRightBuffer();
205 
206   /**
207    * Return the OpenGL name of the front left buffer.
208    * It is GL_FRONT_LEFT if GL is bound to the window-system-provided
209    * framebuffer. It is vtkgl::COLOR_ATTACHMENT0_EXT if GL is bound to an
210    * application-created framebuffer object (GPU-based offscreen rendering)
211    * It is used by vtkOpenGLCamera.
212    */
213   unsigned int GetFrontLeftBuffer();
214 
215   /**
216    * Return the OpenGL name of the front right buffer.
217    * It is GL_FRONT_RIGHT if GL is bound to the window-system-provided
218    * framebuffer. It is vtkgl::COLOR_ATTACHMENT0_EXT+1 if GL is bound to an
219    * application-created framebuffer object (GPU-based offscreen rendering)
220    * It is used by vtkOpenGLCamera.
221    */
222   unsigned int GetFrontRightBuffer();
223 
224   /**
225    * Return the OpenGL name of the back left buffer.
226    * It is GL_BACK if GL is bound to the window-system-provided
227    * framebuffer. It is vtkgl::COLOR_ATTACHMENT0_EXT if GL is bound to an
228    * application-created framebuffer object (GPU-based offscreen rendering)
229    * It is used by vtkOpenGLCamera.
230    */
231   unsigned int GetBackBuffer();
232 
233   /**
234    * Return the OpenGL name of the front left buffer.
235    * It is GL_FRONT if GL is bound to the window-system-provided
236    * framebuffer. It is vtkgl::COLOR_ATTACHMENT0_EXT if GL is bound to an
237    * application-created framebuffer object (GPU-based offscreen rendering)
238    * It is used by vtkOpenGLCamera.
239    */
240   unsigned int GetFrontBuffer();
241 
242   /**
243    * Get the time when the OpenGL context was created.
244    */
245   virtual vtkMTimeType GetContextCreationTime();
246 
247   //@{
248   /**
249    * Returns an Shader Cache object
250    */
251   vtkGetObjectMacro(ShaderCache,vtkOpenGLShaderCache);
252   //@}
253 
254   //@{
255   /**
256    * Returns an Shader Cache object
257    */
258   vtkGetObjectMacro(VBOCache,vtkOpenGLVertexBufferObjectCache);
259   //@}
260 
261   //@{
262   /**
263    * Returns the current default FBO (0 when OffScreenRendering is inactive).
264    */
265   vtkGetMacro(FrameBufferObject, unsigned int);
266   //@}
267 
268   /**
269    * Returns its texture unit manager object. A new one will be created if one
270    * hasn't already been set up.
271    */
272   vtkTextureUnitManager *GetTextureUnitManager();
273 
274   /**
275    * Block the thread until the actual rendering is finished().
276    * Useful for measurement only.
277    */
278   void WaitForCompletion() override;
279 
280   /**
281    * Replacement for the old glDrawPixels function
282    */
283   virtual void DrawPixels(int x1, int y1, int x2, int y2,
284               int numComponents, int dataType, void *data);
285 
286   /**
287    * Replacement for the old glDrawPixels function, but it allows
288    * for scaling the data and using only part of the texture
289    */
290   virtual void DrawPixels(
291     int dstXmin, int dstYmin, int dstXmax, int dstYmax,
292     int srcXmin, int srcYmin, int srcXmax, int srcYmax,
293     int srcWidth, int srcHeight, int numComponents, int dataType, void *data);
294 
295   /**
296    * Replacement for the old glDrawPixels function.  This simple version draws all
297    * the data to the entire current viewport scaling as needed.
298    */
299   virtual void DrawPixels(
300     int srcWidth, int srcHeight, int numComponents, int dataType, void *data);
301 
302   /**
303    * Return the largest line width supported by the hardware
304    */
GetMaximumHardwareLineWidth()305   virtual float GetMaximumHardwareLineWidth() {
306     return this->MaximumHardwareLineWidth; };
307 
308   /**
309    * Returns true if driver has an
310    * EGL/OpenGL bug that makes vtkChartsCoreCxx-TestChartDoubleColors and other tests to fail
311    * because point sprites don't work correctly (gl_PointCoord is undefined) unless
312    * glEnable(GL_POINT_SPRITE)
313    */
IsPointSpriteBugPresent()314   virtual bool IsPointSpriteBugPresent()
315   {
316     return 0;
317   }
318 
319   /**
320    * Get a mapping of vtk data types to native texture formats for this window
321    * we put this on the RenderWindow so that every texture does not have to
322    * build these structures themselves
323    */
324   int GetDefaultTextureInternalFormat(
325     int vtktype, int numComponents,
326     bool needInteger, bool needFloat, bool needSRGB);
327 
328   /**
329    * Return a message profiding additional details about the
330    * results of calling SupportsOpenGL()  This can be used
331    * to retrieve more specifics about what failed
332    */
GetOpenGLSupportMessage()333   std::string GetOpenGLSupportMessage()
334   {
335     return this->OpenGLSupportMessage;
336   }
337 
338   // Create and bind offscreen rendering buffers without destroying the current
339   // OpenGL context. This allows to temporary switch to offscreen rendering
340   // (ie. to make a screenshot even if the window is hidden).
341   // Return if the creation was successful (1) or not (0).
342   // Note: This function requires that the device supports OpenGL framebuffer extension.
343   // The function has no effect if OffScreenRendering is ON.
344   int SetUseOffScreenBuffers(bool offScreen) override;
345   bool GetUseOffScreenBuffers() override;
346 
347   /**
348    * Does this render window support OpenGL? 0-false, 1-true
349    */
350   int SupportsOpenGL() override;
351 
352   /**
353    * Get report of capabilities for the render window
354    */
355   const char *ReportCapabilities() override;
356 
357   /**
358    * Initialize the rendering window.  This will setup all system-specific
359    * resources.  This method and Finalize() must be symmetric and it
360    * should be possible to call them multiple times, even changing WindowId
361    * in-between.  This is what WindowRemap does.
362    */
Initialize(void)363   virtual void Initialize(void) {};
364 
365   std::set<vtkGenericOpenGLResourceFreeCallback *> Resources;
366 
RegisterGraphicsResources(vtkGenericOpenGLResourceFreeCallback * cb)367   void RegisterGraphicsResources(vtkGenericOpenGLResourceFreeCallback *cb) {
368     std::set<vtkGenericOpenGLResourceFreeCallback *>::iterator it
369      = this->Resources.find(cb);
370     if (it == this->Resources.end())
371     {
372       this->Resources.insert(cb);
373     }
374   }
375 
UnregisterGraphicsResources(vtkGenericOpenGLResourceFreeCallback * cb)376   void UnregisterGraphicsResources(vtkGenericOpenGLResourceFreeCallback *cb) {
377     std::set<vtkGenericOpenGLResourceFreeCallback *>::iterator it
378      = this->Resources.find(cb);
379     if (it != this->Resources.end())
380     {
381       this->Resources.erase(it);
382     }
383   }
384 
385   /**
386    * Ability to push and pop this window's context
387    * as the current context. The idea being to
388    * if needed make this window's context current
389    * and when done releasing resources restore
390    * the prior context.  The default implementation
391    * here is only meant as a backup for subclasses
392    * that lack a proper implementation.
393    */
PushContext()394   virtual void PushContext() { this->MakeCurrent(); }
PopContext()395   virtual void PopContext() {}
396 
397   /**
398    * Initialize the render window from the information associated
399    * with the currently activated OpenGL context.
400    */
401   bool InitializeFromCurrentContext() override;
402 
403   /**
404    * Returns the id for the frame buffer object, if any, used by the render window
405    * in which the window does all its rendering. This may be 0, in which case
406    * the render window is rendering to the default OpenGL render buffers.
407    *
408    * @returns the name (or id) of the frame buffer object to render to.
409    */
410   vtkGetMacro(DefaultFrameBufferId, unsigned int);
411 
412   /**
413    * Set the number of vertical syncs required between frames.
414    * A value of 0 means swap buffers as quickly as possible
415    * regardless of the vertical refresh. A value of 1 means swap
416    * buffers in sync with the vertical refresh to eliminate tearing.
417    * A value of -1 means use a value of 1 unless we missed a frame
418    * in which case swap immediately. Returns true if the call
419    * succeeded.
420    */
SetSwapControl(int)421   virtual bool SetSwapControl(int ) { return false; }
422 
423   // Get the state object used to keep track of
424   // OpenGL state
GetState()425   virtual vtkOpenGLState *GetState() {
426     return this->State; }
427 
428   // Get a VBO that can be shared by many
429   // It consists of normalized display
430   // coordinates for a quad and tcoords
431   vtkOpenGLBufferObject *GetTQuad2DVBO();
432 
433   // Activate and return thje texture unit for a generic 2d 64x64
434   // float greyscale noise texture ranging from 0 to 1. The texture is
435   // generated using PerlinNoise.  This textur eunit will automatically
436   // be deactivated at the end of the render process.
437   int GetNoiseTextureUnit();
438 
439   /**
440    * Update the system, if needed, due to stereo rendering. For some stereo
441    * methods, subclasses might need to switch some hardware settings here.
442    */
443   void StereoUpdate() override;
444 
445   /**
446    * Intermediate method performs operations required between the rendering
447    * of the left and right eye.
448    */
449   void StereoMidpoint() override;
450 
451   /**
452    * Handle opengl specific code and calls superclass
453    */
454   void Render() override;
455 
456 protected:
457   vtkOpenGLRenderWindow();
458   ~vtkOpenGLRenderWindow() override;
459 
460   vtkOpenGLShaderCache *ShaderCache;
461   vtkOpenGLVertexBufferObjectCache *VBOCache;
462 
463   vtkOpenGLState *State;
464 
465   // used in testing for opengl support
466   // in the SupportsOpenGL() method
467   bool OpenGLSupportTested;
468   int OpenGLSupportResult;
469   std::string OpenGLSupportMessage;
470 
471   int TextureInternalFormats[VTK_UNICODE_STRING][3][5];
472   void InitializeTextureInternalFormats();
473 
474   std::map<const vtkTextureObject *, int> TextureResourceIds;
475 
476   virtual int ReadPixels(const vtkRecti& rect, int front, int glFormat, int glType, void* data, int right=0);
477 
478   /**
479    * Create an offScreen window based on OpenGL framebuffer extension.
480    * Return if the creation was successful or not.
481    * \pre positive_width: width>0
482    * \pre positive_height: height>0
483    * \pre not_initialized: !OffScreenUseFrameBuffer
484    * \post valid_result: (result==0 || result==1)
485    * && (result implies OffScreenUseFrameBuffer)
486    */
487   int CreateHardwareOffScreenWindow(int width, int height);
488 
489   int CreateHardwareOffScreenBuffers(int width, int height, bool bind = false);
490   void BindHardwareOffScreenBuffers();
491 
492   /**
493    * Destroy an offscreen window based on OpenGL framebuffer extension.
494    * \pre initialized: OffScreenUseFrameBuffer
495    * \post destroyed: !OffScreenUseFrameBuffer
496    */
497   void DestroyHardwareOffScreenWindow();
498 
499   void UnbindHardwareOffScreenBuffers();
500   void DestroyHardwareOffScreenBuffers();
501 
502   /**
503    * Flag telling if a framebuffer-based offscreen is currently in use.
504    */
505   int OffScreenUseFrameBuffer;
506 
507   //@{
508   /**
509    * Variables used by the framebuffer-based offscreen method.
510    */
511   int NumberOfFrameBuffers;
512   unsigned int TextureObjects[4]; // really GLuint
513   unsigned int FrameBufferObject; // really GLuint
514   unsigned int DepthRenderBufferObject; // really GLuint
515   int HardwareBufferSize[2];
516   bool HardwareOffScreenBuffersBind;
517   //@}
518 
519   /**
520    * Create a not-off-screen window.
521    */
522   virtual void CreateAWindow() = 0;
523 
524   /**
525    * Destroy a not-off-screen window.
526    */
527   virtual void DestroyWindow() = 0;
528 
529   /**
530    * Free up any graphics resources associated with this window
531    * a value of NULL means the context may already be destroyed
532    */
533   virtual void ReleaseGraphicsResources(vtkRenderWindow *);
534 
535   /**
536    * Set the texture unit manager.
537    */
538   void SetTextureUnitManager(vtkTextureUnitManager *textureUnitManager);
539 
540 
541   /**
542    * Query and save OpenGL state
543    */
544   void SaveGLState();
545 
546   /**
547    * Restore OpenGL state at end of the rendering
548    */
549   void RestoreGLState();
550 
551   std::map<std::string, int> GLStateIntegers;
552 
553   unsigned int BackLeftBuffer;
554   unsigned int BackRightBuffer;
555   unsigned int FrontLeftBuffer;
556   unsigned int FrontRightBuffer;
557   unsigned int FrontBuffer;
558   unsigned int BackBuffer;
559   unsigned int DefaultFrameBufferId;
560 
561   /**
562    * Flag telling if the context has been created here or was inherited.
563    */
564   int OwnContext;
565 
566   vtkTimeStamp ContextCreationTime;
567 
568   vtkTextureUnitManager *TextureUnitManager;
569 
570   vtkTextureObject *DrawPixelsTextureObject;
571 
572   bool Initialized; // ensure glewinit has been called
573   bool GlewInitValid; // Did glewInit initialize with a valid state?
574 
575   float MaximumHardwareLineWidth;
576 
577   char *Capabilities;
578 
579   // used for fast quad rendering
580   vtkOpenGLBufferObject *TQuad2DVBO;
581 
582   // noise texture
583   vtkTextureObject *NoiseTextureObject;
584 
585 private:
586   vtkOpenGLRenderWindow(const vtkOpenGLRenderWindow&) = delete;
587   void operator=(const vtkOpenGLRenderWindow&) = delete;
588 };
589 
590 #endif
591