/*========================================================================= Program: Visualization Toolkit Module: vtkRenderbuffer.cxx 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. =========================================================================*/ #include "vtkRenderbuffer.h" #include "vtkObjectFactory.h" #include "vtkOpenGLError.h" #include "vtkOpenGLRenderWindow.h" #include "vtk_glew.h" #include //------------------------------------------------------------------------------ vtkStandardNewMacro(vtkRenderbuffer); //------------------------------------------------------------------------------ vtkRenderbuffer::vtkRenderbuffer() { this->Context = nullptr; this->Handle = 0U; this->DepthBufferFloat = 0; this->Samples = 0; this->Format = GL_RGBA; } //------------------------------------------------------------------------------ vtkRenderbuffer::~vtkRenderbuffer() { this->Free(); } //------------------------------------------------------------------------------ bool vtkRenderbuffer::IsSupported(vtkRenderWindow*) { return true; } //------------------------------------------------------------------------------ bool vtkRenderbuffer::LoadRequiredExtensions(vtkRenderWindow*) { // both texture float and depth float are part of OpenGL 3.0 and later this->DepthBufferFloat = true; return true; } //------------------------------------------------------------------------------ void vtkRenderbuffer::Alloc() { glGenRenderbuffers(1, &this->Handle); vtkOpenGLCheckErrorMacro("failed at glGenRenderbuffers"); } void vtkRenderbuffer::ReleaseGraphicsResources(vtkWindow*) { if (this->Context && this->Handle) { glDeleteRenderbuffers(1, &this->Handle); vtkOpenGLCheckErrorMacro("failed at glDeleteRenderBuffers"); } } //------------------------------------------------------------------------------ void vtkRenderbuffer::Free() { this->ReleaseGraphicsResources(nullptr); } //------------------------------------------------------------------------------ vtkRenderWindow* vtkRenderbuffer::GetContext() { return this->Context; } //------------------------------------------------------------------------------ void vtkRenderbuffer::SetContext(vtkRenderWindow* renWin) { // avoid pointless re-assignment if (this->Context == renWin) { return; } // free previous resources this->Free(); this->Context = nullptr; this->DepthBufferFloat = 0; this->Modified(); // check for supported context vtkOpenGLRenderWindow* context = dynamic_cast(renWin); if (!context || !this->LoadRequiredExtensions(renWin)) { vtkErrorMacro("Unsupported render context"); return; } // allocate new fbo this->Context = renWin; this->Context->MakeCurrent(); this->Alloc(); } //------------------------------------------------------------------------------ int vtkRenderbuffer::CreateColorAttachment(unsigned int width, unsigned int height) { assert(this->Context); return this->Create(GL_RGBA32F, width, height); } //------------------------------------------------------------------------------ int vtkRenderbuffer::CreateDepthAttachment(unsigned int width, unsigned int height) { assert(this->Context); // typically DEPTH_COMPONENT will end up being a 32 bit floating // point format however it's not a guarantee and does not seem // to be the case with mesa hence the need to explicitly specify // it as such if at all possible. if (this->DepthBufferFloat) { return this->Create(GL_DEPTH_COMPONENT32F, width, height); } return this->Create(GL_DEPTH_COMPONENT, width, height); } //------------------------------------------------------------------------------ int vtkRenderbuffer::Create(unsigned int format, unsigned int width, unsigned int height) { return this->Create(format, width, height, 0); } int vtkRenderbuffer::Create( unsigned int format, unsigned int width, unsigned int height, unsigned int samples) { assert(this->Context); glBindRenderbuffer(GL_RENDERBUFFER, (GLuint)this->Handle); vtkOpenGLCheckErrorMacro("failed at glBindRenderBuffer"); if (samples) { glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, (GLenum)format, width, height); } else { glRenderbufferStorage(GL_RENDERBUFFER, (GLenum)format, width, height); } vtkOpenGLCheckErrorMacro("failed at glRenderbufferStorage with format: " << format << " and size " << width << " by " << height); this->Width = width; this->Height = height; this->Format = format; this->Samples = samples; return 1; } void vtkRenderbuffer::Resize(unsigned int width, unsigned int height) { if (this->Width == width && this->Height == height) { return; } if (this->Context && this->Handle) { glBindRenderbuffer(GL_RENDERBUFFER, (GLuint)this->Handle); if (this->Samples) { glRenderbufferStorageMultisample( GL_RENDERBUFFER, this->Samples, (GLenum)this->Format, width, height); } else { glRenderbufferStorage(GL_RENDERBUFFER, (GLenum)this->Format, width, height); } } this->Width = width; this->Height = height; } //------------------------------------------------------------------------------ void vtkRenderbuffer::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "Handle=" << this->Handle << endl << indent << "Context=" << this->Context << endl; }