diff --git a/CMake/vtkAndroid.cmake b/CMake/vtkAndroid.cmake
index 565a298fa45c77f99cd48a3653f4d85899020cc8..ba0faf65fe3ccd6089fbcc6a98c47f0b20dc79c8 100644
--- a/CMake/vtkAndroid.cmake
+++ b/CMake/vtkAndroid.cmake
@@ -48,6 +48,10 @@ if (NOT EXISTS ${CMAKE_INSTALL_PREFIX})
     "Install path ${CMAKE_INSTALL_PREFIX} does not exist.")
 endif()
 
+# make sure we have a CTestCustom.cmake file
+configure_file("${VTK_CMAKE_DIR}/CTestCustom.cmake.in"
+  "${CMAKE_CURRENT_BINARY_DIR}/CTestCustom.cmake" @ONLY)
+
 # Compile a minimal VTK for its compile tools
 macro(compile_vtk_tools)
   ExternalProject_Add(
diff --git a/CMake/vtkOpenGL.cmake b/CMake/vtkOpenGL.cmake
index 9e4baba2bc2caf627634fb5165012f036c394da8..9c23d425ac802cd9150bac8b780c0bbfc54510b2 100644
--- a/CMake/vtkOpenGL.cmake
+++ b/CMake/vtkOpenGL.cmake
@@ -146,6 +146,12 @@ if(VTK_CAN_DO_ONSCREEN)
   endif()
 endif()
 
+# windows  opengl delayed loading option
+if(WIN32)
+  option(VTK_USE_OPENGL_DELAYED_LOAD "Use delayed loading for the opengl dll" FALSE)
+  mark_as_advanced(VTK_USE_OPENGL_DELAYED_LOAD)
+endif()
+
 # Function to link a VTK target to the necessary OpenGL libraries.
 function(vtk_opengl_link target)
   if(VTK_OPENGL_HAS_OSMESA)
@@ -157,4 +163,8 @@ function(vtk_opengl_link target)
   if(VTK_CAN_DO_ONSCREEN)
     vtk_module_link_libraries(${target} LINK_PRIVATE ${OPENGL_LIBRARIES})
   endif()
+  if (VTK_USE_OPENGL_DELAYED_LOAD)
+    vtk_module_link_libraries(${target} LINK_PRIVATE delayimp.lib)
+    set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS "/DELAYLOAD:opengl32.dll")
+  endif()
 endfunction()
diff --git a/CMake/vtkVersion.cmake b/CMake/vtkVersion.cmake
index c75bcd29b8a6bd54a22cabc91ebb95f38bf8599d..c2c7190672e3d957b1fb9e9e32921057751581e3 100644
--- a/CMake/vtkVersion.cmake
+++ b/CMake/vtkVersion.cmake
@@ -1,4 +1,4 @@
 # VTK version number components.
 set(VTK_MAJOR_VERSION 8)
 set(VTK_MINOR_VERSION 1)
-set(VTK_BUILD_VERSION 0)
+set(VTK_BUILD_VERSION 1)
diff --git a/CMake/vtkiOS.cmake b/CMake/vtkiOS.cmake
index ab6f50e417c4190c0165c9f8c5da032b7b4932a5..83c7ae0d171ad511239a22fe727b0216b35ae38e 100644
--- a/CMake/vtkiOS.cmake
+++ b/CMake/vtkiOS.cmake
@@ -11,9 +11,9 @@ file(REMOVE_RECURSE ${BUILD_DIR})
 file(REMOVE_RECURSE ${INSTALL_DIR})
 
 # Define default architectures to compile for
-set(IOS_SIMULATOR_ARCHITECTURES "i386;x86_64"
+set(IOS_SIMULATOR_ARCHITECTURES "x86_64"
     CACHE STRING "iOS Simulator Architectures")
-set(IOS_DEVICE_ARCHITECTURES "arm64;armv7"
+set(IOS_DEVICE_ARCHITECTURES "arm64"
     CACHE STRING "iOS Device Architectures")
 list(REMOVE_DUPLICATES IOS_SIMULATOR_ARCHITECTURES)
 list(REMOVE_DUPLICATES IOS_DEVICE_ARCHITECTURES)
diff --git a/Common/Misc/vtkFunctionParser.cxx b/Common/Misc/vtkFunctionParser.cxx
index 3d19ccce11a44c994533bb9fa2c1ac9a85dc4671..283c78cb74df9cc0d75813a67ebd0d499a8c1795 100644
--- a/Common/Misc/vtkFunctionParser.cxx
+++ b/Common/Misc/vtkFunctionParser.cxx
@@ -2448,6 +2448,22 @@ void vtkFunctionParser::UpdateNeededVariables()
   }
 }
 
+//-----------------------------------------------------------------------------
+int vtkFunctionParser::GetScalarVariableIndex(const char* inVariableName)
+{
+  char* variableName = this->RemoveSpacesFrom(inVariableName);
+  for (int i = 0; i < static_cast<int>(this->ScalarVariableNames.size()); ++i)
+  {
+    if (this->ScalarVariableNames[i] == variableName)
+    {
+      delete [] variableName;
+      return i;
+    }
+  }
+  delete [] variableName;
+  return -1;
+}
+
 //-----------------------------------------------------------------------------
 bool vtkFunctionParser::GetScalarVariableNeeded(int i)
 {
@@ -2465,9 +2481,9 @@ bool vtkFunctionParser::GetScalarVariableNeeded(const char* inVariableName)
   std::vector<std::string>::const_iterator iter = std::find(
     this->ScalarVariableNames.begin(), this->ScalarVariableNames.end(),
     std::string(variableName));
-  delete [] variableName;
   if (iter != this->ScalarVariableNames.end())
   {
+    delete [] variableName;
     return this->GetScalarVariableNeeded(
       static_cast<int>(iter - this->ScalarVariableNames.begin()));
   }
@@ -2475,10 +2491,27 @@ bool vtkFunctionParser::GetScalarVariableNeeded(const char* inVariableName)
   {
     vtkErrorMacro("GetScalarVariableNeeded: scalar variable name " << variableName
                    << " does not exist");
+    delete [] variableName;
     return false;
   }
 }
 
+//-----------------------------------------------------------------------------
+int vtkFunctionParser::GetVectorVariableIndex(const char* inVariableName)
+{
+  char* variableName = this->RemoveSpacesFrom(inVariableName);
+  for (int i = 0; i < static_cast<int>(this->VectorVariableNames.size()); ++i)
+  {
+    if (this->VectorVariableNames[i] == variableName)
+    {
+      delete [] variableName;
+      return i;
+    }
+  }
+  delete [] variableName;
+  return -1;
+}
+
 //-----------------------------------------------------------------------------
 bool vtkFunctionParser::GetVectorVariableNeeded(int i)
 {
diff --git a/Common/Misc/vtkFunctionParser.h b/Common/Misc/vtkFunctionParser.h
index badff9670a6f423471629fd3d9b6b1b53f5ac587..56434526144bce3c1e15fe6f6ff6dc0808f28c5f 100644
--- a/Common/Misc/vtkFunctionParser.h
+++ b/Common/Misc/vtkFunctionParser.h
@@ -234,12 +234,22 @@ public:
   int GetNumberOfScalarVariables()
     { return static_cast<int>(this->ScalarVariableNames.size()); }
 
+  /**
+   * Get scalar variable index or -1 if not found
+   */
+  int GetScalarVariableIndex(const char *name);
+
   /**
    * Get the number of vector variables.
    */
   int GetNumberOfVectorVariables()
     { return static_cast<int>(this->VectorVariableNames.size()); }
 
+  /**
+   * Get scalar variable index or -1 if not found
+   */
+  int GetVectorVariableIndex(const char *name);
+
   /**
    * Get the ith scalar variable name.
    */
diff --git a/Filters/Core/vtkArrayCalculator.cxx b/Filters/Core/vtkArrayCalculator.cxx
index 0473eb75f95b4ab61dac4b701f7dad6a64c9e823..92d8d15f8613c71a92445497ba8b6b5f8b8c37d9 100644
--- a/Filters/Core/vtkArrayCalculator.cxx
+++ b/Filters/Core/vtkArrayCalculator.cxx
@@ -427,18 +427,34 @@ int vtkArrayCalculator::RequestData(
   // Save array pointers to avoid looking them up for each tuple.
   std::vector<vtkDataArray*> scalarArrays(this->NumberOfScalarArrays);
   std::vector<vtkDataArray*> vectorArrays(this->NumberOfVectorArrays);
+  std::vector<int> scalarArrayIndicies(this->NumberOfScalarArrays);
+  std::vector<int> vectorArrayIndicies(this->NumberOfVectorArrays);
+
   for (int cc=0; cc < this->NumberOfScalarArrays; cc++)
   {
-    if (this->FunctionParser->GetScalarVariableNeeded(cc))
+    int idx = this->FunctionParser->GetScalarVariableIndex(
+      this->ScalarVariableNames[cc]);
+    if (idx >= 0)
     {
-      scalarArrays[cc] = inFD->GetArray(this->ScalarArrayNames[cc]);
+      if (this->FunctionParser->GetScalarVariableNeeded(idx))
+      {
+        scalarArrays[cc] = inFD->GetArray(this->ScalarArrayNames[cc]);
+        scalarArrayIndicies[cc] = idx;
+      }
     }
   }
+
   for (int cc=0; cc < this->NumberOfVectorArrays; cc++)
   {
-    if (this->FunctionParser->GetVectorVariableNeeded(cc))
+    int idx = this->FunctionParser->GetVectorVariableIndex(
+      this->VectorVariableNames[cc]);
+    if (idx >= 0)
     {
-      vectorArrays[cc] = inFD->GetArray(this->VectorArrayNames[cc]);
+      if (this->FunctionParser->GetVectorVariableNeeded(idx))
+      {
+        vectorArrays[cc] = inFD->GetArray(this->VectorArrayNames[cc]);
+        vectorArrayIndicies[cc] = idx;
+      }
     }
   }
 
@@ -449,16 +465,16 @@ int vtkArrayCalculator::RequestData(
       if ((currentArray = scalarArrays[j]))
       {
         this->FunctionParser->
-          SetScalarVariableValue(
-            j, currentArray->GetComponent(i, this->SelectedScalarComponents[j]));
+          SetScalarVariableValue(scalarArrayIndicies[j],
+            currentArray->GetComponent(i, this->SelectedScalarComponents[j]));
       }
     }
     for (j = 0; j < this->NumberOfVectorArrays; j++)
     {
       if ((currentArray = vectorArrays[j]))
       {
-        this->FunctionParser->SetVectorVariableValue(
-            j, currentArray->GetComponent(i, this->SelectedVectorComponents[j][0]),
+        this->FunctionParser->SetVectorVariableValue(vectorArrayIndicies[j],
+            currentArray->GetComponent(i, this->SelectedVectorComponents[j][0]),
             currentArray->GetComponent(
               i, this->SelectedVectorComponents[j][1]),
             currentArray->GetComponent(i, this->SelectedVectorComponents[j][2]));
diff --git a/Filters/Geometry/vtkStructuredGridGeometryFilter.cxx b/Filters/Geometry/vtkStructuredGridGeometryFilter.cxx
index 912ab742f1d5198e61827591a7ff8119a13edcda..1ae8624098875e8ad2f891a523daa9e260a8af70 100644
--- a/Filters/Geometry/vtkStructuredGridGeometryFilter.cxx
+++ b/Filters/Geometry/vtkStructuredGridGeometryFilter.cxx
@@ -351,20 +351,27 @@ int vtkStructuredGridGeometryFilter::RequestData(
         for (j=0; j < (diff[1]+1); j++)
         {
           pos = startIdx + j*offset[0] + k*offset[1];
+
+          // avoid accessing cells past the end of the grid
+          vtkIdType cellK = (k == dims[2] - 1) ? k - 1 : k;
+          vtkIdType cellJ = (j == dims[1] - 1) ? j - 1 : j;
+          cellPos = startCellIdx + (cellK*(dims[1] - 1) + cellJ)*(dims[0] - 1);
+
           for (i=0; i < (diff[0]+1); i++)
           {
             if ( input->IsPointVisible(pos+i) )
             {
+              vtkIdType cellI = (i == dims[0] - 1) ? i - 1 : i;
               input->GetPoint(pos+i, x);
               ptIds[0] = newPts->InsertNextPoint(x);
               outPD->CopyData(pd,pos+i,ptIds[0]);
               cellId = newVerts->InsertNextCell(1,ptIds);
-              outCD->CopyData(cd,pos+i,cellId);
+              outCD->CopyData(cd,cellPos + cellI, cellId);
             }
           }
         }
       }
-        break; /* end this case */
+      break; /* end this case */
 
   } // switch
 
diff --git a/IO/Export/vtkPDFContextDevice2D.cxx b/IO/Export/vtkPDFContextDevice2D.cxx
index dfa5658865c765ae3adf7ccd0a4ac992b8baa87e..07a0072d5a49a4ba9017552bf57910889fb4d46d 100644
--- a/IO/Export/vtkPDFContextDevice2D.cxx
+++ b/IO/Export/vtkPDFContextDevice2D.cxx
@@ -437,7 +437,9 @@ void vtkPDFContextDevice2D::DrawPointSprites(vtkImageData *spriteIn,
       coloredBuf.reserve(numPoints * 3);
       // Using int since we're iterating to j < 0 (and vtkIdType is unsigned).
       // It's very unlikely that numPoints will be larger than INT_MAX, but
-      // we'll check anyway:
+      // we'll check anyway. This throws a warning (taut-compare) when
+      // vtkIdType is a 32-bit integer, so we disable it in that case.
+#ifdef VTK_USE_64BIT_IDS
       if (numPoints > static_cast<vtkIdType>(VTK_INT_MAX))
       {
         vtkErrorMacro("FIXME: Image data too large for indexing with int.");
@@ -445,6 +447,7 @@ void vtkPDFContextDevice2D::DrawPointSprites(vtkImageData *spriteIn,
         rgb->UnRegister(this);
         return;
       }
+#endif // VTK_USE_64BIT_IDS
       for (int j = static_cast<int>(numPoints) - 1; j >= 0; --j)
       {
         unsigned char *pointColor = bufIn + 3 * j;
diff --git a/IO/Image/vtkJPEGReader.cxx b/IO/Image/vtkJPEGReader.cxx
index e5a01c799b71d09d7d9b0c6420d47b03c71b009f..0a9ff512fe9ae0f0cdd5da6e4dcfef2de48a850a 100644
--- a/IO/Image/vtkJPEGReader.cxx
+++ b/IO/Image/vtkJPEGReader.cxx
@@ -280,22 +280,35 @@ int vtkJPEGReaderUpdate2(vtkJPEGReader *self, OT *outPtr,
   // prepare to read the bulk data
   jpeg_start_decompress(&cinfo);
 
-
-  int rowbytes = cinfo.output_components * cinfo.output_width;
-  unsigned char *tempImage = new unsigned char [rowbytes*cinfo.output_height];
-  JSAMPROW *row_pointers = new JSAMPROW [cinfo.output_height];
-  for (unsigned int ui = 0; ui < cinfo.output_height; ++ui)
+  unsigned int maxChunk = cinfo.output_height;
+  if (maxChunk > 4096)
+  {
+    maxChunk = 4096;
+  }
+  vtkIdType rowbytes = cinfo.output_components * cinfo.output_width;
+  unsigned char *tempImage = new unsigned char [rowbytes*maxChunk];
+  JSAMPROW *row_pointers = new JSAMPROW [maxChunk];
+  for (unsigned int ui = 0; ui < maxChunk; ++ui)
   {
     row_pointers[ui] = tempImage + rowbytes*ui;
   }
 
   // read the bulk data
-  unsigned int remainingRows;
+  long outSize = cinfo.output_components*(outExt[1] - outExt[0] + 1);
   while (cinfo.output_scanline < cinfo.output_height)
   {
-    remainingRows = cinfo.output_height - cinfo.output_scanline;
-    jpeg_read_scanlines(&cinfo, &row_pointers[cinfo.output_scanline],
-                        remainingRows);
+    JDIMENSION linesRead = jpeg_read_scanlines(&cinfo, row_pointers, maxChunk);
+
+    // copy the data into the outPtr
+    OT *outPtr2 = outPtr + (cinfo.output_height - cinfo.output_scanline)*outInc[1];
+    for (unsigned int i = 0; i < linesRead; ++i)
+    {
+      memcpy(outPtr2,
+             row_pointers[linesRead - i - 1]
+             + outExt[0]*cinfo.output_components,
+             outSize);
+      outPtr2 += outInc[1];
+    }
   }
 
   // finish the decompression step
@@ -304,17 +317,6 @@ int vtkJPEGReaderUpdate2(vtkJPEGReader *self, OT *outPtr,
   // destroy the decompression object
   jpeg_destroy_decompress(&cinfo);
 
-  // copy the data into the outPtr
-  OT *outPtr2 = outPtr;
-  long outSize = cinfo.output_components*(outExt[1] - outExt[0] + 1);
-  for (int i = outExt[2]; i <= outExt[3]; ++i)
-  {
-    memcpy(outPtr2,
-           row_pointers[cinfo.output_height - i - 1]
-           + outExt[0]*cinfo.output_components,
-           outSize);
-    outPtr2 += outInc[1];
-  }
   delete [] tempImage;
   delete [] row_pointers;
 
diff --git a/IO/Legacy/vtkUnstructuredGridWriter.cxx b/IO/Legacy/vtkUnstructuredGridWriter.cxx
index 6d10feb61af9c76ade15693c5192626343f2fd3e..2ce2f0f962372cc68f51495c939eda760e4e5fbf 100644
--- a/IO/Legacy/vtkUnstructuredGridWriter.cxx
+++ b/IO/Legacy/vtkUnstructuredGridWriter.cxx
@@ -40,7 +40,8 @@ void vtkUnstructuredGridWriter::WriteData()
   ostream *fp;
   vtkUnstructuredGrid *input= vtkUnstructuredGrid::SafeDownCast(
     this->GetInput());
-  int *types, ncells, cellId;
+  int *types;
+  vtkIdType ncells, cellId;
 
   vtkDebugMacro(<<"Writing vtk unstructured grid data...");
 
@@ -159,7 +160,7 @@ int vtkUnstructuredGridWriter::WriteCellsAndFaces(
   // Create a copy of the cell data with the face streams expanded.
   // Do this before writing anything so that we know the size.
   // Use ints to represent vtkIdTypes, since that's what the superclass does.
-  std::vector<int> cells;
+  std::vector<vtkIdType> cells;
   cells.reserve(grid->GetNumberOfCells() * grid->GetMaxCellSize());
 
   vtkSmartPointer<vtkCellIterator> it =
@@ -195,14 +196,14 @@ int vtkUnstructuredGridWriter::WriteCellsAndFaces(
 
   if ( this->FileType == VTK_ASCII )
   { // Write each cell out to a separate line, must traverse:
-    std::vector<int>::const_iterator cellStart = cells.begin();
-    std::vector<int>::const_iterator cellEnd;
+    std::vector<vtkIdType>::const_iterator cellStart = cells.begin();
+    std::vector<vtkIdType>::const_iterator cellEnd;
     vtkIdType nCells = grid->GetNumberOfCells();
     while (nCells-- > 0)
     {
       cellEnd = cellStart + (*cellStart + 1);
       while (cellStart != cellEnd)
-        *fp << static_cast<int>(*cellStart++) << " ";
+        *fp << static_cast<vtkIdType>(*cellStart++) << " ";
       *fp << "\n";
     }
   }
diff --git a/Rendering/Core/vtkDataSetMapper.cxx b/Rendering/Core/vtkDataSetMapper.cxx
index ff0190e91b4587ae81f66b0fc577c95edc5462f0..0b9180dffee20ec1a3eece806382536576d09e91 100644
--- a/Rendering/Core/vtkDataSetMapper.cxx
+++ b/Rendering/Core/vtkDataSetMapper.cxx
@@ -138,6 +138,14 @@ void vtkDataSetMapper::Render(vtkRenderer *ren, vtkActor *act)
   this->PolyDataMapper->SetInterpolateScalarsBeforeMapping(
                                this->GetInterpolateScalarsBeforeMapping());
 
+  double f, u;
+  this->GetRelativeCoincidentTopologyPolygonOffsetParameters(f,u);
+  this->PolyDataMapper->SetRelativeCoincidentTopologyPolygonOffsetParameters(f,u);
+  this->GetRelativeCoincidentTopologyLineOffsetParameters(f,u);
+  this->PolyDataMapper->SetRelativeCoincidentTopologyLineOffsetParameters(f,u);
+  this->GetRelativeCoincidentTopologyPointOffsetParameter(u);
+  this->PolyDataMapper->SetRelativeCoincidentTopologyPointOffsetParameter(u);
+
   this->PolyDataMapper->SetScalarMode(this->GetScalarMode());
   if ( this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_FIELD_DATA ||
        this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA )
diff --git a/Rendering/OpenGL2/CMakeLists.txt b/Rendering/OpenGL2/CMakeLists.txt
index 5ce7441f02ddd1ed4ccf3d32c8afff40ee320c42..17b24c4194f938184bd22dfd9913b7a8ced36977 100644
--- a/Rendering/OpenGL2/CMakeLists.txt
+++ b/Rendering/OpenGL2/CMakeLists.txt
@@ -366,6 +366,11 @@ if (APPLE_IOS)
   vtk_module_link_libraries(${vtk-module} LINK_PUBLIC "-framework UIKit")
 endif()
 
+if (NOT ANDROID AND NOT APPLE_IOS)
+  VTK_ADD_EXECUTABLE(vtkProbeOpenGLVersion vtkProbeOpenGLVersion.cxx)
+  target_link_libraries(vtkProbeOpenGLVersion ${vtk-module})
+endif()
+
 if (WIN32 AND ( NOT CMAKE_CROSSCOMPILING OR DEFINED CMAKE_CROSSCOMPILING_EMULATOR) )
   VTK_ADD_EXECUTABLE(vtkTestOpenGLVersion vtkTestOpenGLVersion.cxx)
   set_target_properties(vtkTestOpenGLVersion
diff --git a/Rendering/OpenGL2/vtkOpenGLTexture.cxx b/Rendering/OpenGL2/vtkOpenGLTexture.cxx
index 1e553b72689059936f36c27a56cd7f50853d290c..b3ad30ebc6dd3a0d80486c57ecc4f110bd39d1f4 100644
--- a/Rendering/OpenGL2/vtkOpenGLTexture.cxx
+++ b/Rendering/OpenGL2/vtkOpenGLTexture.cxx
@@ -440,7 +440,7 @@ unsigned char *vtkOpenGLTexture::ResampleToPowerOfTwo(int &xs,
                                                       int bpp)
 {
   unsigned char *tptr, *p, *p1, *p2, *p3, *p4;
-  int jOffset, iIdx, jIdx;
+  vtkIdType jOffset, iIdx, jIdx;
   double pcoords[3], rm, sm, w0, w1, w2, w3;
   int yInIncr = xs;
   int xInIncr = 1;
diff --git a/Rendering/OpenGL2/vtkOpenGLVertexBufferObject.cxx b/Rendering/OpenGL2/vtkOpenGLVertexBufferObject.cxx
index 707e70a474f892bb103e09fea3ceb779bbb735e2..4de6d0dc26ef799119fe68095d33651f1f58937f 100644
--- a/Rendering/OpenGL2/vtkOpenGLVertexBufferObject.cxx
+++ b/Rendering/OpenGL2/vtkOpenGLVertexBufferObject.cxx
@@ -248,16 +248,16 @@ void vtkAppendVBOWorker<destType>::operator() (DataArray *array)
   }
 
   destType *VBOit =
-    reinterpret_cast<destType *>(&this->VBO->PackedVBO[this->Offset]);
+    reinterpret_cast<destType *>(&this->VBO->GetPackedVBO()[this->Offset]);
 
   // Accessor for the data array
   vtkDataArrayAccessor<DataArray> data(array);
 
   // compute extra padding required
   int bytesNeeded =
-    this->VBO->DataTypeSize*this->VBO->NumberOfComponents;
+    this->VBO->GetDataTypeSize() * this->VBO->GetNumberOfComponents();
   int extraComponents =
-    ((4 - (bytesNeeded % 4)) % 4)/this->VBO->DataTypeSize;
+    ((4 - (bytesNeeded % 4)) % 4) / this->VBO->GetDataTypeSize();
 
   // If not shift & scale
   if(!this->VBO->GetCoordShiftAndScaleEnabled())
diff --git a/Rendering/OpenGL2/vtkProbeOpenGLVersion.cxx b/Rendering/OpenGL2/vtkProbeOpenGLVersion.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..2d5a4d9fb5d5a4555f76259dd0952c619a53f4b8
--- /dev/null
+++ b/Rendering/OpenGL2/vtkProbeOpenGLVersion.cxx
@@ -0,0 +1,55 @@
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+
+  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 "vtkAutoInit.h"
+VTK_MODULE_INIT(vtkRenderingOpenGL2);
+
+#include "vtkNew.h"
+#include "vtkRenderer.h"
+#include "vtkOpenGLRenderWindow.h"
+#include "vtkOutputWindow.h"
+
+#include <sstream>
+
+int main(int , char* /* argv */[])
+{
+  int result = 0;
+
+  vtkNew<vtkRenderer> renderer;
+  vtkNew<vtkRenderWindow> renderWindow;
+  renderWindow->AddRenderer(renderer);
+
+  std::ostringstream toString;
+
+  toString << "Class: " << renderWindow->GetClassName();
+
+  if (!renderWindow->SupportsOpenGL())
+  {
+    toString << " failed to find a working OpenGL\n\n";
+    toString << vtkOpenGLRenderWindow::SafeDownCast(renderWindow)->GetOpenGLSupportMessage();
+    result = 1;
+  }
+  else
+  {
+    toString << " succeeded in finding a working OpenGL\n\n";
+  }
+
+  renderWindow->Render();
+  toString << renderWindow->ReportCapabilities();
+
+  vtkOutputWindow::GetInstance()->PromptUserOn();
+  vtkOutputWindow::GetInstance()->DisplayText(toString.str().c_str());
+
+  return result;
+}
diff --git a/Rendering/OpenGL2/vtkTestOpenGLVersion.h b/Rendering/OpenGL2/vtkTestOpenGLVersion.h
new file mode 100644
index 0000000000000000000000000000000000000000..79e821b374c539165713d05b7c38846787b452da
--- /dev/null
+++ b/Rendering/OpenGL2/vtkTestOpenGLVersion.h
@@ -0,0 +1,61 @@
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+
+  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.
+
+=========================================================================*/
+/**
+ * This header file is designed to be included into your program
+ * to support delayed loading of opengl and if needed use of Mesa
+ * in cases where the users computer does not support OpenGL 3.2
+ * natively.
+ *
+ * To use this class you must
+ *
+ * 1) Build VTK with the advanced cmake option VTK_USE_OPENGL_DELAYED_LOAD
+ *    turned on.
+ *
+ * 2) Include this file in your application and call HandleOpenGL32Issues
+ *    before you do any rendering or anything that would cause opengl
+ *    to be used. Ideally do this right at the beginning of your program.
+ *
+ * 3) Make sure you include vtkTestOpenGLVersion.exe with your application
+ *    and pass the fullpath to it as the first argument to HandleOpenGL32Issues
+ *
+ * 4) Make sure you include the Mesa libraries with your application. Typically
+ *    this means opengl32.dll swrAVX.dll swrAVX2.dll and graw.dll. Pass the path
+ *    to these libraries as the second argument to HandleOpenGL32Issues
+ */
+
+#include <windows.h>
+
+// returns an int, zero indicates a problem though right now
+// all paths return 1.
+int HandleOpenGL32Issues(
+  const char *pathToTestOpenGLExecutable,
+  const char *mesaLibPath
+  )
+{
+  // run the test executable and collect the result
+  int result = system(pathToTestOpenGLExecutable);
+
+  // if the default works then just return
+  if (result == 0)
+  {
+    return 1;
+  }
+
+  // otherwise set the dll path so that mesa willbe loaded
+  SetDllDirectory(mesaLibPath);
+
+  return 1;
+}
+
+// VTK-HeaderTest-Exclude: vtkTestOpenGLVersion.h
diff --git a/Rendering/OpenGL2/vtkXOpenGLRenderWindow.cxx b/Rendering/OpenGL2/vtkXOpenGLRenderWindow.cxx
index 67d7c658361269ecda9ae7821669548f4eef1b0a..5a9784a8678741fd1c45f8075cbea6d1088201ba 100644
--- a/Rendering/OpenGL2/vtkXOpenGLRenderWindow.cxx
+++ b/Rendering/OpenGL2/vtkXOpenGLRenderWindow.cxx
@@ -1151,7 +1151,7 @@ void vtkXOpenGLRenderWindow::PopContext()
   GLXContext current = glXGetCurrentContext();
   GLXContext target = static_cast<GLXContext>(this->ContextStack.top());
   this->ContextStack.pop();
-  if (target != current)
+  if (target && target != current)
   {
     glXMakeCurrent(this->DisplayStack.top(),
       this->DrawableStack.top(),