/*========================================================================= Program: Visualization Toolkit Module: vtkOpenGLRenderWindow.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 "vtkOpenGLRenderWindow.h" #include #include "vtkFloatArray.h" #include "vtkgl.h" #include "vtkIdList.h" #include "vtkObjectFactory.h" #include "vtkOpenGLActor.h" #include "vtkOpenGLCamera.h" #include "vtkOpenGLExtensionManager.h" #include "vtkOpenGLHardwareSupport.h" #include "vtkOpenGLLight.h" #include "vtkOpenGLProperty.h" #include "vtkOpenGLRenderer.h" #include "vtkOpenGLError.h" #include "vtkOpenGLTexture.h" #include "vtkUnsignedCharArray.h" #include "vtkTextureUnitManager.h" #include "vtkPainterDeviceAdapter.h" #include "vtkStdString.h" #include using std::ostringstream; vtkCxxSetObjectMacro(vtkOpenGLRenderWindow, ExtensionManager, vtkOpenGLExtensionManager); vtkCxxSetObjectMacro(vtkOpenGLRenderWindow, HardwareSupport, vtkOpenGLHardwareSupport); vtkCxxSetObjectMacro(vtkOpenGLRenderWindow, TextureUnitManager, vtkTextureUnitManager); // Initialize static member that controls global maximum number of multisamples // (off by default on Apple because it causes problems on some Mac models). #if defined(__APPLE__) static int vtkOpenGLRenderWindowGlobalMaximumNumberOfMultiSamples = 0; #else static int vtkOpenGLRenderWindowGlobalMaximumNumberOfMultiSamples = 8; #endif const char* defaultWindowName = "Visualization Toolkit - OpenGL"; // ---------------------------------------------------------------------------- void vtkOpenGLRenderWindow::SetGlobalMaximumNumberOfMultiSamples(int val) { if (val == vtkOpenGLRenderWindowGlobalMaximumNumberOfMultiSamples) return; vtkOpenGLRenderWindowGlobalMaximumNumberOfMultiSamples = val; } // ---------------------------------------------------------------------------- int vtkOpenGLRenderWindow::GetGlobalMaximumNumberOfMultiSamples() { return vtkOpenGLRenderWindowGlobalMaximumNumberOfMultiSamples; } // ---------------------------------------------------------------------------- vtkOpenGLRenderWindow::vtkOpenGLRenderWindow() { this->ExtensionManager = NULL; this->HardwareSupport = NULL; this->TextureUnitManager = 0; this->PainterDeviceAdapter = vtkPainterDeviceAdapter::New(); this->MultiSamples = vtkOpenGLRenderWindowGlobalMaximumNumberOfMultiSamples; this->TextureResourceIds = vtkIdList::New(); delete [] this->WindowName; this->WindowName = new char[strlen(defaultWindowName) + 1]; strcpy(this->WindowName, defaultWindowName); this->OffScreenUseFrameBuffer = 0; this->FrameBufferObject = 0; this->HardwareBufferSize[0] = 0; this->HardwareBufferSize[1] = 0; this->HardwareOffScreenBuffersBind = false; this->BackLeftBuffer = static_cast(GL_BACK_LEFT); this->BackRightBuffer = static_cast(GL_BACK_RIGHT); this->FrontLeftBuffer = static_cast(GL_FRONT_LEFT); this->FrontRightBuffer = static_cast(GL_FRONT_RIGHT); this->BackBuffer = static_cast(GL_BACK); this->FrontBuffer = static_cast(GL_FRONT); this->OwnContext = 1; } //---------------------------------------------------------------------------- const char *vtkOpenGLRenderWindow::GetRenderingBackend() { return "OpenGL1"; } // free up memory & close the window // ---------------------------------------------------------------------------- vtkOpenGLRenderWindow::~vtkOpenGLRenderWindow() { this->TextureResourceIds->Delete(); if(this->TextureUnitManager!=0) { this->TextureUnitManager->SetContext(0); } if (this->ExtensionManager) { this->ExtensionManager->SetRenderWindow(0); } if (this->HardwareSupport) { this->HardwareSupport->SetExtensionManager(0); //this->HardwareSupport->Delete(); } this->SetTextureUnitManager(0); this->SetExtensionManager(0); this->SetHardwareSupport(0); } // ---------------------------------------------------------------------------- vtkMTimeType vtkOpenGLRenderWindow::GetContextCreationTime() { return this->ContextCreationTime.GetMTime(); } // ---------------------------------------------------------------------------- // Description: // Return the OpenGL name of the back left buffer. // It is GL_BACK_LEFT if GL is bound to the window-system-provided // framebuffer. It is vtkgl::COLOR_ATTACHMENT0_EXT if GL is bound to an // application-created framebuffer object (GPU-based offscreen rendering) // It is used by vtkOpenGLCamera. unsigned int vtkOpenGLRenderWindow::GetBackLeftBuffer() { return this->BackLeftBuffer; } // ---------------------------------------------------------------------------- // Description: // Return the OpenGL name of the back right buffer. // It is GL_BACK_RIGHT if GL is bound to the window-system-provided // framebuffer. It is vtkgl::COLOR_ATTACHMENT0_EXT+1 if GL is bound to an // application-created framebuffer object (GPU-based offscreen rendering) // It is used by vtkOpenGLCamera. unsigned int vtkOpenGLRenderWindow::GetBackRightBuffer() { return this->BackRightBuffer; } // ---------------------------------------------------------------------------- // Description: // Return the OpenGL name of the front left buffer. // It is GL_FRONT_LEFT if GL is bound to the window-system-provided // framebuffer. It is vtkgl::COLOR_ATTACHMENT0_EXT if GL is bound to an // application-created framebuffer object (GPU-based offscreen rendering) // It is used by vtkOpenGLCamera. unsigned int vtkOpenGLRenderWindow::GetFrontLeftBuffer() { return this->FrontLeftBuffer; } // ---------------------------------------------------------------------------- // Description: // Return the OpenGL name of the front right buffer. // It is GL_FRONT_RIGHT if GL is bound to the window-system-provided // framebuffer. It is vtkgl::COLOR_ATTACHMENT0_EXT+1 if GL is bound to an // application-created framebuffer object (GPU-based offscreen rendering) // It is used by vtkOpenGLCamera. unsigned int vtkOpenGLRenderWindow::GetFrontRightBuffer() { return this->FrontRightBuffer; } // ---------------------------------------------------------------------------- // Description: // Return the OpenGL name of the back left buffer. // It is GL_BACK if GL is bound to the window-system-provided // framebuffer. It is vtkgl::COLOR_ATTACHMENT0_EXT if GL is bound to an // application-created framebuffer object (GPU-based offscreen rendering) // It is used by vtkOpenGLCamera. unsigned int vtkOpenGLRenderWindow::GetBackBuffer() { return this->BackBuffer; } // ---------------------------------------------------------------------------- // Description: // Return the OpenGL name of the front left buffer. // It is GL_FRONT if GL is bound to the window-system-provided // framebuffer. It is vtkgl::COLOR_ATTACHMENT0_EXT if GL is bound to an // application-created framebuffer object (GPU-based offscreen rendering) // It is used by vtkOpenGLCamera. unsigned int vtkOpenGLRenderWindow::GetFrontBuffer() { return this->FrontBuffer; } void vtkOpenGLRenderWindow::SetSize(int a[2]) { this->SetSize(a[0], a[1]); } void vtkOpenGLRenderWindow::SetSize(int x, int y) { if (this->Size[0] == x && this->Size[1] == y) { // Nothing should've happened in the superclass but one never knows... this->Superclass::SetSize(x, y); return; } this->Superclass::SetSize(x, y); if (this->HardwareOffScreenBuffersBind) { // We activate the offscreen buffers again so they will be // recreated at the new window size this->SetUseOffScreenBuffers(true); } } void vtkOpenGLRenderWindow::OpenGLInit() { OpenGLInitContext(); OpenGLInitState(); } void vtkOpenGLRenderWindow::OpenGLInitState() { glMatrixMode( GL_MODELVIEW ); glDepthFunc( GL_LEQUAL ); glEnable( GL_DEPTH_TEST ); glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); // initialize blending for transparency if(vtkgl::BlendFuncSeparate!=0) { vtkgl::BlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE,GL_ONE_MINUS_SRC_ALPHA); } else { glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); } glEnable(GL_BLEND); if (this->PointSmoothing) { glEnable(GL_POINT_SMOOTH); } else { glDisable(GL_POINT_SMOOTH); } if (this->LineSmoothing) { glEnable(GL_LINE_SMOOTH); } else { glDisable(GL_LINE_SMOOTH); } if (this->PolygonSmoothing) { glEnable(GL_POLYGON_SMOOTH); } else { glDisable(GL_POLYGON_SMOOTH); } glEnable(GL_NORMALIZE); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); glAlphaFunc(GL_GREATER,0); // Default OpenGL is 4 bytes but it is only safe with RGBA format. // If format is RGB, row alignment is 4 bytes only if the width is divisible // by 4. Let's do it the safe way: 1-byte alignment. // If an algorithm really need 4 bytes alignment, it should set it itself, // this is the recommended way in "Avoiding 16 Common OpenGL Pitfalls", // section 7: // http://www.opengl.org/resources/features/KilgardTechniques/oglpitfall/ glPixelStorei(GL_UNPACK_ALIGNMENT,1); glPixelStorei(GL_PACK_ALIGNMENT,1); // Set the number of alpha bit planes used by the window int rgba[4]; this->GetColorBufferSizes(rgba); this->SetAlphaBitPlanes(rgba[3]); } void vtkOpenGLRenderWindow::OpenGLInitContext() { // When a new OpenGL context is created, force an update // of the extension manager by calling modified on it. vtkOpenGLExtensionManager *extensions = this->GetExtensionManager(); extensions->Modified(); this->ContextCreationTime.Modified(); // We have to set the function pointer to null, otherwise the following // scenario would fail on Windows (and maybe other kind of configurations): // 1. Render onscreen on GPU that supports OpenGL 1.4 // 2. Switch to offscreen with GDI Windows implementation (1.1) vtkgl::BlendFuncSeparate=0; // Try to initialize vtkgl::BlendFuncSeparate() if available. if (extensions->ExtensionSupported("GL_VERSION_1_4")) { extensions->LoadExtension("GL_VERSION_1_4"); } else { if (extensions->ExtensionSupported("GL_EXT_blend_func_separate")) { extensions->LoadCorePromotedExtension("GL_EXT_blend_func_separate"); } } } void vtkOpenGLRenderWindow::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); } int vtkOpenGLRenderWindow::GetDepthBufferSize() { GLint size; if ( this->Mapped ) { this->MakeCurrent(); size = 0; glGetIntegerv( GL_DEPTH_BITS, &size ); return static_cast(size); } else { vtkDebugMacro(<< "Window is not mapped yet!" ); return 24; } } int vtkOpenGLRenderWindow::GetColorBufferSizes(int *rgba) { GLint size; if (rgba==NULL) { return 0; } rgba[0] = 0; rgba[1] = 0; rgba[2] = 0; rgba[3] = 0; if ( this->Mapped) { this->MakeCurrent(); glGetIntegerv( GL_RED_BITS, &size ); rgba[0] = static_cast(size); glGetIntegerv( GL_GREEN_BITS, &size ); rgba[1] = static_cast(size); glGetIntegerv( GL_BLUE_BITS, &size ); rgba[2] = static_cast(size); glGetIntegerv( GL_ALPHA_BITS, &size ); rgba[3] = static_cast(size); return rgba[0]+rgba[1]+rgba[2]+rgba[3]; } else { vtkDebugMacro(<< "Window is not mapped yet!" ); rgba[0] = 8; rgba[1] = 8; rgba[2] = 8; rgba[3] = 8; return 32; } } unsigned char* vtkOpenGLRenderWindow::GetPixelData(int x1, int y1, int x2, int y2, int front, int right) { int y_low, y_hi; int x_low, x_hi; if (y1 < y2) { y_low = y1; y_hi = y2; } else { y_low = y2; y_hi = y1; } if (x1 < x2) { x_low = x1; x_hi = x2; } else { x_low = x2; x_hi = x1; } unsigned char *data = new unsigned char[(x_hi - x_low + 1)*(y_hi - y_low + 1)*3]; this->GetPixelData(x1, y1, x2, y2, front, data, right); return data; } int vtkOpenGLRenderWindow::GetPixelData(int x1, int y1, int x2, int y2, int front, vtkUnsignedCharArray* data, int right) { int y_low, y_hi; int x_low, x_hi; if (y1 < y2) { y_low = y1; y_hi = y2; } else { y_low = y2; y_hi = y1; } if (x1 < x2) { x_low = x1; x_hi = x2; } else { x_low = x2; x_hi = x1; } int width = abs(x_hi - x_low) + 1; int height = abs(y_hi - y_low) + 1; int size = 3*width*height; if ( data->GetMaxId()+1 != size) { vtkDebugMacro("Resizing array."); data->SetNumberOfComponents(3); data->SetNumberOfValues(size); } return this->GetPixelData(x1, y1, x2, y2, front, data->GetPointer(0), right); } int vtkOpenGLRenderWindow::GetPixelData(int x1, int y1, int x2, int y2, int front, unsigned char* data, int right) { int y_low, y_hi; int x_low, x_hi; // set the current window this->MakeCurrent(); if (y1 < y2) { y_low = y1; y_hi = y2; } else { y_low = y2; y_hi = y1; } if (x1 < x2) { x_low = x1; x_hi = x2; } else { x_low = x2; x_hi = x1; } // Must clear previous errors first. while(glGetError() != GL_NO_ERROR) { ; } if (front) { if (right) { glReadBuffer(static_cast(this->GetFrontRightBuffer())); } else { glReadBuffer(static_cast(this->GetFrontLeftBuffer())); } } else { if (right) { glReadBuffer(static_cast(this->GetBackRightBuffer())); } else { glReadBuffer(static_cast(this->GetBackLeftBuffer())); } } glDisable( GL_SCISSOR_TEST ); // Turn of texturing in case it is on - some drivers have a problem // getting / setting pixels with texturing enabled. glDisable( GL_TEXTURE_2D ); // Calling pack alignment ensures that we can grab the any size window glPixelStorei( GL_PACK_ALIGNMENT, 1 ); glReadPixels(x_low, y_low, x_hi-x_low+1, y_hi-y_low+1, GL_RGB, GL_UNSIGNED_BYTE, data); if (glGetError() != GL_NO_ERROR) { return VTK_ERROR; } else { return VTK_OK; } } int vtkOpenGLRenderWindow::SetPixelData(int x1, int y1, int x2, int y2, vtkUnsignedCharArray *data, int front, int right) { int y_low, y_hi; int x_low, x_hi; if (y1 < y2) { y_low = y1; y_hi = y2; } else { y_low = y2; y_hi = y1; } if (x1 < x2) { x_low = x1; x_hi = x2; } else { x_low = x2; x_hi = x1; } int width = abs(x_hi - x_low) + 1; int height = abs(y_hi - y_low) + 1; int size = 3*width*height; if ( data->GetMaxId()+1 != size) { vtkErrorMacro("Buffer is of wrong size."); return VTK_ERROR; } return this->SetPixelData(x1, y1, x2, y2, data->GetPointer(0), front, right); } int vtkOpenGLRenderWindow::SetPixelData(int x1, int y1, int x2, int y2, unsigned char *data, int front, int right) { int y_low, y_hi; int x_low, x_hi; // set the current window this->MakeCurrent(); // Error checking // Must clear previous errors first. while(glGetError() != GL_NO_ERROR) { ; } GLint buffer; glGetIntegerv(GL_DRAW_BUFFER, &buffer); if (front) { if (right) { glDrawBuffer(this->GetFrontRightBuffer()); } else { glDrawBuffer(this->GetFrontLeftBuffer()); } } else { if (right) { glDrawBuffer(this->GetBackRightBuffer()); } else { glDrawBuffer(this->GetBackLeftBuffer()); } } if (y1 < y2) { y_low = y1; y_hi = y2; } else { y_low = y2; y_hi = y1; } if (x1 < x2) { x_low = x1; x_hi = x2; } else { x_low = x2; x_hi = x1; } glDisable( GL_SCISSOR_TEST ); glViewport(0, 0, this->Size[0], this->Size[1]); // Turn of texturing in case it is on - some drivers have a problem // getting / setting pixels with texturing enabled. glDisable( GL_TEXTURE_2D ); // now write the binary info glMatrixMode( GL_MODELVIEW ); glPushMatrix(); glLoadIdentity(); glMatrixMode( GL_PROJECTION ); glPushMatrix(); glLoadIdentity(); glRasterPos3f( (2.0 * static_cast(x_low) / this->Size[0] - 1), (2.0 * static_cast(y_low) / this->Size[1] - 1), -1.0 ); glMatrixMode( GL_PROJECTION ); glPopMatrix(); glMatrixMode( GL_MODELVIEW ); glPopMatrix(); glPixelStorei( GL_UNPACK_ALIGNMENT, 1); glDisable(GL_BLEND); glDrawPixels((x_hi-x_low+1), (y_hi - y_low + 1), GL_RGB, GL_UNSIGNED_BYTE, data); glEnable(GL_BLEND); // This seems to be necessary for the image to show up glFlush(); glDrawBuffer(buffer); if (glGetError() != GL_NO_ERROR) { return VTK_ERROR; } else { return VTK_OK; } } float* vtkOpenGLRenderWindow::GetRGBAPixelData(int x1, int y1, int x2, int y2, int front, int right) { int y_low, y_hi; int x_low, x_hi; int width, height; if (y1 < y2) { y_low = y1; y_hi = y2; } else { y_low = y2; y_hi = y1; } if (x1 < x2) { x_low = x1; x_hi = x2; } else { x_low = x2; x_hi = x1; } width = abs(x_hi - x_low) + 1; height = abs(y_hi - y_low) + 1; float *data = new float[ (width*height*4) ]; this->GetRGBAPixelData(x1, y1, x2, y2, front, data, right); return data; } int vtkOpenGLRenderWindow::GetRGBAPixelData(int x1, int y1, int x2, int y2, int front, vtkFloatArray* data, int right) { int y_low, y_hi; int x_low, x_hi; int width, height; if (y1 < y2) { y_low = y1; y_hi = y2; } else { y_low = y2; y_hi = y1; } if (x1 < x2) { x_low = x1; x_hi = x2; } else { x_low = x2; x_hi = x1; } width = abs(x_hi - x_low) + 1; height = abs(y_hi - y_low) + 1; int size = 4*width*height; if ( data->GetMaxId()+1 != size) { vtkDebugMacro("Resizing array."); data->SetNumberOfComponents(4); data->SetNumberOfValues(size); } return this->GetRGBAPixelData(x1, y1, x2, y2, front, data->GetPointer(0), right); } int vtkOpenGLRenderWindow::GetRGBAPixelData(int x1, int y1, int x2, int y2, int front, float* data, int right) { int y_low, y_hi; int x_low, x_hi; int width, height; // set the current window this->MakeCurrent(); if (y1 < y2) { y_low = y1; y_hi = y2; } else { y_low = y2; y_hi = y1; } if (x1 < x2) { x_low = x1; x_hi = x2; } else { x_low = x2; x_hi = x1; } // Error checking // Must clear previous errors first. while(glGetError() != GL_NO_ERROR) { ; } if (front) { if (right) { glReadBuffer(static_cast(this->GetFrontRightBuffer())); } else { glReadBuffer(static_cast(this->GetFrontLeftBuffer())); } } else { if (right) { glReadBuffer(static_cast(this->GetBackRightBuffer())); } else { glReadBuffer(static_cast(this->GetBackLeftBuffer())); } } width = abs(x_hi - x_low) + 1; height = abs(y_hi - y_low) + 1; // Turn of texturing in case it is on - some drivers have a problem // getting / setting pixels with texturing enabled. glDisable( GL_TEXTURE_2D ); glPixelStorei( GL_PACK_ALIGNMENT, 1 ); glReadPixels( x_low, y_low, width, height, GL_RGBA, GL_FLOAT, data); if (glGetError() != GL_NO_ERROR) { return VTK_ERROR; } else { return VTK_OK; } } void vtkOpenGLRenderWindow::ReleaseRGBAPixelData(float *data) { delete[] data; } int vtkOpenGLRenderWindow::SetRGBAPixelData(int x1, int y1, int x2, int y2, vtkFloatArray *data, int front, int blend, int right) { int y_low, y_hi; int x_low, x_hi; int width, height; if (y1 < y2) { y_low = y1; y_hi = y2; } else { y_low = y2; y_hi = y1; } if (x1 < x2) { x_low = x1; x_hi = x2; } else { x_low = x2; x_hi = x1; } width = abs(x_hi-x_low) + 1; height = abs(y_hi-y_low) + 1; int size = 4*width*height; if ( data->GetMaxId()+1 != size ) { vtkErrorMacro("Buffer is of wrong size."); return VTK_ERROR; } return this->SetRGBAPixelData(x1, y1, x2, y2, data->GetPointer(0), front, blend, right); } int vtkOpenGLRenderWindow::SetRGBAPixelData(int x1, int y1, int x2, int y2, float *data, int front, int blend, int right) { int y_low, y_hi; int x_low, x_hi; int width, height; // set the current window this->MakeCurrent(); // Error checking // Must clear previous errors first. while(glGetError() != GL_NO_ERROR) { ; } GLint buffer; glGetIntegerv(GL_DRAW_BUFFER, &buffer); if (front) { if (right) { glDrawBuffer(this->GetFrontRightBuffer()); } else { glDrawBuffer(this->GetFrontLeftBuffer()); } } else { if (right) { glDrawBuffer(this->GetBackRightBuffer()); } else { glDrawBuffer(this->GetBackLeftBuffer()); } } if (y1 < y2) { y_low = y1; y_hi = y2; } else { y_low = y2; y_hi = y1; } if (x1 < x2) { x_low = x1; x_hi = x2; } else { x_low = x2; x_hi = x1; } width = abs(x_hi-x_low) + 1; height = abs(y_hi-y_low) + 1; /* write out a row of pixels */ glDisable( GL_ALPHA_TEST ); glDisable( GL_SCISSOR_TEST ); glViewport(0, 0, this->Size[0], this->Size[1]); glMatrixMode( GL_MODELVIEW ); glPushMatrix(); glLoadIdentity(); glMatrixMode( GL_PROJECTION ); glPushMatrix(); glLoadIdentity(); glRasterPos3f( (2.0 * static_cast(x_low) / this->Size[0] - 1), (2.0 * static_cast(y_low) / this->Size[1] - 1), -1.0 ); glMatrixMode( GL_PROJECTION ); glPopMatrix(); glMatrixMode( GL_MODELVIEW ); glPopMatrix(); glPixelStorei( GL_UNPACK_ALIGNMENT, 1); if (!blend) { glDisable(GL_BLEND); glDrawPixels( width, height, GL_RGBA, GL_FLOAT, data); glEnable(GL_BLEND); } else { glDrawPixels( width, height, GL_RGBA, GL_FLOAT, data); } // This seems to be necessary for the image to show up glFlush(); glDrawBuffer(buffer); if (glGetError() != GL_NO_ERROR) { return VTK_ERROR; } else { return VTK_OK; } } unsigned char *vtkOpenGLRenderWindow::GetRGBACharPixelData(int x1, int y1, int x2, int y2, int front, int right) { int y_low, y_hi; int x_low, x_hi; int width, height; if (y1 < y2) { y_low = y1; y_hi = y2; } else { y_low = y2; y_hi = y1; } if (x1 < x2) { x_low = x1; x_hi = x2; } else { x_low = x2; x_hi = x1; } width = abs(x_hi - x_low) + 1; height = abs(y_hi - y_low) + 1; unsigned char *data = new unsigned char[ (width*height)*4 ]; this->GetRGBACharPixelData(x1, y1, x2, y2, front, data, right); return data; } int vtkOpenGLRenderWindow::GetRGBACharPixelData(int x1, int y1, int x2, int y2, int front, vtkUnsignedCharArray* data, int right) { int y_low, y_hi; int x_low, x_hi; if (y1 < y2) { y_low = y1; y_hi = y2; } else { y_low = y2; y_hi = y1; } if (x1 < x2) { x_low = x1; x_hi = x2; } else { x_low = x2; x_hi = x1; } int width = abs(x_hi - x_low) + 1; int height = abs(y_hi - y_low) + 1; int size = 4*width*height; if ( data->GetMaxId()+1 != size) { vtkDebugMacro("Resizing array."); data->SetNumberOfComponents(4); data->SetNumberOfValues(size); } return this->GetRGBACharPixelData(x1, y1, x2, y2, front, data->GetPointer(0), right); } int vtkOpenGLRenderWindow::GetRGBACharPixelData(int x1, int y1, int x2, int y2, int front, unsigned char* data, int right) { int y_low, y_hi; int x_low, x_hi; int width, height; // set the current window this->MakeCurrent(); if (y1 < y2) { y_low = y1; y_hi = y2; } else { y_low = y2; y_hi = y1; } if (x1 < x2) { x_low = x1; x_hi = x2; } else { x_low = x2; x_hi = x1; } // Must clear previous errors first. while(glGetError() != GL_NO_ERROR) { ; } if (front) { if (right) { glReadBuffer(static_cast(this->GetFrontRightBuffer())); } else { glReadBuffer(static_cast(this->GetFrontLeftBuffer())); } } else { if (right) { glReadBuffer(static_cast(this->GetBackRightBuffer())); } else { glReadBuffer(static_cast(this->GetBackLeftBuffer())); } } width = abs(x_hi - x_low) + 1; height = abs(y_hi - y_low) + 1; glDisable( GL_SCISSOR_TEST ); // Turn of texturing in case it is on - some drivers have a problem // getting / setting pixels with texturing enabled. glDisable( GL_TEXTURE_2D ); glReadPixels( x_low, y_low, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data); if (glGetError() != GL_NO_ERROR) { return VTK_ERROR; } else { return VTK_OK; } } int vtkOpenGLRenderWindow::SetRGBACharPixelData(int x1,int y1,int x2,int y2, vtkUnsignedCharArray *data, int front, int blend, int right) { int y_low, y_hi; int x_low, x_hi; int width, height; if (y1 < y2) { y_low = y1; y_hi = y2; } else { y_low = y2; y_hi = y1; } if (x1 < x2) { x_low = x1; x_hi = x2; } else { x_low = x2; x_hi = x1; } width = abs(x_hi-x_low) + 1; height = abs(y_hi-y_low) + 1; int size = 4*width*height; if ( data->GetMaxId()+1 != size ) { vtkErrorMacro("Buffer is of wrong size. It is " << data->GetMaxId()+1 << ", it should be: " << size); return VTK_ERROR; } return this->SetRGBACharPixelData(x1, y1, x2, y2, data->GetPointer(0), front, blend, right); } int vtkOpenGLRenderWindow::SetRGBACharPixelData(int x1, int y1, int x2, int y2, unsigned char *data, int front, int blend, int right) { int y_low, y_hi; int x_low, x_hi; int width, height; // set the current window this->MakeCurrent(); // Error checking // Must clear previous errors first. while(glGetError() != GL_NO_ERROR) { ; } GLint buffer; glGetIntegerv(GL_DRAW_BUFFER, &buffer); if (front) { if (right) { glDrawBuffer(this->GetFrontRightBuffer()); } else { glDrawBuffer(this->GetFrontLeftBuffer()); } } else { if (right) { glDrawBuffer(this->GetBackRightBuffer()); } else { glDrawBuffer(this->GetBackLeftBuffer()); } } if (y1 < y2) { y_low = y1; y_hi = y2; } else { y_low = y2; y_hi = y1; } if (x1 < x2) { x_low = x1; x_hi = x2; } else { x_low = x2; x_hi = x1; } width = abs(x_hi-x_low) + 1; height = abs(y_hi-y_low) + 1; /* write out a row of pixels */ glViewport(0, 0, this->Size[0], this->Size[1]); glMatrixMode( GL_MODELVIEW ); glPushMatrix(); glLoadIdentity(); glMatrixMode( GL_PROJECTION ); glPushMatrix(); glLoadIdentity(); glRasterPos3f( (2.0 * static_cast(x_low) / this->Size[0] - 1), (2.0 * static_cast(y_low) / this->Size[1] - 1), -1.0 ); glMatrixMode( GL_PROJECTION ); glPopMatrix(); glMatrixMode( GL_MODELVIEW ); glPopMatrix(); glDisable( GL_ALPHA_TEST ); glDisable( GL_SCISSOR_TEST ); // Disable writing on the z-buffer. glDepthMask(GL_FALSE); glDisable(GL_DEPTH_TEST); // Turn of texturing in case it is on - some drivers have a problem // getting / setting pixels with texturing enabled. glDisable( GL_TEXTURE_2D ); if (!blend) { glDisable(GL_BLEND); glDrawPixels( width, height, GL_RGBA, GL_UNSIGNED_BYTE, data); glEnable(GL_BLEND); } else { glDrawPixels( width, height, GL_RGBA, GL_UNSIGNED_BYTE, data); } // Renenable writing on the z-buffer. glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); // This seems to be necessary for the image to show up glFlush(); glDrawBuffer(buffer); if (glGetError() != GL_NO_ERROR) { return VTK_ERROR; } else { return VTK_OK; } } int vtkOpenGLRenderWindow::GetZbufferData( int x1, int y1, int x2, int y2, float* z_data ) { int y_low; int x_low; int width, height; // set the current window this->MakeCurrent(); if (y1 < y2) { y_low = y1; } else { y_low = y2; } if (x1 < x2) { x_low = x1; } else { x_low = x2; } width = abs(x2 - x1)+1; height = abs(y2 - y1)+1; // Error checking // Must clear previous errors first. while(glGetError() != GL_NO_ERROR) { ; } // Turn of texturing in case it is on - some drivers have a problem // getting / setting pixels with texturing enabled. glDisable( GL_TEXTURE_2D ); glDisable( GL_SCISSOR_TEST ); glPixelStorei( GL_PACK_ALIGNMENT, 1 ); glReadPixels( x_low, y_low, width, height, GL_DEPTH_COMPONENT, GL_FLOAT, z_data ); if (glGetError() != GL_NO_ERROR) { return VTK_ERROR; } else { return VTK_OK; } } float *vtkOpenGLRenderWindow::GetZbufferData( int x1, int y1, int x2, int y2 ) { float *z_data; int width, height; width = abs(x2 - x1)+1; height = abs(y2 - y1)+1; z_data = new float[width*height]; this->GetZbufferData(x1, y1, x2, y2, z_data); return z_data; } int vtkOpenGLRenderWindow::GetZbufferData( int x1, int y1, int x2, int y2, vtkFloatArray *buffer ) { int width, height; width = abs(x2 - x1)+1; height = abs(y2 - y1)+1; int size = width*height; if ( buffer->GetMaxId()+1 != size) { vtkDebugMacro("Resizing array."); buffer->SetNumberOfComponents(1); buffer->SetNumberOfValues(size); } return this->GetZbufferData(x1, y1, x2, y2, buffer->GetPointer(0)); } int vtkOpenGLRenderWindow::SetZbufferData( int x1, int y1, int x2, int y2, vtkFloatArray *buffer ) { int width, height; width = abs(x2 - x1)+1; height = abs(y2 - y1)+1; int size = width*height; if ( buffer->GetMaxId()+1 != size ) { vtkErrorMacro("Buffer is of wrong size."); return VTK_ERROR; } return this->SetZbufferData(x1, y1, x2, y2, buffer->GetPointer(0)); } int vtkOpenGLRenderWindow::SetZbufferData( int x1, int y1, int x2, int y2, float *buffer ) { int y_low; int x_low; int width, height; // set the current window this->MakeCurrent(); if (y1 < y2) { y_low = y1; } else { y_low = y2; } if (x1 < x2) { x_low = x1; } else { x_low = x2; } width = abs(x2 - x1)+1; height = abs(y2 - y1)+1; // Error checking // Must clear previous errors first. while(glGetError() != GL_NO_ERROR) { ; } glViewport(0, 0, this->Size[0], this->Size[1]); glMatrixMode( GL_MODELVIEW ); glPushMatrix(); glLoadIdentity(); glMatrixMode( GL_PROJECTION ); glPushMatrix(); glLoadIdentity(); glRasterPos2f( 2.0 * static_cast(x_low) / this->Size[0] - 1, 2.0 * static_cast(y_low) / this->Size[1] - 1); glMatrixMode( GL_PROJECTION ); glPopMatrix(); glMatrixMode( GL_MODELVIEW ); glPopMatrix(); glDisable( GL_ALPHA_TEST ); glDisable( GL_SCISSOR_TEST ); int gldepth; glGetIntegerv(GL_DEPTH_FUNC, &gldepth); glDepthFunc(GL_ALWAYS); // Turn of texturing in case it is on - some drivers have a problem // getting / setting pixels with texturing enabled. glDisable( GL_TEXTURE_2D ); glPixelStorei( GL_PACK_ALIGNMENT, 1 ); glDrawPixels( width, height, GL_DEPTH_COMPONENT, GL_FLOAT, buffer); // This seems to be necessary for the image to show up glFlush(); glDepthFunc(gldepth); if (glGetError() != GL_NO_ERROR) { return VTK_ERROR; } else { return VTK_OK; } } void vtkOpenGLRenderWindow::RegisterTextureResource (GLuint id) { this->TextureResourceIds->InsertNextId (static_cast(id)); } // ---------------------------------------------------------------------------- // Description: // Create an offScreen window based on OpenGL framebuffer extension. // Return if the creation was successful or not. // \pre positive_width: width>0 // \pre positive_height: height>0 // \pre not_initialized: !OffScreenUseFrameBuffer // \post valid_result: (result==0 || result==1) // && (result implies OffScreenUseFrameBuffer) int vtkOpenGLRenderWindow::CreateHardwareOffScreenWindow(int width, int height) { assert("pre: positive_width" && width>0); assert("pre: positive_height" && height>0); assert("pre: not_initialized" && !this->OffScreenUseFrameBuffer); // Create a regular OpenGLcontext (ie create a window) this->CreateAWindow(); this->MakeCurrent(); this->OpenGLInit(); int result = this->CreateHardwareOffScreenBuffers(width, height); if (!result) { this->DestroyWindow(); } else { this->BindHardwareOffScreenBuffers(); this->OffScreenUseFrameBuffer = 1; } // A=>B = !A || B assert("post: valid_result" && (result==0 || result==1) && (!result || OffScreenUseFrameBuffer)); return result; } // ---------------------------------------------------------------------------- // Description: // Create an offScreen rendering buffer based on OpenGL framebuffer extension. // Return if the creation was successful or not. int vtkOpenGLRenderWindow::CreateHardwareOffScreenBuffers(int width, int height, bool bind) { assert("pre: positive_width" && width>0); assert("pre: positive_height" && height>0); // This implementation currently ignores multisampling configurations: if (this->MultiSamples > 1) { vtkDebugMacro(<<"Multisampling is not currently supported by the " "accelerated offscreen rendering backend. Falling back to " "a platform-specific offscreen solution..."); return 0; } this->MakeCurrent(); if (this->FrameBufferObject && this->HardwareBufferSize[0] == width && this->HardwareBufferSize[1] == height) { if (bind) { this->BindHardwareOffScreenBuffers(); } return 1; } if (this->FrameBufferObject) { this->DestroyHardwareOffScreenBuffers(); } this->FrameBufferObject = 0; this->HardwareBufferSize[0] = 0; this->HardwareBufferSize[1] = 0; // Check for OpenGL extensions GL_EXT/ARB_framebuffer_object and // GL_ARB_texture_non_power_of_two (core-promoted feature in OpenGL 2.0) vtkOpenGLExtensionManager *extensions = this->GetExtensionManager(); float glVersion; sscanf(reinterpret_cast(glGetString(GL_VERSION)), "%f", &glVersion); int supports_GL_EXT_framebuffer_object = glVersion >= 3.0 || extensions->ExtensionSupported("GL_EXT_framebuffer_object") || extensions->ExtensionSupported("GL_ARB_framebuffer_object"); // TODO Mesa 6.5.1 is from 2006 verify that this is still an issue // with newer releases // We skip it if you use Mesa. Even if the VTK offscreen test passes (OSCone) // with Mesa, all the Paraview batch test are failing (Mesa 6.5.1 or CVS) // After too much time spent to investigate this case, we just skip it. int isMesa = false; /*= extensions->DriverGLRendererHas("Mesa") && !extensions->GetIgnoreDriverBugs("Mesa 6.5.1 pvbatch offscreen bug");*/ int supports_texture_non_power_of_two = extensions->ExtensionSupported("GL_VERSION_2_0") || extensions->ExtensionSupported("GL_ARB_texture_non_power_of_two"); int supports_texture_rectangle = extensions->ExtensionSupported("GL_ARB_texture_rectangle"); // The following extension does not exist on ATI. There will be no HW // Offscreen on ATI if a stencil buffer is required. int supports_packed_depth_stencil = extensions->ExtensionSupported("GL_EXT_packed_depth_stencil"); if(!(supports_GL_EXT_framebuffer_object && (supports_texture_non_power_of_two || supports_texture_rectangle) && !isMesa && (!this->StencilCapable || supports_packed_depth_stencil))) { if (!supports_GL_EXT_framebuffer_object) { vtkDebugMacro( << " extension GL_EXT_framebuffer_object is not supported. " "Hardware accelerated offscreen rendering is not available" ); } if (!supports_texture_non_power_of_two) { vtkDebugMacro( << " extension texture_non_power_of_two is not supported " "because neither OpenGL 2.0 nor GL_ARB_texture_non_power_of_two extension " "is supported. Hardware accelerated offscreen rendering is not available"); } if (!supports_texture_rectangle) { vtkDebugMacro(<<" extension GL_ARB_texture_rectangle is not supported"); } if (isMesa) { vtkDebugMacro(<<" Renderer is Mesa. Hardware accelerated offscreen " "rendering is not available"); } if (this->StencilCapable && !supports_packed_depth_stencil) { vtkDebugMacro(<<" a stencil buffer is required but extension " "GL_EXT_packed_depth_stencil is not supported"); } return 0; } int result = 0; if (!extensions->LoadSupportedExtension("GL_EXT_framebuffer_object")) { extensions->LoadSupportedExtension("GL_ARB_framebuffer_object"); } this->NumberOfFrameBuffers = 1; GLboolean isStereo; glGetBooleanv(GL_STEREO, &isStereo); if (isStereo) { this->NumberOfFrameBuffers = 2; } // Up to 2 for stereo GLuint textureObjects[2] = { 0, 0 }; GLuint frameBufferObject; GLuint depthRenderBufferObject; vtkgl::GenFramebuffersEXT(1, &frameBufferObject); // color vtkgl::GenRenderbuffersEXT(1, &depthRenderBufferObject); // depth glGenTextures(this->NumberOfFrameBuffers, textureObjects); // Bind the color buffer vtkgl::BindFramebufferEXT(vtkgl::FRAMEBUFFER_EXT, frameBufferObject); GLenum target = supports_texture_non_power_of_two ? GL_TEXTURE_2D : vtkgl::TEXTURE_RECTANGLE_ARB; for (int i = 0 ; i < this->NumberOfFrameBuffers; i++) { glBindTexture(target, textureObjects[i]); glTexParameteri(target, GL_TEXTURE_WRAP_S, vtkgl::CLAMP_TO_EDGE); glTexParameteri(target, GL_TEXTURE_WRAP_T, vtkgl::CLAMP_TO_EDGE); glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexImage2D(target, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); vtkgl::FramebufferTexture2DEXT(vtkgl::FRAMEBUFFER_EXT, vtkgl::COLOR_ATTACHMENT0_EXT+i, target, textureObjects[i], 0); } GLenum status = vtkgl::CheckFramebufferStatusEXT(vtkgl::FRAMEBUFFER_EXT); if (status == vtkgl::FRAMEBUFFER_UNSUPPORTED_EXT && target == GL_TEXTURE_2D && supports_texture_rectangle) { // The following cards fall in this case: // GeForce FX Go5650/AGP/SSE2 with Linux driver 2.0.2 NVIDIA 87.76 // GeForce FX 5900 Ultra/AGP/SSE2 with Linux driver 2.0.2 NVIDIA 87.74 // GeForce FX 5200/AGP/SSE2 with Windows XP SP2 32bit driver 2.0.3 // Quadro FX 1000/AGP/SSE2 with Windows XP SP2 32bit driver 2.0.1 // Quadro FX 2000/AGP/SSE2 with Windows XP SP2 32bit driver 2.0.1 target = vtkgl::TEXTURE_RECTANGLE_ARB; // try again. glDeleteTextures(this->NumberOfFrameBuffers, textureObjects); glGenTextures(this->NumberOfFrameBuffers, textureObjects); for (int i = 0; i < this->NumberOfFrameBuffers; i++) { glBindTexture(target, textureObjects[i]); glTexParameteri(target, GL_TEXTURE_WRAP_S, vtkgl::CLAMP_TO_EDGE); glTexParameteri(target, GL_TEXTURE_WRAP_T, vtkgl::CLAMP_TO_EDGE); glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexImage2D(target, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); vtkgl::FramebufferTexture2DEXT(vtkgl::FRAMEBUFFER_EXT, vtkgl::COLOR_ATTACHMENT0_EXT+i, target, textureObjects[i], 0); } // Ask for the status again. status = vtkgl::CheckFramebufferStatusEXT(vtkgl::FRAMEBUFFER_EXT); } if (status != vtkgl::FRAMEBUFFER_COMPLETE_EXT) { vtkDebugMacro(<< "Hardware does not support GPU Offscreen rendering."); vtkgl::DeleteFramebuffersEXT(1, &frameBufferObject); vtkgl::DeleteRenderbuffersEXT(1, &depthRenderBufferObject); glDeleteTextures(this->NumberOfFrameBuffers, textureObjects); bind = true; } else { // Set up the depth (and stencil), render buffer vtkgl::BindRenderbufferEXT(vtkgl::RENDERBUFFER_EXT, depthRenderBufferObject); vtkgl::RenderbufferStorageEXT(vtkgl::RENDERBUFFER_EXT, this->StencilCapable ? vtkgl::DEPTH_STENCIL_EXT : vtkgl::DEPTH_COMPONENT24, width, height); vtkgl::FramebufferRenderbufferEXT(vtkgl::FRAMEBUFFER_EXT, vtkgl::DEPTH_ATTACHMENT_EXT, vtkgl::RENDERBUFFER_EXT, depthRenderBufferObject); if (this->StencilCapable) { vtkgl::FramebufferRenderbufferEXT(vtkgl::FRAMEBUFFER_EXT, vtkgl::STENCIL_ATTACHMENT_EXT, vtkgl::RENDERBUFFER_EXT, depthRenderBufferObject); } // Last check to see if the FBO is supported or not. status = vtkgl::CheckFramebufferStatusEXT(vtkgl::FRAMEBUFFER_EXT); if (status != vtkgl::FRAMEBUFFER_COMPLETE_EXT) { vtkDebugMacro(<< "Hardware does not support GPU Offscreen rendering with" "this depth/stencil configuration."); glBindTexture(target, 0); vtkgl::DeleteFramebuffersEXT(1, &frameBufferObject); vtkgl::DeleteRenderbuffersEXT(1, &depthRenderBufferObject); glDeleteTextures(this->NumberOfFrameBuffers, textureObjects); bind = true; } else { result = 1; // Save GL objects by static casting to standard C types. GL* types // are not allowed in VTK header files. this->FrameBufferObject = static_cast(frameBufferObject); this->DepthRenderBufferObject = static_cast(depthRenderBufferObject); for (int i = 0; i < this->NumberOfFrameBuffers; i++) { this->TextureObjects[i] = static_cast(textureObjects[i]); } this->HardwareBufferSize[0] = width; this->HardwareBufferSize[1] = height; this->HardwareOffScreenBuffersBind = true; if (bind) { unsigned int buffer = static_cast(vtkgl::COLOR_ATTACHMENT0_EXT); this->BackLeftBuffer = buffer; this->FrontLeftBuffer = buffer; this->BackBuffer = buffer; this->FrontBuffer = buffer; if (this->NumberOfFrameBuffers == 2) { buffer = static_cast(vtkgl::COLOR_ATTACHMENT1_EXT); this->BackRightBuffer = buffer; this->FrontRightBuffer = buffer; } } } } if (!bind) { // Rebind the hardware on-screen buffer for now this->UnbindHardwareOffScreenBuffers(); } // A=>B = !A || B assert("post: valid_result" && (result==0 || result==1) && (!result || this->FrameBufferObject)); return result; } // ---------------------------------------------------------------------------- void vtkOpenGLRenderWindow::BindHardwareOffScreenBuffers() { if (!this->FrameBufferObject || this->HardwareOffScreenBuffersBind) { return; } this->MakeCurrent(); vtkgl::BindFramebufferEXT(vtkgl::FRAMEBUFFER_EXT, static_cast(this->FrameBufferObject)); unsigned int buffer = static_cast(vtkgl::COLOR_ATTACHMENT0_EXT); this->BackLeftBuffer = buffer; this->FrontLeftBuffer = buffer; this->BackBuffer = buffer; this->FrontBuffer = buffer; if (this->NumberOfFrameBuffers == 2) { buffer = static_cast(vtkgl::COLOR_ATTACHMENT1_EXT); this->BackRightBuffer = buffer; this->FrontRightBuffer = buffer; } this->HardwareOffScreenBuffersBind = true; } // ---------------------------------------------------------------------------- void vtkOpenGLRenderWindow::UnbindHardwareOffScreenBuffers() { if (!this->FrameBufferObject || !this->HardwareOffScreenBuffersBind) { return; } this->MakeCurrent(); vtkgl::BindFramebufferEXT(vtkgl::FRAMEBUFFER_EXT, 0); // Restore framebuffer names. this->BackLeftBuffer = static_cast(GL_BACK_LEFT); this->BackRightBuffer = static_cast(GL_BACK_RIGHT); this->FrontLeftBuffer = static_cast(GL_FRONT_LEFT); this->FrontRightBuffer = static_cast(GL_FRONT_RIGHT); this->BackBuffer = static_cast(GL_BACK); this->FrontBuffer = static_cast(GL_FRONT); this->HardwareOffScreenBuffersBind = false; } // ---------------------------------------------------------------------------- void vtkOpenGLRenderWindow::DestroyHardwareOffScreenBuffers() { if (!this->FrameBufferObject) { return; } this->UnbindHardwareOffScreenBuffers(); GLuint frameBufferObject = static_cast(this->FrameBufferObject); vtkgl::DeleteFramebuffersEXT(1, &frameBufferObject); this->FrameBufferObject = 0; GLuint depthRenderBufferObject = static_cast(this->DepthRenderBufferObject); vtkgl::DeleteRenderbuffersEXT(1, &depthRenderBufferObject); this->DepthRenderBufferObject = 0; GLuint textureObjects[4]; for (int i = 0; i < this->NumberOfFrameBuffers; i++) { textureObjects[i] = static_cast(this->TextureObjects[i]); } glDeleteTextures(this->NumberOfFrameBuffers, textureObjects); this->DepthRenderBufferObject = 0; this->FrameBufferObject = 0; this->HardwareBufferSize[0] = 0; this->HardwareBufferSize[1] = 0; } // ---------------------------------------------------------------------------- // Description: // Destroy an offscreen window based on OpenGL framebuffer extension. // \pre initialized: OffScreenUseFrameBuffer // \post destroyed: !OffScreenUseFrameBuffer void vtkOpenGLRenderWindow::DestroyHardwareOffScreenWindow() { assert("pre: initialized" && this->OffScreenUseFrameBuffer); this->UnbindHardwareOffScreenBuffers(); this->DestroyHardwareOffScreenBuffers(); this->OffScreenUseFrameBuffer = 0; this->DestroyWindow(); } // ---------------------------------------------------------------------------- // Description: // Returns the extension manager. A new one will be created if one hasn't // already been set up. vtkOpenGLExtensionManager* vtkOpenGLRenderWindow::GetExtensionManager() { if (!this->ExtensionManager) { vtkOpenGLExtensionManager* mgr = vtkOpenGLExtensionManager::New(); // This does not form a reference loop since vtkOpenGLExtensionManager does // not keep a reference to the render window. mgr->SetRenderWindow(this); this->SetExtensionManager(mgr); mgr->Delete(); } return this->ExtensionManager; } // ---------------------------------------------------------------------------- // Description: // Returns an Hardware Support object. A new one will be created if one hasn't // already been set up. vtkOpenGLHardwareSupport* vtkOpenGLRenderWindow::GetHardwareSupport() { if (!this->HardwareSupport) { vtkOpenGLHardwareSupport* hardware = vtkOpenGLHardwareSupport::New(); // This does not form a reference loop since vtkOpenGLHardwareSupport does // not keep a reference to the render window. hardware->SetExtensionManager(this->GetExtensionManager()); this->SetHardwareSupport(hardware); hardware->Delete(); } return this->HardwareSupport; } // ---------------------------------------------------------------------------- // Description: // Returns its texture unit manager object. A new one will be created if one // hasn't already been set up. vtkTextureUnitManager *vtkOpenGLRenderWindow::GetTextureUnitManager() { if(this->TextureUnitManager==0) { vtkTextureUnitManager *manager=vtkTextureUnitManager::New(); // This does not form a reference loop since vtkOpenGLHardwareSupport does // not keep a reference to the render window. manager->SetContext(this); this->SetTextureUnitManager(manager); manager->Delete(); } return this->TextureUnitManager; } // ---------------------------------------------------------------------------- // Description: // Block the thread until the actual rendering is finished(). // Useful for measurement only. void vtkOpenGLRenderWindow::WaitForCompletion() { glFinish(); } // ---------------------------------------------------------------------------- int vtkOpenGLRenderWindow::SetUseOffScreenBuffers(bool offScreen) { if (this->OffScreenRendering || (!offScreen && !this->HardwareOffScreenBuffersBind)) { return 1; } if (!offScreen) { if (!this->OffScreenUseFrameBuffer) { this->UnbindHardwareOffScreenBuffers(); } return 1; } if (this->OffScreenUseFrameBuffer) { return 1; } // We are currently in on screen rendering mode. // Create offscreen buffers at the screen size. int* size = this->GetSize(); return this->CreateHardwareOffScreenBuffers(size[0], size[1], true); } // ---------------------------------------------------------------------------- bool vtkOpenGLRenderWindow::GetUseOffScreenBuffers() { return this->HardwareOffScreenBuffersBind || this->OffScreenRendering; }