diff --git a/Qt/Components/Resources/UI/pqDisplayProxyEditor.ui b/Qt/Components/Resources/UI/pqDisplayProxyEditor.ui
index 1d0bf2c..2f7c5c7 100644
--- a/Qt/Components/Resources/UI/pqDisplayProxyEditor.ui
+++ b/Qt/Components/Resources/UI/pqDisplayProxyEditor.ui
@@ -581,13 +581,43 @@
        </spacer>
       </item>
       <item row="7" column="0">
-       <widget class="QLabel" name="label_19">
+       <widget class="QLabel" name="label_17">
         <property name="text">
+         <string>Subdivision</string>
+        </property>
+       </widget>
+      </item>
+      <item row="7" column="1">
+       <widget class="QSpinBox" name="NonlinearSubdivisionLevel">
+        <property name="toolTip">
+         <string>Nonlinear faces are approximated with flat polygons.  This parameter controls how many times to subdivide nonlinear surface cells.  Higher subdivisions generate closer approximations but take more memory and rendering time.  Subdivision is recursive, so the number of output polygons can grow exponentially with this parameter.</string>
+        </property>
+        <property name="maximum">
+         <number>4</number>
+        </property>
+       </widget>
+      </item>
+      <item row="7" column="2">
+       <spacer name="horizontalSpacer">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>40</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item row="8" column="0" >
+       <widget class="QLabel" name="label_19" >
+        <property name="text" >
          <string>Volume mapper</string>
         </property>
        </widget>
       </item>
-      <item row="7" column="1" colspan="2">
+      <item row="8" column="1" colspan="2">
        <widget class="QComboBox" name="SelectedMapperIndex">
         <property name="toolTip">
          <string>&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;/head&gt;&lt;body style=&quot; white-space: pre-wrap; font-family:Sans Serif; font-size:9pt; font-weight:400; font-style:normal; text-decoration:none;&quot;&gt;&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Choose the mapper to use for volume rendering.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
@@ -1123,6 +1153,7 @@
   <tabstop>StylePointSize</tabstop>
   <tabstop>StyleLineWidth</tabstop>
   <tabstop>Opacity</tabstop>
+  <tabstop>NonlinearSubdivisionLevel</tabstop>
   <tabstop>SelectedMapperIndex</tabstop>
   <tabstop>EdgeColor</tabstop>
   <tabstop>SpecularIntensity</tabstop>
diff --git a/Qt/Components/pqDisplayProxyEditor.cxx b/Qt/Components/pqDisplayProxyEditor.cxx
index 64cfa25..bc3f83b 100644
--- a/Qt/Components/pqDisplayProxyEditor.cxx
+++ b/Qt/Components/pqDisplayProxyEditor.cxx
@@ -390,6 +390,15 @@ void pqDisplayProxyEditor::setRepresentation(pqPipelineRepresentation* repr)
     "value", SIGNAL(editingFinished()),
     reprProxy, reprProxy->GetProperty("Opacity"));
 
+  // setup of nonlinear subdivision
+  if (reprProxy->GetProperty("NonlinearSubdivisionLevel"))
+    {
+    this->Internal->Links->addPropertyLink(
+                this->Internal->NonlinearSubdivisionLevel,
+                "value", SIGNAL(valueChanged(int)),
+                reprProxy, reprProxy->GetProperty("NonlinearSubdivisionLevel"));
+    }
+
   // setup for map scalars
   this->Internal->Links->addPropertyLink(
     this->Internal->ColorMapScalars, "checked", SIGNAL(stateChanged(int)),
diff --git a/Servers/Filters/CMakeLists.txt b/Servers/Filters/CMakeLists.txt
index 13cd94f..2adaebd 100644
--- a/Servers/Filters/CMakeLists.txt
+++ b/Servers/Filters/CMakeLists.txt
@@ -129,6 +129,7 @@ SET(Filters_SRCS
   vtkPVMain.cxx
   vtkPVMergeTables.cxx
   vtkPVNullSource.cxx
+  vtkPVRecoverGeometryWireframe.cxx
   vtkPVRenderViewProxy.cxx
   vtkPVScalarBarActor.cxx
   vtkPVSelectionSource.cxx
diff --git a/Servers/Filters/vtkPVGeometryFilter.cxx b/Servers/Filters/vtkPVGeometryFilter.cxx
index 13a956f..47d7333 100644
--- a/Servers/Filters/vtkPVGeometryFilter.cxx
+++ b/Servers/Filters/vtkPVGeometryFilter.cxx
@@ -14,10 +14,12 @@
 =========================================================================*/
 #include "vtkPVGeometryFilter.h"
 
+#include "vtkAlgorithmOutput.h"
 #include "vtkAppendPolyData.h"
 #include "vtkCallbackCommand.h"
 #include "vtkCellArray.h"
 #include "vtkCellData.h"
+#include "vtkCellTypes.h"
 #include "vtkCleanArrays.h"
 #include "vtkCommand.h"
 #include "vtkCompositeDataIterator.h"
@@ -42,6 +44,7 @@
 #include "vtkPointData.h"
 #include "vtkPolyData.h"
 #include "vtkPolygon.h"
+#include "vtkPVRecoverGeometryWireframe.h"
 #include "vtkRectilinearGrid.h"
 #include "vtkRectilinearGridOutlineFilter.h"
 #include "vtkSmartPointer.h"
@@ -52,14 +55,17 @@
 #include "vtkTimerLog.h"
 #include "vtkUnsignedCharArray.h"
 #include "vtkUnsignedIntArray.h"
-#include "vtkAlgorithmOutput.h"
 #include "vtkUnstructuredGrid.h"
+#include "vtkUnstructuredGridGeometryFilter.h"
 
 #include <vtkstd/map>
 #include <vtkstd/vector>
 #include <vtkstd/string>
 #include <assert.h>
 
+#define VTK_CREATE(type, name) \
+  vtkSmartPointer<type> name = vtkSmartPointer<type>::New()
+
 vtkCxxRevisionMacro(vtkPVGeometryFilter, "1.105");
 vtkStandardNewMacro(vtkPVGeometryFilter);
 
@@ -131,10 +137,13 @@ vtkPVGeometryFilter::vtkPVGeometryFilter ()
   this->UseOutline = 1;
   this->UseStrips = 0;
   this->GenerateCellNormals = 1;
+  this->NonlinearSubdivisionLevel = 1;
 
   this->DataSetSurfaceFilter = vtkDataSetSurfaceFilter::New();
   this->GenericGeometryFilter=vtkGenericGeometryFilter::New();
-  
+  this->UnstructuredGridGeometryFilter=vtkUnstructuredGridGeometryFilter::New();
+  this->RecoverWireframeFilter = vtkPVRecoverGeometryWireframe::New();
+
   // Setup a callback for the internal readers to report progress.
   this->InternalProgressObserver = vtkCallbackCommand::New();
   this->InternalProgressObserver->SetCallback(
@@ -162,13 +171,31 @@ vtkPVGeometryFilter::vtkPVGeometryFilter ()
 //----------------------------------------------------------------------------
 vtkPVGeometryFilter::~vtkPVGeometryFilter ()
 {
-  if(this->DataSetSurfaceFilter)
+  // Be careful how you delete these so that you don't foul up the garbage
+  // collector.
+  if (this->DataSetSurfaceFilter)
     {
-    this->DataSetSurfaceFilter->Delete();
+    vtkDataSetSurfaceFilter *tmp = this->DataSetSurfaceFilter;
+    this->DataSetSurfaceFilter = NULL;
+    tmp->Delete();
     }
-  if(this->GenericGeometryFilter!=0)
+  if (this->GenericGeometryFilter)
     {
-    this->GenericGeometryFilter->Delete();
+    vtkGenericGeometryFilter *tmp = this->GenericGeometryFilter;
+    this->GenericGeometryFilter = NULL;
+    tmp->Delete();
+    }
+  if (this->UnstructuredGridGeometryFilter)
+    {
+    vtkUnstructuredGridGeometryFilter *tmp=this->UnstructuredGridGeometryFilter;
+    this->UnstructuredGridGeometryFilter = NULL;
+    tmp->Delete();
+    }
+  if (this->RecoverWireframeFilter)
+    {
+    vtkPVRecoverGeometryWireframe *tmp = this->RecoverWireframeFilter;
+    this->RecoverWireframeFilter = NULL;
+    tmp->Delete();
     }
   this->OutlineSource->Delete();
   this->InternalProgressObserver->Delete();
@@ -1067,10 +1094,160 @@ void vtkPVGeometryFilter::UnstructuredGridExecute(
   if (!this->UseOutline)
     {
     this->OutlineFlag = 0;
+
+    bool handleSubdivision = false;
+    if (this->NonlinearSubdivisionLevel > 0)
+      {
+      // Check to see if the data actually has nonlinear cells.  Handling
+      // nonlinear cells adds unnecessary work if we only have linear cells.
+      vtkUnsignedCharArray *types = input->GetCellTypesArray();
+      vtkIdType numCells = input->GetNumberOfCells();
+      for (vtkIdType i = 0; i < numCells; i++)
+        {
+        if (!vtkCellTypes::IsLinear(types->GetValue(i)))
+          {
+          handleSubdivision = true;
+          break;
+          }
+        }
+      }
+
+    vtkSmartPointer<vtkIdTypeArray> facePtIds2OriginalPtIds;
+
+    if (handleSubdivision)
+      {
+      // Use the vtkUnstructuredGridGeometryFilter to extract 2D surface cells
+      // from the geometry.  This is important to extract an appropriate
+      // wireframe in vtkPVRecoverGeometryWireframe.  Also, at the time of this
+      // writing vtkDataSetSurfaceFilter only properly subdivides 2D cells past
+      // level 1.
+      VTK_CREATE(vtkUnstructuredGrid, inputClone);
+      inputClone->ShallowCopy(input);
+      this->UnstructuredGridGeometryFilter->SetInput(inputClone);
+
+      // Let the vtkUnstructuredGridGeometryFilter record from which point and
+      // cell each face comes from in the standard vtkOriginalCellIds array.
+      this->UnstructuredGridGeometryFilter->SetPassThroughCellIds(
+                                                      this->PassThroughCellIds);
+      this->UnstructuredGridGeometryFilter->SetPassThroughPointIds(
+                                                     this->PassThroughPointIds);
+
+      // Observe the progress of the internal filter.
+      // TODO: Make the consecutive internal filter execution have monotonically
+      // increasing progress rather than restarting for every internal filter.
+      this->UnstructuredGridGeometryFilter->AddObserver(
+                                                vtkCommand::ProgressEvent,
+                                                this->InternalProgressObserver);
+      this->UnstructuredGridGeometryFilter->Update();
+      // The internal filter finished.  Remove the observer.
+      this->UnstructuredGridGeometryFilter->RemoveObserver(
+                                                this->InternalProgressObserver);
+
+      this->UnstructuredGridGeometryFilter->SetInput(NULL);
+
+      // Feed the extracted surface as the input to the rest of the processing.
+      input->ShallowCopy(this->UnstructuredGridGeometryFilter->GetOutput());
+
+      // Keep a handle to the vtkOriginalPointIds array.  We might need it.
+      facePtIds2OriginalPtIds = vtkIdTypeArray::SafeDownCast(
+                        input->GetPointData()->GetArray("vtkOriginalPointIds"));
+
+      // Flag the data set surface filter to record original cell ids, but do it
+      // in a specially named array that vtkPVRecoverGeometryWireframe will
+      // recognize.  Note that because the data set comes from
+      // UnstructuredGridGeometryFilter, the ids will represent the faces rather
+      // than the original cells, which is important.
+      this->DataSetSurfaceFilter->PassThroughCellIdsOn();
+      this->DataSetSurfaceFilter->SetOriginalCellIdsName(
+                            vtkPVRecoverGeometryWireframe::ORIGINAL_FACE_IDS());
+
+      if (this->PassThroughPointIds)
+        {
+        if (this->NonlinearSubdivisionLevel <= 1)
+          {
+          // Do not allow the vtkDataSetSurfaceFilter create an array of
+          // original cell ids; it will overwrite the correct array from the
+          // vtkUnstructuredGridGeometryFilter.
+          this->DataSetSurfaceFilter->PassThroughPointIdsOff();
+          }
+        else
+          {
+          // vtkDataSetSurfaceFilter is going to strip the vtkOriginalPointIds
+          // created by the vtkPVUnstructuredGridGeometryFilter because it
+          // cannot interpolate the ids.  Make the vtkDataSetSurfaceFilter make
+          // its own original ids array.  We will resolve them later.
+          this->DataSetSurfaceFilter->PassThroughPointIdsOn();
+          }
+        }
+      }
+
     if (input->GetNumberOfCells() > 0)
       {
       this->DataSetSurfaceFilter->UnstructuredGridExecute(input, output);
       }
+
+    if (handleSubdivision)
+      {
+      // Restore state of DataSetSurfaceFilter.
+      this->DataSetSurfaceFilter->SetPassThroughCellIds(
+                                                      this->PassThroughCellIds);
+      this->DataSetSurfaceFilter->SetOriginalCellIdsName(NULL);
+      this->DataSetSurfaceFilter->SetPassThroughPointIds(
+                                                     this->PassThroughPointIds);
+
+      // Now use vtkPVRecoverGeometryWireframe to create an edge flag attribute
+      // that will cause the wireframe to be rendered correctly.
+      VTK_CREATE(vtkPolyData, nextStageInput);
+      nextStageInput->ShallowCopy(output);  // Yes output is correct.
+      this->RecoverWireframeFilter->SetInput(nextStageInput);
+
+      // Observe the progress of the internal filter.
+      // TODO: Make the consecutive internal filter execution have monotonically
+      // increasing progress rather than restarting for every internal filter.
+      this->RecoverWireframeFilter->AddObserver(
+                                                vtkCommand::ProgressEvent,
+                                                this->InternalProgressObserver);
+      this->RecoverWireframeFilter->Update();
+      // The internal filter finished.  Remove the observer.
+      this->RecoverWireframeFilter->RemoveObserver(
+                                                this->InternalProgressObserver);
+
+      this->RecoverWireframeFilter->SetInput(NULL);
+
+      // Get what should be the final output.
+      output->ShallowCopy(this->RecoverWireframeFilter->GetOutput());
+
+      if (this->PassThroughPointIds && (this->NonlinearSubdivisionLevel > 1))
+        {
+        // The output currently has a vtkOriginalPointIds array that maps points
+        // to the data containing only the faces.  Correct this to point to the
+        // original data set.
+        vtkIdTypeArray *polyPtIds2FacePtIds = vtkIdTypeArray::SafeDownCast(
+                       output->GetPointData()->GetArray("vtkOriginalPointIds"));
+        if (!facePtIds2OriginalPtIds || !polyPtIds2FacePtIds)
+          {
+          vtkErrorMacro(<< "Missing original point id arrays.");
+          return;
+          }
+        vtkIdType numPts = polyPtIds2FacePtIds->GetNumberOfTuples();
+        VTK_CREATE(vtkIdTypeArray, polyPtIds2OriginalPtIds);
+        polyPtIds2OriginalPtIds->SetName("vtkOriginalPointIds");
+        polyPtIds2OriginalPtIds->SetNumberOfComponents(1);
+        polyPtIds2OriginalPtIds->SetNumberOfTuples(numPts);
+        for (vtkIdType polyPtId = 0; polyPtId < numPts; polyPtId++)
+          {
+          vtkIdType facePtId = polyPtIds2FacePtIds->GetValue(polyPtId);
+          vtkIdType originalPtId = -1;
+          if (facePtId >= 0)
+            {
+            originalPtId = facePtIds2OriginalPtIds->GetValue(facePtId);
+            }
+          polyPtIds2OriginalPtIds->SetValue(polyPtId, originalPtId);
+          }
+        output->GetPointData()->AddArray(polyPtIds2OriginalPtIds);
+        }
+      }
+
     return;
     }
   
@@ -1193,6 +1370,10 @@ void vtkPVGeometryFilter::ReportReferences(vtkGarbageCollector* collector)
                             "DataSetSurfaceFilter");
   vtkGarbageCollectorReport(collector, this->GenericGeometryFilter,
                             "GenericGeometryFilter");
+  vtkGarbageCollectorReport(collector, this->UnstructuredGridGeometryFilter,
+                            "UnstructuredGridGeometryFilter");
+  vtkGarbageCollectorReport(collector, this->RecoverWireframeFilter,
+                            "RecoverWireframeFilter");
 }
 
 //----------------------------------------------------------------------------
@@ -1213,6 +1394,8 @@ void vtkPVGeometryFilter::PrintSelf(ostream& os, vtkIndent indent)
   os << indent << "UseStrips: " << (this->UseStrips?"on":"off") << endl;
   os << indent << "GenerateCellNormals: " 
      << (this->GenerateCellNormals?"on":"off") << endl;
+  os << indent << "NonlinearSubdivisionLevel: "
+     << this->NonlinearSubdivisionLevel << endl;
   os << indent << "Controller: " << this->Controller << endl;
 
   os << indent << "PassThroughCellIds: " 
@@ -1306,3 +1489,20 @@ void vtkPVGeometryFilter::RemoveGhostCells(vtkPolyData* output)
     output->RemoveGhostCells(1);
     }
 }
+
+//-----------------------------------------------------------------------------
+void vtkPVGeometryFilter::SetNonlinearSubdivisionLevel(int newvalue)
+{
+  if (this->NonlinearSubdivisionLevel != newvalue)
+    {
+    this->NonlinearSubdivisionLevel = newvalue;
+
+    if (this->DataSetSurfaceFilter)
+      {
+      this->DataSetSurfaceFilter->SetNonlinearSubdivisionLevel(
+                                               this->NonlinearSubdivisionLevel);
+      }
+
+    this->Modified();
+    }
+}
diff --git a/Servers/Filters/vtkPVGeometryFilter.h b/Servers/Filters/vtkPVGeometryFilter.h
index f9e4485..9fb7be2 100644
--- a/Servers/Filters/vtkPVGeometryFilter.h
+++ b/Servers/Filters/vtkPVGeometryFilter.h
@@ -34,9 +34,11 @@ class vtkInformationVector;
 class vtkCompositeDataSet;
 class vtkMultiProcessController;
 class vtkOutlineSource;
+class vtkPVRecoverGeometryWireframe;
 class vtkRectilinearGrid;
 class vtkStructuredGrid;
 class vtkUnstructuredGrid;
+class vtkUnstructuredGridGeometryFilter;
 
 class VTK_EXPORT vtkPVGeometryFilter : public vtkPolyDataAlgorithm
 {
@@ -79,6 +81,15 @@ public:
   vtkBooleanMacro(GenerateCellNormals, int);
 
   // Description:
+  // Nonlinear faces are approximated with flat polygons.  This parameter
+  // controls how many times to subdivide nonlinear surface cells.  Higher
+  // subdivisions generate closer approximations but take more memory and
+  // rendering time.  Subdivision is recursive, so the number of output polygons
+  // can grow exponentially with this parameter.
+  virtual void SetNonlinearSubdivisionLevel(int);
+  vtkGetMacro(NonlinearSubdivisionLevel, int);
+
+  // Description:
   // Set and get the controller.
   virtual void SetController(vtkMultiProcessController*);
   vtkGetObjectMacro(Controller, vtkMultiProcessController);
@@ -159,11 +170,14 @@ protected:
   int UseOutline;
   int UseStrips;
   int GenerateCellNormals;
+  int NonlinearSubdivisionLevel;
 
   vtkMultiProcessController* Controller;
   vtkOutlineSource *OutlineSource;
   vtkDataSetSurfaceFilter* DataSetSurfaceFilter;
   vtkGenericGeometryFilter *GenericGeometryFilter;
+  vtkUnstructuredGridGeometryFilter *UnstructuredGridGeometryFilter;
+  vtkPVRecoverGeometryWireframe *RecoverWireframeFilter;
   
   int CheckAttributes(vtkDataObject* input);
 
diff --git a/Servers/Filters/vtkPVRecoverGeometryWireframe.cxx b/Servers/Filters/vtkPVRecoverGeometryWireframe.cxx
new file mode 100644
index 0000000..acc35f3
--- /dev/null
+++ b/Servers/Filters/vtkPVRecoverGeometryWireframe.cxx
@@ -0,0 +1,308 @@
+// -*- c++ -*-
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    $RCSfile: pqBlotDialog.h,v $
+
+  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.
+
+=========================================================================*/
+/*-------------------------------------------------------------------------
+  Copyright 2009 Sandia Corporation.
+  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+  the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------*/
+
+#include "vtkPVRecoverGeometryWireframe.h"
+
+#include "vtkCellArray.h"
+#include "vtkCellData.h"
+#include "vtkIdTypeArray.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "vtkPolyData.h"
+#include "vtkUnsignedCharArray.h"
+
+#include "vtkSmartPointer.h"
+#define VTK_CREATE(type, name) \
+  vtkSmartPointer<type> name = vtkSmartPointer<type>::New()
+
+#include <vtkstd/algorithm>
+#include <vtkstd/vector>
+#include <vtksys/hash_map.hxx>
+
+static const unsigned char NO_EDGE_FLAG = static_cast<unsigned char >(-1);
+
+//=============================================================================
+namespace vtkPVRecoverGeometryWireframeNamespace
+{
+  // Description:
+  // Simple class used internally to define an edge based on the endpoints.  The
+  // endpoints are canonically identified by the lower and higher values.
+  class EdgeEndpoints
+  {
+  public:
+    EdgeEndpoints() : MinEndPoint(-1), MaxEndPoint(-1) {}
+    EdgeEndpoints(vtkIdType endpointA, vtkIdType endpointB)
+      : MinEndPoint((endpointA < endpointB) ? endpointA : endpointB),
+        MaxEndPoint((endpointA < endpointB) ? endpointB : endpointA)
+    {}
+    const vtkIdType MinEndPoint;
+    const vtkIdType MaxEndPoint;
+    inline bool operator==(const EdgeEndpoints &other) const {
+      return (   (this->MinEndPoint == other.MinEndPoint)
+              && (this->MaxEndPoint == other.MaxEndPoint) );
+    }
+  };
+  struct EdgeEndpointsHash {
+  public:
+    size_t operator()(const EdgeEndpoints &edge) const {
+      return static_cast<size_t>(edge.MinEndPoint + edge.MaxEndPoint);
+    }
+  };
+
+  // Description:
+  // Holds the information necessary for the facet this edge came from.
+  class EdgeInformation
+  {
+  public:
+    vtkIdType OriginalFaceId;
+    vtkIdType *StartPointIdP;
+  };
+
+  // Description:
+  // A map from edge endpoints to the information about that edge.
+  typedef vtksys::hash_map<EdgeEndpoints, EdgeInformation, EdgeEndpointsHash>
+    EdgeMapType;
+
+  void RecordEdgeFlag(vtkPolyData *output, const EdgeInformation &edgeInfo,
+                      vtkUnsignedCharArray *edgeFlagArray, unsigned char flag,
+                      vtkIdType *duplicatePointMap)
+  {
+    vtkIdType pt = edgeInfo.StartPointIdP[0];
+    if (edgeFlagArray->GetValue(pt) == flag)
+      {
+      // Edge flag already set correctly.  Nothing to do.
+      return;
+      }
+    if (edgeFlagArray->GetValue(pt) == NO_EDGE_FLAG)
+      {
+      // Nothing has set the edge flag yet.  Just set it and return.
+      edgeFlagArray->SetValue(pt, flag);
+      return;
+      }
+
+    // If we are here then some other cell has already put a flag on this
+    // point different than ours.  We have to adjust our cell topology to
+    // use a duplicate point.
+    if (duplicatePointMap[pt] == -1)
+      {
+      // No duplicate made.  We need to make one.
+      vtkPoints *points = output->GetPoints();
+      double coords[3];
+      points->GetPoint(pt, coords);
+      vtkIdType newPt = points->InsertNextPoint(coords);
+      duplicatePointMap[pt] = newPt;
+      // Copying attributes from yourself seems weird, but is valid.
+      vtkPointData *pd = output->GetPointData();
+      pd->CopyData(pd, pt, newPt);
+      edgeFlagArray->InsertValue(newPt, flag);
+      }
+    edgeInfo.StartPointIdP[0] = duplicatePointMap[pt];
+  }
+}
+using namespace vtkPVRecoverGeometryWireframeNamespace;
+
+//=============================================================================
+vtkCxxRevisionMacro(vtkPVRecoverGeometryWireframe, "$Revision$");
+vtkStandardNewMacro(vtkPVRecoverGeometryWireframe);
+
+//-----------------------------------------------------------------------------
+vtkPVRecoverGeometryWireframe::vtkPVRecoverGeometryWireframe()
+{
+}
+
+vtkPVRecoverGeometryWireframe::~vtkPVRecoverGeometryWireframe()
+{
+}
+
+void vtkPVRecoverGeometryWireframe::PrintSelf(ostream &os, vtkIndent indent)
+{
+  this->Superclass::PrintSelf(os, indent);
+}
+
+//-----------------------------------------------------------------------------
+int vtkPVRecoverGeometryWireframe::RequestData(
+                                            vtkInformation *vtkNotUsed(request),
+                                            vtkInformationVector **inputVector,
+                                            vtkInformationVector *outputVector)
+{
+  vtkPolyData *input = vtkPolyData::GetData(inputVector[0]);
+  vtkPolyData *output = vtkPolyData::GetData(outputVector);
+
+  vtkIdType npts, *pts;
+  vtkstd::vector<vtkIdType> originalPts;
+
+  if (!input->GetCellData()->HasArray(ORIGINAL_FACE_IDS()))
+    {
+    // Did not find the field used to identify the face each linear patch comes
+    // from.  The original data was probably linear so using all the edges
+    // should be OK (and is at least the best we can do), so just pass the data.
+    output->ShallowCopy(input);
+    return 1;
+    }
+
+  vtkIdTypeArray *faceIds = vtkIdTypeArray::SafeDownCast(
+                   input->GetCellData()->GetAbstractArray(ORIGINAL_FACE_IDS()));
+  if (!faceIds)
+    {
+    vtkErrorMacro(<< ORIGINAL_FACE_IDS() << " array is not of expected type.");
+    return 0;
+    }
+
+  // Shallow copy the cell data.  All the cells get copied to output.
+  output->GetCellData()->PassData(input->GetCellData());
+
+  // Deep copy the point information and be ready to add points.
+  VTK_CREATE(vtkPoints, points);
+  points->DeepCopy(input->GetPoints());
+  output->SetPoints(points);
+  vtkPointData *inputPD = input->GetPointData();
+  vtkPointData *outputPD = output->GetPointData();
+  outputPD->CopyAllocate(inputPD);
+  vtkIdType numOriginalPoints = points->GetNumberOfPoints();
+  for (vtkIdType i = 0; i < numOriginalPoints; i++)
+    {
+    outputPD->CopyData(inputPD, i, i);
+    }
+
+  // Create an edge flag array.
+  VTK_CREATE(vtkUnsignedCharArray, edgeflags);
+  edgeflags->SetName("vtkEdgeFlags");
+  outputPD->AddArray(edgeflags);
+  outputPD->SetActiveAttribute("vtkEdgeFlags", vtkDataSetAttributes::EDGEFLAG);
+  edgeflags->SetNumberOfComponents(1);
+  edgeflags->SetNumberOfTuples(numOriginalPoints);
+  vtkstd::fill(edgeflags->GetPointer(0),
+               edgeflags->GetPointer(numOriginalPoints), NO_EDGE_FLAG);
+
+  // Some (probably many) points will have to be duplicated because different
+  // cells will need different edge flags.  This array maps the original
+  // point id to the duplicate id.
+  vtkstd::vector<vtkIdType> duplicatePointMap(numOriginalPoints);
+  vtkstd::fill(duplicatePointMap.begin(), duplicatePointMap.end(), -1);
+
+  // Shallow copy the verts.  Set the edge flags to true.
+  vtkCellArray *inputVerts = input->GetVerts();
+  output->SetVerts(inputVerts);
+  for (inputVerts->InitTraversal(); inputVerts->GetNextCell(npts, pts); )
+    {
+    for (vtkIdType i = 0; i < npts; i++)
+      {
+      edgeflags->SetValue(pts[i], 1);
+      }
+    }
+
+  // Shallow copy the lines. Set the edge flags to true.
+  vtkCellArray *inputLines = input->GetLines();
+  output->SetLines(inputLines);
+  for (inputLines->InitTraversal(); inputLines->GetNextCell(npts, pts); )
+    {
+    // No need to set edge flag for last index.
+    for (vtkIdType i = 0; i < npts-1; i++)
+      {
+      edgeflags->SetValue(pts[i], 1);
+      }
+    }
+
+  // Shallow copy the triangle strips.  Set the edge flags to true.
+  vtkCellArray *inputStrips = input->GetStrips();
+  output->SetStrips(inputStrips);
+  for (inputStrips->InitTraversal(); inputStrips->GetNextCell(npts, pts); )
+    {
+    for (vtkIdType i = 0; i < npts; i++)
+      {
+      edgeflags->SetValue(pts[i], 1);
+      }
+    }
+
+  // Deep copy the polygons because we will be changing some indices when we
+  // duplicate points.
+  VTK_CREATE(vtkCellArray, outputPolys);
+  outputPolys->DeepCopy(input->GetPolys());
+  output->SetPolys(outputPolys);
+
+  // Iterate over all the input facets and see which edge interfaces belonged to
+  // different faces.  We do that by recording the original face id in a map.
+  // When we find a pair of edges, we turn on the appropriate edge flag if they
+  // came from different faces, or turn it off if they came from the same face.
+  EdgeMapType edgeMap;
+  vtkIdType inputCellId
+    = inputVerts->GetNumberOfCells() + inputLines->GetNumberOfCells();
+  for (outputPolys->InitTraversal(); outputPolys->GetNextCell(npts, pts);
+       inputCellId++)
+    {
+    if ((inputCellId%1000) == 0)
+      {
+      this->UpdateProgress(static_cast<double>(inputCellId)
+                           /input->GetNumberOfCells());
+      if (this->GetAbortExecute()) return 0;
+      }
+    // Record the original points of the polygon.  As we iterate over edges,
+    // we may change the indices, but we allways compare edges by the original
+    // indices.
+    originalPts.resize(npts);
+    vtkstd::copy(pts, pts+npts, originalPts.begin());
+    vtkIdType originalFace = faceIds->GetValue(inputCellId);
+    for (vtkIdType i = 0; i < npts; i++)
+      {
+      EdgeEndpoints edge(originalPts[i], originalPts[(i+1)%npts]);
+      EdgeInformation edgeInfo;
+      edgeInfo.OriginalFaceId = originalFace;
+      edgeInfo.StartPointIdP = &pts[i];
+
+      EdgeMapType::iterator edgeMatch = edgeMap.find(edge);
+      if (edgeMatch == edgeMap.end())
+        {
+        // Not encountered yet.  Add to the map.
+        edgeMap.insert(vtkstd::make_pair(edge, edgeInfo));
+        }
+      else
+        {
+        // The edge flag is true if the edge connects two different faces.
+        unsigned char eflag = static_cast<unsigned char>(
+                              edgeMatch->second.OriginalFaceId != originalFace);
+        RecordEdgeFlag(output, edgeMatch->second, edgeflags, eflag,
+                       &duplicatePointMap.at(0));
+        RecordEdgeFlag(output, edgeInfo, edgeflags, eflag,
+                       &duplicatePointMap.at(0));
+        // Remove the edge from the map since we already found the pair.
+        edgeMap.erase(edgeMatch);
+        }
+      } // For each edge
+    } // For each cell.
+
+  // Everything left in the edge map has no match.  It must necessarily be
+  // on the outside of a face.
+  for (EdgeMapType::iterator iter = edgeMap.begin();
+       iter != edgeMap.end(); iter++)
+    {
+    RecordEdgeFlag(output, iter->second, edgeflags, 1,
+                   &duplicatePointMap.at(0));
+    }
+
+  // If any points are unmarked, set some edge flag on them (although they
+  // are probably not referenced by any cell).
+  for (vtkIdType i = 0; i < numOriginalPoints; i++)
+    {
+    if (edgeflags->GetValue(i) == NO_EDGE_FLAG) edgeflags->SetValue(i, 1);
+    }
+
+  return 1;
+}
diff --git a/Servers/Filters/vtkPVRecoverGeometryWireframe.h b/Servers/Filters/vtkPVRecoverGeometryWireframe.h
new file mode 100644
index 0000000..6d1d569
--- /dev/null
+++ b/Servers/Filters/vtkPVRecoverGeometryWireframe.h
@@ -0,0 +1,73 @@
+// -*- c++ -*-
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    $RCSfile: pqBlotDialog.h,v $
+
+  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.
+
+=========================================================================*/
+/*-------------------------------------------------------------------------
+  Copyright 2009 Sandia Corporation.
+  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+  the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------*/
+
+// .NAME vtkPVRecoverGeometryWireframe - Get corrected wireframe from tesselated facets
+//
+// .SECTION Description
+//
+// When vtkPVGeometryFilter tessellates nonlinear faces into linear
+// approximations, it introduces edges in the middle of the facets of the
+// original mesh (as any valid tessellation would).  To correct for this,
+// vtkPVGeometryFilter also writes out some fields that allows use to identify
+// the edges that are actually part of the original mesh.  This filter works in
+// conjunction with vtkPVGeometryFilter by taking its output, adding an edge
+// flag and making the appropriate adjustments so that rendering with line
+// fill mode will make the correct wireframe.
+//
+// .SECTION See Also
+// vtkPVGeometryFilter
+//
+
+#ifndef __vtkPVRecoverGeometryWireframe_h
+#define __vtkPVRecoverGeometryWireframe_h
+
+#include "vtkPolyDataAlgorithm.h"
+
+class VTK_EXPORT vtkPVRecoverGeometryWireframe : public vtkPolyDataAlgorithm
+{
+public:
+  vtkTypeRevisionMacro(vtkPVRecoverGeometryWireframe, vtkPolyDataAlgorithm);
+  static vtkPVRecoverGeometryWireframe *New();
+  virtual void PrintSelf(ostream &os, vtkIndent indent);
+
+  // Description:
+  // In order to determine which edges existed in the original data, we need an
+  // identifier on each cell determining which face (not cell) it originally
+  // came from.  The ids should be put in a cell data array with this name.  The
+  // existance of this field is also a signal that this wireframe extraction is
+  // necessary.
+  static const char *ORIGINAL_FACE_IDS()
+    { return "vtkPVRecoverWireframeOriginalFaceIds"; }
+
+protected:
+  vtkPVRecoverGeometryWireframe();
+  ~vtkPVRecoverGeometryWireframe();
+
+  virtual int RequestData(vtkInformation *request,
+                          vtkInformationVector **inputVector,
+                          vtkInformationVector *outputVector);
+
+private:
+  vtkPVRecoverGeometryWireframe(const vtkPVRecoverGeometryWireframe &); // Not implemented
+  void operator=(const vtkPVRecoverGeometryWireframe &); // Not implemented
+};
+
+#endif //__vtkPVRecoverGeometryWireframe_h
diff --git a/Servers/ServerManager/Resources/filters.xml b/Servers/ServerManager/Resources/filters.xml
index 70289ad..efd7835 100644
--- a/Servers/ServerManager/Resources/filters.xml
+++ b/Servers/ServerManager/Resources/filters.xml
@@ -1545,6 +1545,26 @@ The Extract Surface filter extracts the polygons forming the outer surface of th
          If the value of this property is set to 1, internal surfaces along process boundaries will be removed. NOTE: Enabling this option might cause multiple executions of the data source because more information is needed to remove internal surfaces.
        </Documentation>
      </IntVectorProperty>
+
+     <IntVectorProperty name="NonlinearSubdivisionLevel"
+                        command="SetNonlinearSubdivisionLevel"
+                        number_of_elements="1"
+                        default_values="1">
+       <IntRangeDomain name="range" min="0" max="4" />
+       <Documentation>
+         If the input is an unstructured grid with nonlinear faces, this
+         parameter determines how many times the face is subdivided into
+         linear faces.  If 0, the output is the equivalent of its linear
+         couterpart (and the midpoints determining the nonlinear
+         interpolation are discarded).  If 1, the nonlinear face is
+         triangulated based on the midpoints.  If greater than 1, the
+         triangulated pieces are recursively subdivided to reach the
+         desired subdivision.  Setting the value to greater than 1 may
+         cause some point data to not be passed even if no quadratic faces
+         exist.  This option has no effect if the input is not an
+         unstructured grid.
+       </Documentation>
+     </IntVectorProperty>
    <!-- End DataSetSurfaceFilter -->
    </SourceProxy>
 
@@ -7365,6 +7385,20 @@ Tessellate a higher-order dataset.
           Toggle whether to generate an outline or a surface.
         </Documentation>
       </IntVectorProperty>
+      <IntVectorProperty name="NonlinearSubdivisionLevel"
+                         command="SetNonlinearSubdivisionLevel"
+                         number_of_elements="1"
+                         default_values="1">
+        <IntRangeDomain name="range" min="0" max="4" />
+        <Documentation>
+          Nonlinear faces are approximated with flat polygons.  This
+          parameter controls how many times to subdivide nonlinear surface
+          cells.  Higher subdivisions generate closer approximations but
+          take more memory and rendering time.  Subdivision is recursive,
+          so the number of output polygons can grow exponentially with this
+          parameter.
+        </Documentation>
+      </IntVectorProperty>
       <IntVectorProperty
         name="PassThroughIds"
         command="SetPassThroughCellIds"
diff --git a/Servers/ServerManager/Resources/rendering.xml b/Servers/ServerManager/Resources/rendering.xml
index c5cf4eb..8d019f7 100644
--- a/Servers/ServerManager/Resources/rendering.xml
+++ b/Servers/ServerManager/Resources/rendering.xml
@@ -7118,7 +7118,7 @@
 
       <SubProxy>
         <!--
-          Geometry filter is used to conver non-polydata input to polydata.
+          Geometry filter is used to convert non-polydata input to polydata.
           It is also used to convert poly data to triangle strips when
           requested.
         -->
@@ -7127,6 +7127,7 @@
         <ExposedProperties>
           <Property name="UseStrips" />
           <Property name="ForceStrips" />
+          <Property name="NonlinearSubdivisionLevel" />
         </ExposedProperties>
       </SubProxy>
 
@@ -7992,6 +7993,7 @@
           <!-- Geometry Filter properties -->
           <Property name="UseStrips" />
           <Property name="ForceStrips" />
+          <Property name="NonlinearSubdivisionLevel" />
 
           <!-- Mapper properties -->
           <Property name="LookupTable" />
diff --git a/VTK b/VTK
index 8920140..18f5783 160000
--- a/VTK
+++ b/VTK
@@ -1 +1 @@
-Subproject commit 892014037f07ac668979c85b85112fc850515b94
+Subproject commit 18f57839105fff9ca30c172e14f730af4f7a39c2
