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.
414 lines
13 KiB
C++
414 lines
13 KiB
C++
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: vtkOpenGLState.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 vtkOpenGLState
|
|
* @brief OpenGL state storage
|
|
*
|
|
* vtkOpenGLState is a class designed to keep track of the state of
|
|
* an OpenGL context. Applications using VTK have so much control
|
|
* over the rendering process that is can be difficult in VTK code
|
|
* to know if the OpenGL state is correct for your code. The two
|
|
* traditional solutions have been to set everything yourself
|
|
* and to save and restore OpenGL state that you change. The former
|
|
* makes your code work, the latter helps prevent your code from
|
|
* breaking something else. The problem is that the former results
|
|
* in tons of redundant OpenGL calls and the later is done by querying
|
|
* the OpenGL state which can cause a pipeline sync/stall which is
|
|
* very slow.
|
|
*
|
|
* To address these issues this class stores OpenGL state for commonly
|
|
* used functions. Requests made to change state to the current
|
|
* state become no-ops. Queries of state can be done by querying the
|
|
* state stored in this class without impacting the OpenGL driver.
|
|
*
|
|
* This class is designed to hold all context related values and
|
|
* could just as well be considered a representation of the OpenGL
|
|
* context.
|
|
*
|
|
* To facilitate saving state and restoring it this class contains
|
|
* a number of nested classes named Scoped<glFunction> that store
|
|
* the state of that glFunction and when they go out of scope they restore
|
|
* it. This is useful when you want to change the OpenGL state and then
|
|
* automatically restore it when done. They can be used as follows
|
|
*
|
|
* {
|
|
* vtkOpenGLState *ostate = renWin->GetState();
|
|
* vtkOpenGLState::ScopedglDepthMask dmsaved(ostate);
|
|
* // the prior state is now saved
|
|
* ...
|
|
* ostate->glDepthMask(GL_TRUE); // maybe change the state
|
|
* ... etc
|
|
* } // prior state will be restored here as it goes out of scope
|
|
*
|
|
*
|
|
* You must use this class to make state changing OpenGL class otherwise the
|
|
* results will be undefined.
|
|
*
|
|
* For convenience some OpenGL calls that do not impact state are also
|
|
* provided.
|
|
*/
|
|
|
|
#ifndef vtkOpenGLState_h
|
|
#define vtkOpenGLState_h
|
|
|
|
#include "vtkObject.h"
|
|
#include "vtkRenderingOpenGL2Module.h" // For export macro
|
|
#include <array> // for ivar
|
|
#include <list> // for ivar
|
|
#include <map> // for ivar
|
|
|
|
class vtkOpenGLFramebufferObject;
|
|
class vtkOpenGLRenderWindow;
|
|
class vtkOpenGLShaderCache;
|
|
class vtkOpenGLVertexBufferObjectCache;
|
|
class vtkTextureObject;
|
|
class vtkTextureUnitManager;
|
|
|
|
class VTKRENDERINGOPENGL2_EXPORT vtkOpenGLState : public vtkObject
|
|
{
|
|
public:
|
|
static vtkOpenGLState* New();
|
|
vtkTypeMacro(vtkOpenGLState, vtkObject);
|
|
|
|
//@{
|
|
// cached OpenGL methods. By calling these the context will check
|
|
// the current value prior to making the OpenGL call. This can reduce
|
|
// the burden on the driver.
|
|
//
|
|
void vtkglClearColor(float red, float green, float blue, float alpha);
|
|
void vtkglClearDepth(double depth);
|
|
void vtkglDepthFunc(unsigned int val);
|
|
void vtkglDepthMask(unsigned char flag);
|
|
void vtkglColorMask(unsigned char r, unsigned char g, unsigned char b, unsigned char a);
|
|
void vtkglViewport(int x, int y, int width, int height);
|
|
void vtkglScissor(int x, int y, int width, int height);
|
|
void vtkglEnable(unsigned int cap);
|
|
void vtkglDisable(unsigned int cap);
|
|
void vtkglBlendFunc(unsigned int sfactor, unsigned int dfactor)
|
|
{
|
|
this->vtkglBlendFuncSeparate(sfactor, dfactor, sfactor, dfactor);
|
|
}
|
|
void vtkglBlendFuncSeparate(unsigned int sfactorRGB, unsigned int dfactorRGB,
|
|
unsigned int sfactorAlpha, unsigned int dfactorAlpha);
|
|
void vtkglBlendEquation(unsigned int val);
|
|
void vtkglBlendEquationSeparate(unsigned int col, unsigned int alpha);
|
|
void vtkglCullFace(unsigned int val);
|
|
void vtkglActiveTexture(unsigned int);
|
|
|
|
void vtkglBindFramebuffer(unsigned int target, unsigned int fb);
|
|
void vtkglDrawBuffer(unsigned int);
|
|
void vtkglDrawBuffers(unsigned int n, unsigned int*);
|
|
void vtkglReadBuffer(unsigned int);
|
|
|
|
void vtkBindFramebuffer(unsigned int target, vtkOpenGLFramebufferObject* fo);
|
|
void vtkDrawBuffers(unsigned int n, unsigned int*, vtkOpenGLFramebufferObject*);
|
|
void vtkReadBuffer(unsigned int, vtkOpenGLFramebufferObject*);
|
|
//@}
|
|
|
|
//@{
|
|
// Methods to reset the state to the current OpenGL context value.
|
|
// These methods are useful when interfacing with third party code
|
|
// that may have changed the opengl state.
|
|
//
|
|
void ResetGLClearColorState();
|
|
void ResetGLClearDepthState();
|
|
void ResetGLDepthFuncState();
|
|
void ResetGLDepthMaskState();
|
|
void ResetGLColorMaskState();
|
|
void ResetGLViewportState();
|
|
void ResetGLScissorState();
|
|
void ResetGLBlendFuncState();
|
|
void ResetGLBlendEquationState();
|
|
void ResetGLCullFaceState();
|
|
void ResetGLActiveTexture();
|
|
//@}
|
|
|
|
//@{
|
|
// OpenGL functions that we provide an API for even though they may
|
|
// not hold any state.
|
|
void vtkglClear(unsigned int mask);
|
|
//@}
|
|
|
|
//@{
|
|
// Get methods that can be used to query state if the state is not cached
|
|
// they fall through and call the underlying opengl functions
|
|
void vtkglGetBooleanv(unsigned int pname, unsigned char* params);
|
|
void vtkglGetIntegerv(unsigned int pname, int* params);
|
|
void vtkglGetDoublev(unsigned int pname, double* params);
|
|
void vtkglGetFloatv(unsigned int pname, float* params);
|
|
//@}
|
|
|
|
// convenience to get all 4 values at once
|
|
void GetBlendFuncState(int*);
|
|
|
|
// convenience to return a bool
|
|
// as opposed to a unsigned char
|
|
bool GetEnumState(unsigned int name);
|
|
|
|
// convenience method to set a enum (glEnable/glDisable)
|
|
void SetEnumState(unsigned int name, bool value);
|
|
|
|
/**
|
|
* convenience method to reset an enum state from current openGL context
|
|
*/
|
|
void ResetEnumState(unsigned int name);
|
|
|
|
// superclass for Scoped subclasses
|
|
template <typename T>
|
|
class VTKRENDERINGOPENGL2_EXPORT ScopedValue
|
|
{
|
|
public:
|
|
~ScopedValue() // restore value
|
|
{
|
|
((*this->State).*(this->Method))(this->Value);
|
|
}
|
|
|
|
protected:
|
|
vtkOpenGLState* State;
|
|
T Value;
|
|
void (vtkOpenGLState::*Method)(T);
|
|
};
|
|
|
|
/**
|
|
* Activate a texture unit for this texture
|
|
*/
|
|
void ActivateTexture(vtkTextureObject*);
|
|
|
|
/**
|
|
* Deactivate a previously activated texture
|
|
*/
|
|
void DeactivateTexture(vtkTextureObject*);
|
|
|
|
/**
|
|
* Get the texture unit for a given texture object
|
|
*/
|
|
int GetTextureUnitForTexture(vtkTextureObject*);
|
|
|
|
/**
|
|
* Check to make sure no textures have been left active
|
|
*/
|
|
void VerifyNoActiveTextures();
|
|
|
|
//@{
|
|
/**
|
|
* Store/Restore the current framebuffer bindings and buffers.
|
|
*/
|
|
void PushFramebufferBindings()
|
|
{
|
|
this->PushDrawFramebufferBinding();
|
|
this->PushReadFramebufferBinding();
|
|
}
|
|
void PushDrawFramebufferBinding();
|
|
void PushReadFramebufferBinding();
|
|
|
|
void PopFramebufferBindings()
|
|
{
|
|
this->PopReadFramebufferBinding();
|
|
this->PopDrawFramebufferBinding();
|
|
}
|
|
void PopDrawFramebufferBinding();
|
|
void PopReadFramebufferBinding();
|
|
|
|
void ResetFramebufferBindings();
|
|
//@}
|
|
|
|
// Scoped classes you can use to save state
|
|
class VTKRENDERINGOPENGL2_EXPORT ScopedglDepthMask : public ScopedValue<unsigned char>
|
|
{
|
|
public:
|
|
ScopedglDepthMask(vtkOpenGLState* state);
|
|
};
|
|
class VTKRENDERINGOPENGL2_EXPORT ScopedglClearColor : public ScopedValue<std::array<float, 4> >
|
|
{
|
|
public:
|
|
ScopedglClearColor(vtkOpenGLState* state);
|
|
};
|
|
class VTKRENDERINGOPENGL2_EXPORT ScopedglColorMask
|
|
: public ScopedValue<std::array<unsigned char, 4> >
|
|
{
|
|
public:
|
|
ScopedglColorMask(vtkOpenGLState* state);
|
|
};
|
|
class VTKRENDERINGOPENGL2_EXPORT ScopedglScissor : public ScopedValue<std::array<int, 4> >
|
|
{
|
|
public:
|
|
ScopedglScissor(vtkOpenGLState* state);
|
|
};
|
|
class VTKRENDERINGOPENGL2_EXPORT ScopedglViewport : public ScopedValue<std::array<int, 4> >
|
|
{
|
|
public:
|
|
ScopedglViewport(vtkOpenGLState* state);
|
|
};
|
|
class VTKRENDERINGOPENGL2_EXPORT ScopedglBlendFuncSeparate
|
|
: public ScopedValue<std::array<unsigned int, 4> >
|
|
{
|
|
public:
|
|
ScopedglBlendFuncSeparate(vtkOpenGLState* state);
|
|
};
|
|
class VTKRENDERINGOPENGL2_EXPORT ScopedglDepthFunc : public ScopedValue<unsigned int>
|
|
{
|
|
public:
|
|
ScopedglDepthFunc(vtkOpenGLState* state);
|
|
};
|
|
class VTKRENDERINGOPENGL2_EXPORT ScopedglActiveTexture : public ScopedValue<unsigned int>
|
|
{
|
|
public:
|
|
ScopedglActiveTexture(vtkOpenGLState* state);
|
|
};
|
|
|
|
class ScopedglEnableDisable
|
|
{
|
|
public:
|
|
ScopedglEnableDisable(vtkOpenGLState* state, unsigned int name)
|
|
{
|
|
this->State = state;
|
|
this->Name = name;
|
|
unsigned char val;
|
|
this->State->vtkglGetBooleanv(name, &val);
|
|
this->Value = val == 1;
|
|
}
|
|
~ScopedglEnableDisable() // restore value
|
|
{
|
|
this->State->SetEnumState(this->Name, this->Value);
|
|
}
|
|
|
|
protected:
|
|
vtkOpenGLState* State;
|
|
unsigned int Name;
|
|
bool Value;
|
|
};
|
|
|
|
/**
|
|
* Initialize OpenGL context using current state
|
|
*/
|
|
void Initialize(vtkOpenGLRenderWindow*);
|
|
|
|
/**
|
|
* Set the texture unit manager.
|
|
*/
|
|
void SetTextureUnitManager(vtkTextureUnitManager* textureUnitManager);
|
|
|
|
/**
|
|
* Returns its texture unit manager object. A new one will be created if one
|
|
* hasn't already been set up.
|
|
*/
|
|
vtkTextureUnitManager* GetTextureUnitManager();
|
|
|
|
// get the shader program cache for this context
|
|
vtkGetObjectMacro(ShaderCache, vtkOpenGLShaderCache);
|
|
|
|
// get the vbo buffer cache for this context
|
|
vtkGetObjectMacro(VBOCache, vtkOpenGLVertexBufferObjectCache);
|
|
|
|
// set the VBO Cache to use for this state
|
|
// this allows two contexts to share VBOs
|
|
// basically this is OPenGL's support for shared
|
|
// lists
|
|
void SetVBOCache(vtkOpenGLVertexBufferObjectCache* val);
|
|
|
|
/**
|
|
* Get a mapping of vtk data types to native texture formats for this window
|
|
* we put this on the RenderWindow so that every texture does not have to
|
|
* build these structures themselves
|
|
*/
|
|
int GetDefaultTextureInternalFormat(
|
|
int vtktype, int numComponents, bool needInteger, bool needFloat, bool needSRGB);
|
|
|
|
protected:
|
|
vtkOpenGLState(); // set initial values
|
|
~vtkOpenGLState() override;
|
|
|
|
void BlendFuncSeparate(std::array<unsigned int, 4> val);
|
|
void ClearColor(std::array<float, 4> val);
|
|
void ColorMask(std::array<unsigned char, 4> val);
|
|
void Scissor(std::array<int, 4> val);
|
|
void Viewport(std::array<int, 4> val);
|
|
|
|
int TextureInternalFormats[VTK_UNICODE_STRING][3][5];
|
|
void InitializeTextureInternalFormats();
|
|
|
|
vtkTextureUnitManager* TextureUnitManager;
|
|
std::map<const vtkTextureObject*, int> TextureResourceIds;
|
|
|
|
/**
|
|
* Check that this OpenGL state has consistent values
|
|
* with the current OpenGL context
|
|
*/
|
|
void CheckState();
|
|
|
|
// framebuffers hold state themselves
|
|
// specifically they hold their draw and read buffers
|
|
// and when bound they reinstate those buffers
|
|
class VTKRENDERINGOPENGL2_EXPORT BufferBindingState
|
|
{
|
|
public:
|
|
BufferBindingState();
|
|
// bool operator==(const BufferBindingState& a, const BufferBindingState& b);
|
|
// either this holds a vtkOpenGLFramebufferObject
|
|
vtkOpenGLFramebufferObject* Framebuffer;
|
|
// or the handle to an unknown OpenGL FO
|
|
unsigned int Binding;
|
|
unsigned int ReadBuffer;
|
|
unsigned int DrawBuffers[10];
|
|
unsigned int GetBinding();
|
|
unsigned int GetDrawBuffer(unsigned int);
|
|
unsigned int GetReadBuffer();
|
|
};
|
|
std::list<BufferBindingState> DrawBindings;
|
|
std::list<BufferBindingState> ReadBindings;
|
|
|
|
class VTKRENDERINGOPENGL2_EXPORT GLState
|
|
{
|
|
public:
|
|
double ClearDepth;
|
|
unsigned char DepthMask;
|
|
unsigned int DepthFunc;
|
|
unsigned int BlendEquationValue1;
|
|
unsigned int BlendEquationValue2;
|
|
unsigned int CullFaceMode;
|
|
unsigned int ActiveTexture;
|
|
std::array<float, 4> ClearColor;
|
|
std::array<unsigned char, 4> ColorMask;
|
|
std::array<int, 4> Viewport;
|
|
std::array<int, 4> Scissor;
|
|
std::array<unsigned int, 4> BlendFunc;
|
|
bool DepthTest;
|
|
bool CullFace;
|
|
bool ScissorTest;
|
|
bool StencilTest;
|
|
bool Blend;
|
|
bool MultiSample;
|
|
int MaxTextureSize;
|
|
int MajorVersion;
|
|
int MinorVersion;
|
|
BufferBindingState DrawBinding;
|
|
BufferBindingState ReadBinding;
|
|
GLState() {}
|
|
};
|
|
|
|
GLState CurrentState;
|
|
|
|
vtkOpenGLVertexBufferObjectCache* VBOCache;
|
|
vtkOpenGLShaderCache* ShaderCache;
|
|
|
|
private:
|
|
vtkOpenGLState(const vtkOpenGLState&) = delete;
|
|
void operator=(const vtkOpenGLState&) = delete;
|
|
};
|
|
|
|
#endif
|
|
|
|
// VTK-HeaderTest-Exclude: vtkOpenGLState.h
|