1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkPixelBufferObject.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   vtkPixelBufferObject
17  * @brief   abstracts an OpenGL pixel buffer object.
18  *
19  * Provides low-level access to PBO mapped memory. Used to transfer raw data
20  * to/from PBO mapped memory and the application. Once data is transferred to
21  * the PBO it can then be transferred to the GPU (eg texture memory). Data may
22  * be uploaded from the application into a pixel buffer or downloaded from the
23  * pixel buffer to the application. The vtkTextureObject is used to transfer
24  * data from/to the PBO to/from texture memory on the GPU.
25  * @sa
26  * OpenGL Pixel Buffer Object Extension Spec (ARB_pixel_buffer_object):
27  * http://www.opengl.org/registry/specs/ARB/pixel_buffer_object.txt
28  * @warning
29  * Since most PBO mapped don't support double format all double data is converted to
30  * float and then uploaded.
31 */
32 
33 #ifndef vtkPixelBufferObject_h
34 #define vtkPixelBufferObject_h
35 
36 #include "vtkObject.h"
37 #include "vtkRenderingOpenGL2Module.h" // For export macro
38 #include "vtkWeakPointer.h" // needed for vtkWeakPointer.
39 
40 class vtkRenderWindow;
41 class vtkOpenGLExtensionManager;
42 
43 class VTKRENDERINGOPENGL2_EXPORT vtkPixelBufferObject : public vtkObject
44 {
45 public:
46 
47   // Usage values.
48   enum
49   {
50     StreamDraw=0,
51     StreamRead,
52     StreamCopy,
53     StaticDraw,
54     StaticRead,
55     StaticCopy,
56     DynamicDraw,
57     DynamicRead,
58     DynamicCopy,
59     NumberOfUsages
60   };
61 
62   static vtkPixelBufferObject* New();
63   vtkTypeMacro(vtkPixelBufferObject, vtkObject);
64   void PrintSelf(ostream& os, vtkIndent indent) override;
65 
66   //@{
67   /**
68    * Get/Set the context. Context must be a vtkOpenGLRenderWindow.
69    * This does not increase the reference count of the
70    * context to avoid reference loops.
71    * SetContext() may raise an error is the OpenGL context does not support the
72    * required OpenGL extensions.
73    */
74   void SetContext(vtkRenderWindow* context);
75   vtkRenderWindow* GetContext();
76   //@}
77 
78   //@{
79   /**
80    * Usage is a performance hint.
81    * Valid values are:
82    * - StreamDraw specified once by A, used few times S
83    * - StreamRead specified once by R, queried a few times by A
84    * - StreamCopy specified once by R, used a few times S
85    * - StaticDraw specified once by A, used many times S
86    * - StaticRead specified once by R, queried many times by A
87    * - StaticCopy specified once by R, used many times S
88    * - DynamicDraw respecified repeatedly by A, used many times S
89    * - DynamicRead respecified repeatedly by R, queried many times by A
90    * - DynamicCopy respecified repeatedly by R, used many times S
91    * A: the application
92    * S: as the source for GL drawing and image specification commands.
93    * R: reading data from the GL
94    * Initial value is StaticDraw, as in OpenGL spec.
95    */
96   vtkGetMacro(Usage,int);
97   vtkSetMacro(Usage,int);
98   //@}
99 
100   //@{
101   /**
102    * Upload data to PBO mapped.
103    * The input data can be freed after this call.
104    * The data ptr is treated as an 1D array with the given number of tuples and
105    * given number of components in each tuple to be copied to the PBO mapped. increment
106    * is the offset added after the last component in each tuple is transferred.
107    * Look at the documentation for ContinuousIncrements in vtkImageData for
108    * details about how increments are specified.
109    */
Upload1D(int type,void * data,unsigned int numtuples,int comps,vtkIdType increment)110   bool Upload1D(int type, void* data,
111     unsigned int numtuples, int comps, vtkIdType increment)
112   {
113     unsigned int newdims[3];
114     newdims[0] = numtuples;
115     newdims[1] = 1;
116     newdims[2] = 1;
117     vtkIdType newinc[3];
118     newinc[0] = increment;
119     newinc[1] = 0;
120     newinc[2] = 0;
121     return this->Upload3D(type, data, newdims, comps, newinc,0,nullptr);
122   }
123   //@}
124 
125   //@{
126   /**
127    * Update data to PBO mapped sourcing it from a 2D array.
128    * The input data can be freed after this call.
129    * The data ptr is treated as a 2D array with increments indicating how to
130    * iterate over the data.
131    * Look at the documentation for ContinuousIncrements in vtkImageData for
132    * details about how increments are specified.
133    */
Upload2D(int type,void * data,unsigned int dims[2],int comps,vtkIdType increments[2])134   bool Upload2D(int type, void* data,
135     unsigned int dims[2],
136     int comps,
137     vtkIdType increments[2])
138   {
139     unsigned int newdims[3];
140     newdims[0] = dims[0];
141     newdims[1] = dims[1];
142     newdims[2] = 1;
143     vtkIdType newinc[3];
144     newinc[0] = increments[0];
145     newinc[1] = increments[1];
146     newinc[2] = 0;
147     return this->Upload3D(type, data, newdims, comps, newinc,0,nullptr);
148   }
149   //@}
150 
151   /**
152    * Update data to PBO mapped sourcing it from a 3D array.
153    * The input data can be freed after this call.
154    * The data ptr is treated as a 3D array with increments indicating how to
155    * iterate over the data.
156    * Look at the documentation for ContinuousIncrements in vtkImageData for
157    * details about how increments are specified.
158    */
159   bool Upload3D(int type, void* data,
160                 unsigned int dims[3], int comps,
161                 vtkIdType increments[3],
162                 int components,
163                 int *componentList);
164 
165   //@{
166   /**
167    * Get the type with which the data is loaded into the PBO mapped.
168    * eg. VTK_FLOAT for float32, VTK_CHAR for byte, VTK_UNSIGNED_CHAR for
169    * unsigned byte etc.
170    */
171   vtkGetMacro(Type, int);
172   vtkSetMacro(Type, int);
173   //@}
174 
175   //@{
176   /**
177    * Get the number of components used to initialize the buffer.
178    */
179   vtkGetMacro(Components, int);
180   vtkSetMacro(Components, int);
181   //@}
182 
183   //@{
184   /**
185    * Get the size of the data loaded into the PBO mapped memory. Size is
186    * in the number of elements of the uploaded Type.
187    */
188   vtkGetMacro(Size, unsigned int);
189   vtkSetMacro(Size, unsigned int);
190   void SetSize(unsigned int nTups, int nComps);
191   //@}
192 
193   //@{
194   /**
195    * Get the openGL buffer handle.
196    */
197   vtkGetMacro(Handle, unsigned int);
198   //@}
199 
200   //@{
201   /**
202    * Download data from pixel buffer to the 1D array. The length of the array
203    * must be equal to the size of the data in the memory.
204    */
Download1D(int type,void * data,unsigned int dim,int numcomps,vtkIdType increment)205   bool Download1D(
206     int type, void* data,
207     unsigned int dim,
208     int numcomps, vtkIdType increment)
209   {
210     unsigned int newdims[3];
211     newdims[0] = dim;
212     newdims[1] = 1;
213     newdims[2] = 1;
214     vtkIdType newincrements[3];
215     newincrements[0] = increment;
216     newincrements[1] = 0;
217     newincrements[2] = 0;
218     return this->Download3D(type, data, newdims, numcomps, newincrements);
219   }
220   //@}
221 
222   //@{
223   /**
224    * Download data from pixel buffer to the 2D array. (lengthx * lengthy)
225    * must be equal to the size of the data in the memory.
226    */
Download2D(int type,void * data,unsigned int dims[2],int numcomps,vtkIdType increments[2])227   bool Download2D(
228     int type, void* data,
229     unsigned int dims[2],
230     int numcomps, vtkIdType increments[2])
231   {
232     unsigned int newdims[3];
233     newdims[0] = dims[0];
234     newdims[1] = dims[1];
235     newdims[2] = 1;
236     vtkIdType newincrements[3];
237     newincrements[0] = increments[0];
238     newincrements[1] = increments[1];
239     newincrements[2] =  0;
240     return this->Download3D(type, data, newdims, numcomps, newincrements);
241   }
242   //@}
243 
244   /**
245    * Download data from pixel buffer to the 3D array.
246    * (lengthx * lengthy * lengthz) must be equal to the size of the data in
247    * the memory.
248    */
249   bool Download3D(int type, void* data,
250     unsigned int dims[3],
251     int numcomps, vtkIdType increments[3]);
252 
253   /**
254    * Convenience methods for binding.
255    */
BindToPackedBuffer()256   void BindToPackedBuffer()
257     { this->Bind(PACKED_BUFFER); }
258 
BindToUnPackedBuffer()259   void BindToUnPackedBuffer()
260     { this->Bind(UNPACKED_BUFFER); }
261 
262   /**
263    * Deactivate the buffer.
264    */
265   void UnBind();
266 
267   /**
268    * Convenience api for mapping buffers to app address space.
269    * See also MapBuffer.
270    */
MapPackedBuffer()271   void *MapPackedBuffer()
272     { return this->MapBuffer(PACKED_BUFFER); }
273 
MapPackedBuffer(int type,unsigned int numtuples,int comps)274   void *MapPackedBuffer(int type, unsigned int numtuples, int comps)
275     { return this->MapBuffer(type, numtuples, comps, PACKED_BUFFER); }
276 
MapPackedBuffer(unsigned int numbytes)277   void *MapPackedBuffer(unsigned int numbytes)
278     { return this->MapBuffer(numbytes, PACKED_BUFFER); }
279 
MapUnpackedBuffer()280   void *MapUnpackedBuffer()
281     { return this->MapBuffer(UNPACKED_BUFFER); }
282 
MapUnpackedBuffer(int type,unsigned int numtuples,int comps)283   void *MapUnpackedBuffer(int type, unsigned int numtuples, int comps)
284     { return this->MapBuffer(type, numtuples, comps, UNPACKED_BUFFER); }
285 
MapUnpackedBuffer(unsigned int numbytes)286   void *MapUnpackedBuffer(unsigned int numbytes)
287     { return this->MapBuffer(numbytes, UNPACKED_BUFFER); }
288 
289   /**
290    * Convenience api for unmapping buffers from app address space.
291    * See also UnmapBuffer.
292    */
UnmapUnpackedBuffer()293   void UnmapUnpackedBuffer()
294     { this->UnmapBuffer(UNPACKED_BUFFER); }
295 
UnmapPackedBuffer()296   void UnmapPackedBuffer()
297     { this->UnmapBuffer(PACKED_BUFFER); }
298 
299   // PACKED_BUFFER for download APP<-PBO
300   // UNPACKED_BUFFER for upload APP->PBO
301   enum BufferType{
302     UNPACKED_BUFFER=0,
303     PACKED_BUFFER
304   };
305 
306   /**
307    * Make the buffer active.
308    */
309   void Bind(BufferType buffer);
310 
311   //@{
312   /**
313    * Map the buffer to our addresspace. Returns a pointer to the mapped memory
314    * for read/write access. If type, tuples and components are specified new buffer
315    * data will be allocated, else the current allocation is mapped. When finished
316    * call UnmapBuffer.
317    */
318   void *MapBuffer(int type, unsigned int numtuples, int comps, BufferType mode);
319   void *MapBuffer(unsigned int numbytes, BufferType mode);
320   void *MapBuffer(BufferType mode);
321   //@}
322 
323   /**
324    * Un-map the buffer from our address space, OpenGL can then use/reclaim the
325    * buffer contents.
326    */
327   void UnmapBuffer(BufferType mode);
328 
329   /**
330    * Allocate PACKED/UNPACKED memory to hold numTuples*numComponents of vtkType.
331    */
332   void Allocate(
333         int vtkType,
334         unsigned int numtuples,
335         int comps,
336         BufferType mode);
337 
338   /**
339    * Allocate PACKED/UNPACKED memory to hold nBytes of data.
340    */
341   void Allocate(
342         unsigned int nbytes,
343         BufferType mode);
344 
345   /**
346    * Release the memory allocated without destroying the PBO handle.
347    */
348   void ReleaseMemory();
349 
350   /**
351    * Returns if the context supports the required extensions.
352    * Extension will be loaded when the context is set.
353    */
354   static bool IsSupported(vtkRenderWindow* renWin);
355 
356 protected:
357   vtkPixelBufferObject();
358   ~vtkPixelBufferObject() override;
359 
360   /**
361    * Loads all required OpenGL extensions. Must be called every time a new
362    * context is set.
363    */
364   bool LoadRequiredExtensions(vtkRenderWindow* renWin);
365 
366   /**
367    * Create the pixel buffer object.
368    */
369   void CreateBuffer();
370 
371   /**
372    * Destroys the pixel buffer object.
373    */
374   void DestroyBuffer();
375 
376   int Usage;
377   unsigned int BufferTarget; // GLenum
378   int Type;
379   int Components;
380   unsigned int Size;
381   vtkWeakPointer<vtkRenderWindow> Context;
382   unsigned int Handle;
383 private:
384   vtkPixelBufferObject(const vtkPixelBufferObject&) = delete;
385   void operator=(const vtkPixelBufferObject&) = delete;
386 };
387 
388 #endif
389