You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

369 lines
11 KiB
C++

/*=========================================================================
Program: Visualization Toolkit
Module: vtkPixelBufferObject.h
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
/**
* @class vtkPixelBufferObject
* @brief abstracts an OpenGL pixel buffer object.
*
* Provides low-level access to PBO mapped memory. Used to transfer raw data
* to/from PBO mapped memory and the application. Once data is transferred to
* the PBO it can then be transferred to the GPU (eg texture memory). Data may
* be uploaded from the application into a pixel buffer or downloaded from the
* pixel buffer to the application. The vtkTextureObject is used to transfer
* data from/to the PBO to/from texture memory on the GPU.
* @sa
* OpenGL Pixel Buffer Object Extension Spec (ARB_pixel_buffer_object):
* http://www.opengl.org/registry/specs/ARB/pixel_buffer_object.txt
* @warning
* Since most PBO mapped don't support double format all double data is converted to
* float and then uploaded.
*/
#ifndef vtkPixelBufferObject_h
#define vtkPixelBufferObject_h
#include "vtkObject.h"
#include "vtkRenderingOpenGL2Module.h" // For export macro
#include "vtkWeakPointer.h" // needed for vtkWeakPointer.
class vtkRenderWindow;
class vtkOpenGLExtensionManager;
class VTKRENDERINGOPENGL2_EXPORT vtkPixelBufferObject : public vtkObject
{
public:
// Usage values.
enum
{
StreamDraw = 0,
StreamRead,
StreamCopy,
StaticDraw,
StaticRead,
StaticCopy,
DynamicDraw,
DynamicRead,
DynamicCopy,
NumberOfUsages
};
static vtkPixelBufferObject* New();
vtkTypeMacro(vtkPixelBufferObject, vtkObject);
void PrintSelf(ostream& os, vtkIndent indent) override;
//@{
/**
* Get/Set the context. Context must be a vtkOpenGLRenderWindow.
* This does not increase the reference count of the
* context to avoid reference loops.
* SetContext() may raise an error is the OpenGL context does not support the
* required OpenGL extensions.
*/
void SetContext(vtkRenderWindow* context);
vtkRenderWindow* GetContext();
//@}
//@{
/**
* Usage is a performance hint.
* Valid values are:
* - StreamDraw specified once by A, used few times S
* - StreamRead specified once by R, queried a few times by A
* - StreamCopy specified once by R, used a few times S
* - StaticDraw specified once by A, used many times S
* - StaticRead specified once by R, queried many times by A
* - StaticCopy specified once by R, used many times S
* - DynamicDraw respecified repeatedly by A, used many times S
* - DynamicRead respecified repeatedly by R, queried many times by A
* - DynamicCopy respecified repeatedly by R, used many times S
* A: the application
* S: as the source for GL drawing and image specification commands.
* R: reading data from the GL
* Initial value is StaticDraw, as in OpenGL spec.
*/
vtkGetMacro(Usage, int);
vtkSetMacro(Usage, int);
//@}
//@{
/**
* Upload data to PBO mapped.
* The input data can be freed after this call.
* The data ptr is treated as an 1D array with the given number of tuples and
* given number of components in each tuple to be copied to the PBO mapped. increment
* is the offset added after the last component in each tuple is transferred.
* Look at the documentation for ContinuousIncrements in vtkImageData for
* details about how increments are specified.
*/
bool Upload1D(int type, void* data, unsigned int numtuples, int comps, vtkIdType increment)
{
unsigned int newdims[3];
newdims[0] = numtuples;
newdims[1] = 1;
newdims[2] = 1;
vtkIdType newinc[3];
newinc[0] = increment;
newinc[1] = 0;
newinc[2] = 0;
return this->Upload3D(type, data, newdims, comps, newinc, 0, nullptr);
}
//@}
//@{
/**
* Update data to PBO mapped sourcing it from a 2D array.
* The input data can be freed after this call.
* The data ptr is treated as a 2D array with increments indicating how to
* iterate over the data.
* Look at the documentation for ContinuousIncrements in vtkImageData for
* details about how increments are specified.
*/
bool Upload2D(int type, void* data, unsigned int dims[2], int comps, vtkIdType increments[2])
{
unsigned int newdims[3];
newdims[0] = dims[0];
newdims[1] = dims[1];
newdims[2] = 1;
vtkIdType newinc[3];
newinc[0] = increments[0];
newinc[1] = increments[1];
newinc[2] = 0;
return this->Upload3D(type, data, newdims, comps, newinc, 0, nullptr);
}
//@}
/**
* Update data to PBO mapped sourcing it from a 3D array.
* The input data can be freed after this call.
* The data ptr is treated as a 3D array with increments indicating how to
* iterate over the data.
* Look at the documentation for ContinuousIncrements in vtkImageData for
* details about how increments are specified.
*/
bool Upload3D(int type, void* data, unsigned int dims[3], int comps, vtkIdType increments[3],
int components, int* componentList);
//@{
/**
* Get the type with which the data is loaded into the PBO mapped.
* eg. VTK_FLOAT for float32, VTK_CHAR for byte, VTK_UNSIGNED_CHAR for
* unsigned byte etc.
*/
vtkGetMacro(Type, int);
vtkSetMacro(Type, int);
//@}
//@{
/**
* Get the number of components used to initialize the buffer.
*/
vtkGetMacro(Components, int);
vtkSetMacro(Components, int);
//@}
//@{
/**
* Get the size of the data loaded into the PBO mapped memory. Size is
* in the number of elements of the uploaded Type.
*/
vtkGetMacro(Size, unsigned int);
vtkSetMacro(Size, unsigned int);
void SetSize(unsigned int nTups, int nComps);
//@}
//@{
/**
* Get the openGL buffer handle.
*/
vtkGetMacro(Handle, unsigned int);
//@}
//@{
/**
* Download data from pixel buffer to the 1D array. The length of the array
* must be equal to the size of the data in the memory.
*/
bool Download1D(int type, void* data, unsigned int dim, int numcomps, vtkIdType increment)
{
unsigned int newdims[3];
newdims[0] = dim;
newdims[1] = 1;
newdims[2] = 1;
vtkIdType newincrements[3];
newincrements[0] = increment;
newincrements[1] = 0;
newincrements[2] = 0;
return this->Download3D(type, data, newdims, numcomps, newincrements);
}
//@}
//@{
/**
* Download data from pixel buffer to the 2D array. (lengthx * lengthy)
* must be equal to the size of the data in the memory.
*/
bool Download2D(int type, void* data, unsigned int dims[2], int numcomps, vtkIdType increments[2])
{
unsigned int newdims[3];
newdims[0] = dims[0];
newdims[1] = dims[1];
newdims[2] = 1;
vtkIdType newincrements[3];
newincrements[0] = increments[0];
newincrements[1] = increments[1];
newincrements[2] = 0;
return this->Download3D(type, data, newdims, numcomps, newincrements);
}
//@}
/**
* Download data from pixel buffer to the 3D array.
* (lengthx * lengthy * lengthz) must be equal to the size of the data in
* the memory.
*/
bool Download3D(
int type, void* data, unsigned int dims[3], int numcomps, vtkIdType increments[3]);
/**
* Convenience methods for binding.
*/
void BindToPackedBuffer() { this->Bind(PACKED_BUFFER); }
void BindToUnPackedBuffer() { this->Bind(UNPACKED_BUFFER); }
/**
* Deactivate the buffer.
*/
void UnBind();
/**
* Convenience api for mapping buffers to app address space.
* See also MapBuffer.
*/
void* MapPackedBuffer() { return this->MapBuffer(PACKED_BUFFER); }
void* MapPackedBuffer(int type, unsigned int numtuples, int comps)
{
return this->MapBuffer(type, numtuples, comps, PACKED_BUFFER);
}
void* MapPackedBuffer(unsigned int numbytes) { return this->MapBuffer(numbytes, PACKED_BUFFER); }
void* MapUnpackedBuffer() { return this->MapBuffer(UNPACKED_BUFFER); }
void* MapUnpackedBuffer(int type, unsigned int numtuples, int comps)
{
return this->MapBuffer(type, numtuples, comps, UNPACKED_BUFFER);
}
void* MapUnpackedBuffer(unsigned int numbytes)
{
return this->MapBuffer(numbytes, UNPACKED_BUFFER);
}
/**
* Convenience api for unmapping buffers from app address space.
* See also UnmapBuffer.
*/
void UnmapUnpackedBuffer() { this->UnmapBuffer(UNPACKED_BUFFER); }
void UnmapPackedBuffer() { this->UnmapBuffer(PACKED_BUFFER); }
// PACKED_BUFFER for download APP<-PBO
// UNPACKED_BUFFER for upload APP->PBO
enum BufferType
{
UNPACKED_BUFFER = 0,
PACKED_BUFFER
};
/**
* Make the buffer active.
*/
void Bind(BufferType buffer);
//@{
/**
* Map the buffer to our addresspace. Returns a pointer to the mapped memory
* for read/write access. If type, tuples and components are specified new buffer
* data will be allocated, else the current allocation is mapped. When finished
* call UnmapBuffer.
*/
void* MapBuffer(int type, unsigned int numtuples, int comps, BufferType mode);
void* MapBuffer(unsigned int numbytes, BufferType mode);
void* MapBuffer(BufferType mode);
//@}
/**
* Un-map the buffer from our address space, OpenGL can then use/reclaim the
* buffer contents.
*/
void UnmapBuffer(BufferType mode);
/**
* Allocate PACKED/UNPACKED memory to hold numTuples*numComponents of vtkType.
*/
void Allocate(int vtkType, unsigned int numtuples, int comps, BufferType mode);
/**
* Allocate PACKED/UNPACKED memory to hold nBytes of data.
*/
void Allocate(unsigned int nbytes, BufferType mode);
/**
* Release the memory allocated without destroying the PBO handle.
*/
void ReleaseMemory();
/**
* Returns if the context supports the required extensions.
* Extension will be loaded when the context is set.
*/
static bool IsSupported(vtkRenderWindow* renWin);
protected:
vtkPixelBufferObject();
~vtkPixelBufferObject() override;
/**
* Loads all required OpenGL extensions. Must be called every time a new
* context is set.
*/
bool LoadRequiredExtensions(vtkRenderWindow* renWin);
/**
* Create the pixel buffer object.
*/
void CreateBuffer();
/**
* Destroys the pixel buffer object.
*/
void DestroyBuffer();
int Usage;
unsigned int BufferTarget; // GLenum
int Type;
int Components;
unsigned int Size;
vtkWeakPointer<vtkRenderWindow> Context;
unsigned int Handle;
private:
vtkPixelBufferObject(const vtkPixelBufferObject&) = delete;
void operator=(const vtkPixelBufferObject&) = delete;
};
#endif