diff --git a/Filters/Parallel/CMakeLists.txt b/Filters/Parallel/CMakeLists.txt
index 8bace5f9887bc85e3861d835c839c246eddd81a7..e521ecf227860e82c3714e6b20b4ea52f41d6ea6 100644
--- a/Filters/Parallel/CMakeLists.txt
+++ b/Filters/Parallel/CMakeLists.txt
@@ -30,6 +30,7 @@ set(Module_SRCS
   vtkProcessIdScalars.cxx
   vtkRectilinearGridOutlineFilter.cxx
   vtkTransmitPolyDataPiece.cxx
+  vtkTransmitStructuredDataPiece.cxx
   vtkTransmitRectilinearGridPiece.cxx
   vtkTransmitStructuredGridPiece.cxx
   vtkTransmitUnstructuredGridPiece.cxx
diff --git a/Filters/Parallel/Testing/Cxx/TransmitImageData.cxx b/Filters/Parallel/Testing/Cxx/TransmitImageData.cxx
index 7e271c5f1fd72094fa39251c82263e63042d9f00..96dc31486abb80c32c7bab99ff6e3603678d51c7 100644
--- a/Filters/Parallel/Testing/Cxx/TransmitImageData.cxx
+++ b/Filters/Parallel/Testing/Cxx/TransmitImageData.cxx
@@ -107,6 +107,7 @@ void MyProcess::Execute()
     spr->SetFileName(fname);
 
     sp = spr->GetOutput();
+    sp->Register(0);
 
     spr->Update();
 
@@ -125,6 +126,7 @@ void MyProcess::Execute()
     }
   else
     {
+    sp = vtkStructuredPoints::New();
     }
 
   vtkMPICommunicator *comm =
@@ -138,6 +140,7 @@ void MyProcess::Execute()
       {
       spr->Delete();
       }
+    sp->Delete();
     prm->Delete();
     return;
     }
@@ -145,13 +148,7 @@ void MyProcess::Execute()
   // FILTER WE ARE TRYING TO TEST
   vtkTransmitImageDataPiece *pass = vtkTransmitImageDataPiece::New();
   pass->SetController(this->Controller);
-  if (me == 0)
-    {
-    pass->SetInputData(sp);
-    }
-  else
-    {
-    }
+  pass->SetInputData(sp);
 
   // FILTERING
   vtkContourFilter *cf = vtkContourFilter::New();
@@ -181,16 +178,6 @@ void MyProcess::Execute()
   prm->SetRenderWindow(renWin);
   prm->SetController(this->Controller);
   prm->InitializeOffScreen();   // Mesa GL only
-  if (me == 0)
-    {
-    prm->ResetAllCameras();
-    }
-
-  // We must update the whole pipeline here, otherwise node 0
-  // goes into GetActiveCamera which updates the pipeline, putting
-  // it into vtkDistributedDataFilter::Execute() which then hangs.
-  // If it executes here, dd will be up-to-date won't have to
-  // execute in GetActiveCamera.
 
   mapper->SetPiece(me);
   mapper->SetNumberOfPieces(numProcs);
@@ -204,6 +191,8 @@ void MyProcess::Execute()
     //camera->UpdateViewport(renderer);
     camera->SetParallelScale(16);
 
+    prm->ResetAllCameras();
+
     renWin->Render();
     renWin->Render();
 
@@ -234,6 +223,7 @@ void MyProcess::Execute()
     {
     spr->Delete();
     }
+  sp->Delete();
   prm->Delete();
 }
 
diff --git a/Filters/Parallel/Testing/Cxx/TransmitImageDataRenderPass.cxx b/Filters/Parallel/Testing/Cxx/TransmitImageDataRenderPass.cxx
index 2f0832ead2cc2e7b5b59170bdf8f6e62f0d827b1..188dfca6e7864e5a9801bb2f9fdb59f94f40ddb6 100644
--- a/Filters/Parallel/Testing/Cxx/TransmitImageDataRenderPass.cxx
+++ b/Filters/Parallel/Testing/Cxx/TransmitImageDataRenderPass.cxx
@@ -121,6 +121,10 @@ void MyProcess::Execute()
       go = 0;
       }
     }
+  else
+    {
+    sp = vtkSmartPointer<vtkStructuredPoints>::New();
+    }
 
   vtkMPICommunicator *comm =
     vtkMPICommunicator::SafeDownCast(this->Controller->GetCommunicator());
@@ -134,10 +138,7 @@ void MyProcess::Execute()
   vtkSmartPointer<vtkTransmitImageDataPiece> pass =
     vtkSmartPointer<vtkTransmitImageDataPiece>::New();
   pass->SetController(this->Controller);
-  if (me == 0)
-    {
-    pass->SetInputData(sp);
-    }
+  pass->SetInputData(sp);
 
   // FILTERING
   vtkSmartPointer<vtkContourFilter> cf =
@@ -204,7 +205,6 @@ void MyProcess::Execute()
   prm->InitializeOffScreen();   // Mesa GL only
   if (me == 0)
     {
-    prm->ResetAllCameras();
     }
 
   // We must update the whole pipeline here, otherwise node 0
@@ -213,19 +213,10 @@ void MyProcess::Execute()
   // If it executes here, dd will be up-to-date won't have to
   // execute in GetActiveCamera.
 
-  // mapper->SetPiece(me);
-  // mapper->SetNumberOfPieces(numProcs);
+  mapper->SetPiece(me);
+  mapper->SetNumberOfPieces(numProcs);
   mapper->Update();
 
-  if (me ==1)
-    {
-    vtkSmartPointer<vtkPolyDataWriter> writer =
-      vtkSmartPointer<vtkPolyDataWriter>::New();
-    writer->SetInputConnection(elev->GetOutputPort());
-    writer->SetFileName("contour1.vtk");
-    writer->Write();
-    }
-
   const int MY_RETURN_VALUE_MESSAGE=0x11;
 
   if (me == 0)
@@ -234,6 +225,8 @@ void MyProcess::Execute()
     //camera->UpdateViewport(renderer);
     camera->SetParallelScale(16);
 
+    prm->ResetAllCameras();
+
     renWin->Render();
     renWin->Render();
 
diff --git a/Filters/Parallel/Testing/Cxx/TransmitRectilinearGrid.cxx b/Filters/Parallel/Testing/Cxx/TransmitRectilinearGrid.cxx
index cad8f3f4481f1487b988acae669f36ceb605b27a..d2989f63056dbb2e64b3c76aaeb88b87e0245703 100644
--- a/Filters/Parallel/Testing/Cxx/TransmitRectilinearGrid.cxx
+++ b/Filters/Parallel/Testing/Cxx/TransmitRectilinearGrid.cxx
@@ -105,6 +105,7 @@ void MyProcess::Execute()
     rgr->SetFileName(fname);
 
     rg = rgr->GetOutput();
+    rg->Register(0);
 
     rgr->Update();
 
@@ -118,6 +119,10 @@ void MyProcess::Execute()
       go = 0;
       }
     }
+  else
+    {
+    rg = vtkRectilinearGrid::New();
+    }
 
   vtkMPICommunicator *comm =
     vtkMPICommunicator::SafeDownCast(this->Controller->GetCommunicator());
@@ -130,6 +135,7 @@ void MyProcess::Execute()
       {
       rgr->Delete();
       }
+    rg->Delete();
     prm->Delete();
     return;
     }
@@ -137,10 +143,7 @@ void MyProcess::Execute()
   // FILTER WE ARE TRYING TO TEST
   vtkTransmitRectilinearGridPiece *pass = vtkTransmitRectilinearGridPiece::New();
   pass->SetController(this->Controller);
-  if (me == 0)
-    {
-    pass->SetInputData(rg);
-    }
+  pass->SetInputData(rg);
 
   // FILTERING
   vtkContourFilter *cf = vtkContourFilter::New();
@@ -170,10 +173,6 @@ void MyProcess::Execute()
   prm->SetRenderWindow(renWin);
   prm->SetController(this->Controller);
   prm->InitializeOffScreen();   // Mesa GL only
-  if (me == 0)
-    {
-    prm->ResetAllCameras();
-    }
 
   // We must update the whole pipeline here, otherwise node 0
   // goes into GetActiveCamera which updates the pipeline, putting
@@ -193,6 +192,8 @@ void MyProcess::Execute()
     //camera->UpdateViewport(renderer);
     camera->SetParallelScale(16);
 
+    prm->ResetAllCameras();
+
     renWin->Render();
     renWin->Render();
 
@@ -223,6 +224,7 @@ void MyProcess::Execute()
     {
     rgr->Delete();
     }
+  rg->Delete();
   prm->Delete();
 }
 
diff --git a/Filters/Parallel/Testing/Cxx/TransmitStructuredGrid.cxx b/Filters/Parallel/Testing/Cxx/TransmitStructuredGrid.cxx
index 9203bc2dd0b27f2310955c3bd537f00c5174b393..46953e5e0442036189ffaaa9c2a421da449f4c92 100644
--- a/Filters/Parallel/Testing/Cxx/TransmitStructuredGrid.cxx
+++ b/Filters/Parallel/Testing/Cxx/TransmitStructuredGrid.cxx
@@ -104,6 +104,7 @@ void MyProcess::Execute()
     sgr->SetFileName(fname);
 
     sg = sgr->GetOutput();
+    sg->Register(0);
 
     sgr->Update();
 
@@ -117,6 +118,10 @@ void MyProcess::Execute()
       go = 0;
       }
     }
+  else
+    {
+    sg = vtkStructuredGrid::New();
+    }
 
   vtkMPICommunicator *comm =
     vtkMPICommunicator::SafeDownCast(this->Controller->GetCommunicator());
@@ -129,6 +134,7 @@ void MyProcess::Execute()
       {
       sgr->Delete();
       }
+    sg->Delete();
     prm->Delete();
     return;
     }
@@ -136,10 +142,7 @@ void MyProcess::Execute()
   // FILTER WE ARE TRYING TO TEST
   vtkTransmitStructuredGridPiece *pass = vtkTransmitStructuredGridPiece::New();
   pass->SetController(this->Controller);
-  if (me == 0)
-    {
-    pass->SetInputData(sg);
-    }
+  pass->SetInputData(sg);
 
   // FILTERING
   vtkContourFilter *cf = vtkContourFilter::New();
@@ -169,10 +172,6 @@ void MyProcess::Execute()
   prm->SetRenderWindow(renWin);
   prm->SetController(this->Controller);
   prm->InitializeOffScreen();   // Mesa GL only
-  if (me == 0)
-    {
-    prm->ResetAllCameras();
-    }
 
   // We must update the whole pipeline here, otherwise node 0
   // goes into GetActiveCamera which updates the pipeline, putting
@@ -192,6 +191,8 @@ void MyProcess::Execute()
     //camera->UpdateViewport(renderer);
     camera->SetParallelScale(16);
 
+    prm->ResetAllCameras();
+
     renWin->Render();
     renWin->Render();
 
@@ -222,6 +223,7 @@ void MyProcess::Execute()
     {
     sgr->Delete();
     }
+  sg->Delete();
   prm->Delete();
 }
 
diff --git a/Filters/Parallel/Testing/Python/CMakeLists.txt b/Filters/Parallel/Testing/Python/CMakeLists.txt
index a4a06ac5f49b5dff90c34b4552d503a8413aabb5..d80137532df3562be1db573db8c4671c1c41e7b3 100644
--- a/Filters/Parallel/Testing/Python/CMakeLists.txt
+++ b/Filters/Parallel/Testing/Python/CMakeLists.txt
@@ -1,7 +1,10 @@
-vtk_add_test_python(
-  RectOutline.py
-  TestCutMaterial.py
-  TestExtractCTHPart.py
-  TestExtrudePiece.py
-  TestImageStreamer.py
-  )
+vtk_add_test_python(RectOutline.py)
+vtk_add_test_python(TestCutMaterial.py)
+vtk_add_test_python(TestExtractCTHPart.py)
+vtk_add_test_python(TestExtrudePiece.py)
+vtk_add_test_python(TestImageStreamer.py)
+
+add_test(NAME ${vtk-module}Python-testTransmit
+  COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} 4 ${MPIEXEC_PREFLAGS}
+    $<TARGET_FILE:pvtkpython> ${CMAKE_CURRENT_SOURCE_DIR}/testTransmit.py
+    ${VTK_MPI_POSTFLAGS})
\ No newline at end of file
diff --git a/Filters/Parallel/Testing/Python/testTransmit.py b/Filters/Parallel/Testing/Python/testTransmit.py
new file mode 100644
index 0000000000000000000000000000000000000000..f453d4c20ac2b37055e2a814591c763b27faee4f
--- /dev/null
+++ b/Filters/Parallel/Testing/Python/testTransmit.py
@@ -0,0 +1,146 @@
+import vtk
+from vtk.test import Testing
+from vtk.util.misc import vtkGetTempDir
+VTK_TEMP_DIR = vtkGetTempDir()
+
+contr = vtk.vtkMultiProcessController.GetGlobalController()
+if not contr:
+    nranks = 1
+    rank = 0
+else:
+    nranks = contr.GetNumberOfProcesses()
+    rank = contr.GetLocalProcessId()
+
+def GetSource(dataType):
+    s = vtk.vtkRTAnalyticSource()
+    # Fake serial source
+    if rank == 0:
+        s.Update()
+
+    if dataType == 'ImageData':
+        return s.GetOutput()
+
+    elif dataType == 'UnstructuredGrid':
+        dst = vtk.vtkDataSetTriangleFilter()
+        dst.SetInputData(s.GetOutput())
+        dst.Update()
+        return dst.GetOutput()
+
+    elif dataType == 'RectilinearGrid':
+
+        input = s.GetOutput()
+
+        rg = vtk.vtkRectilinearGrid()
+        rg.SetExtent(input.GetExtent())
+        dims = input.GetDimensions()
+        spacing = input.GetSpacing()
+
+        x = vtk.vtkFloatArray()
+        x.SetNumberOfTuples(dims[0])
+        for i in range(dims[0]):
+            x.SetValue(i, spacing[0]*i)
+
+        y = vtk.vtkFloatArray()
+        y.SetNumberOfTuples(dims[1])
+        for i in range(dims[1]):
+            y.SetValue(i, spacing[1]*i)
+
+        z = vtk.vtkFloatArray()
+        z.SetNumberOfTuples(dims[2])
+        for i in range(dims[2]):
+            z.SetValue(i, spacing[2]*i)
+
+        rg.SetXCoordinates(x)
+        rg.SetYCoordinates(y)
+        rg.SetZCoordinates(z)
+
+        rg.GetPointData().ShallowCopy(input.GetPointData())
+
+        return rg
+
+    elif dataType == 'StructuredGrid':
+
+        input = s.GetOutput()
+
+        sg = vtk.vtkStructuredGrid()
+        sg.SetExtent(input.GetExtent())
+        pts = vtk.vtkPoints()
+        sg.SetPoints(pts)
+        npts = input.GetNumberOfPoints()
+        for i in xrange(npts):
+            pts.InsertNextPoint(input.GetPoint(i))
+        sg.GetPointData().ShallowCopy(input.GetPointData())
+
+        return sg
+
+def TestDataType(dataType, filter):
+    if rank == 0:
+        print dataType
+
+    s = GetSource(dataType)
+
+    da = vtk.vtkIntArray()
+    da.SetNumberOfTuples(6)
+    if rank == 0:
+        try:
+            ext = s.GetExtent()
+        except:
+            ext = (0, -1, 0, -1, 0, -1)
+        for i in range(6):
+            da.SetValue(i, ext[i])
+    contr.Broadcast(da, 0)
+
+    ext = []
+    for i in range(6):
+        ext.append(da.GetValue(i))
+    ext = tuple(ext)
+
+    tp = vtk.vtkTrivialProducer()
+    tp.SetOutput(s)
+    tp.SetWholeExtent(ext)
+
+    ncells = vtk.vtkIntArray()
+    ncells.SetNumberOfTuples(1)
+    if rank == 0:
+        ncells.SetValue(0, s.GetNumberOfCells())
+    contr.Broadcast(ncells, 0)
+
+    result = vtk.vtkIntArray()
+    result.SetNumberOfTuples(1)
+    result.SetValue(0, 1)
+
+    if rank > 0:
+        if s.GetNumberOfCells() != 0:
+            result.SetValue(0, 0)
+
+    filter.SetInputConnection(tp.GetOutputPort())
+    filter.UpdateInformation()
+    filter.SetUpdateExtent(rank, nranks, 0)
+    filter.Update()
+
+    if filter.GetOutput().GetNumberOfCells() != ncells.GetValue(0) / nranks:
+        result.SetValue(0, 0)
+
+    filter.UpdateInformation()
+    filter.SetUpdateExtent(rank, nranks, 1)
+    filter.Update()
+
+    gl = filter.GetOutput().GetCellData().GetArray("vtkGhostLevels")
+    if not gl:
+        result.SetValue(0, 0)
+    else:
+        rng = gl.GetRange()
+        if rng[1] != 1:
+            result.SetValue(0, 0)
+
+    resArray = vtk.vtkIntArray()
+    resArray.SetNumberOfTuples(1)
+    contr.AllReduce(result, resArray, vtk.vtkCommunicator.MIN_OP)
+
+    assert resArray.GetValue(0) == 1
+
+
+TestDataType('ImageData', vtk.vtkTransmitImageDataPiece())
+TestDataType('RectilinearGrid', vtk.vtkTransmitRectilinearGridPiece())
+TestDataType('StructuredGrid', vtk.vtkTransmitStructuredGridPiece())
+TestDataType('UnstructuredGrid', vtk.vtkTransmitUnstructuredGridPiece())
diff --git a/Filters/Parallel/vtkTransmitPolyDataPiece.cxx b/Filters/Parallel/vtkTransmitPolyDataPiece.cxx
index 523f6e6be8ef04d12f54f633961d6aa083333d0b..61adb525c8a68b3e3dc8e9fde41a970dd54e3e4c 100644
--- a/Filters/Parallel/vtkTransmitPolyDataPiece.cxx
+++ b/Filters/Parallel/vtkTransmitPolyDataPiece.cxx
@@ -45,45 +45,6 @@ vtkTransmitPolyDataPiece::~vtkTransmitPolyDataPiece()
   this->SetController(NULL);
 }
 
-//----------------------------------------------------------------------------
-int vtkTransmitPolyDataPiece::RequestUpdateExtent(
-  vtkInformation *vtkNotUsed(request),
-  vtkInformationVector **inputVector,
-  vtkInformationVector *vtkNotUsed(outputVector))
-{
-  // get the info object
-  vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
-
-  if (this->Controller == NULL)
-    {
-    inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(),
-                1);
-    inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), 0);
-    inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(),
-                0);
-    return 1;
-    }
-
-  if (this->Controller->GetLocalProcessId() == 0)
-    { // Request everything.
-    inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(),
-                1);
-    inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), 0);
-    inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(),
-                0);
-    }
-  else
-    { // Request nothing.
-    inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(),
-                0);
-    inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(),
-                0);
-    inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(),
-                0);
-    }
-  return 1;
-}
-
 //----------------------------------------------------------------------------
 int vtkTransmitPolyDataPiece::RequestData(
   vtkInformation *vtkNotUsed(request),
diff --git a/Filters/Parallel/vtkTransmitPolyDataPiece.h b/Filters/Parallel/vtkTransmitPolyDataPiece.h
index 3bc012c249c9cb04939132d0b40f5713814057a9..d0aa81da56221d983dbe382fb435c6fc844be74d 100644
--- a/Filters/Parallel/vtkTransmitPolyDataPiece.h
+++ b/Filters/Parallel/vtkTransmitPolyDataPiece.h
@@ -12,12 +12,13 @@
      PURPOSE.  See the above copyright notice for more information.
 
 =========================================================================*/
-// .NAME vtkTransmitPolyDataPiece - Return specified piece, including specified
-// number of ghost levels.
+// .NAME vtkTransmitRectilinearGridPiece - Redistributes data produced
+// by serial readers
+//
 // .SECTION Description
-// This filter updates the appropriate piece by requesting the piece from
-// process 0.  Process 0 always updates all of the data.  It is important that
-// Execute get called on all processes, otherwise the filter will deadlock.
+// This filter can be used to redistribute data from producers that can't
+// produce data in parallel. All data is produced on first process and
+// the distributed to others using the multiprocess controller.
 
 
 #ifndef __vtkTransmitPolyDataPiece_h
@@ -55,7 +56,6 @@ protected:
   int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *);
   void RootExecute(vtkPolyData *input, vtkPolyData *output, vtkInformation *outInfo);
   void SatelliteExecute(int procId, vtkPolyData *output, vtkInformation *outInfo);
-  int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *);
 
   int CreateGhostCells;
   vtkMultiProcessController *Controller;
diff --git a/Filters/Parallel/vtkTransmitRectilinearGridPiece.cxx b/Filters/Parallel/vtkTransmitRectilinearGridPiece.cxx
index cc15c12698cd696033a80f9f65b55b0e4bc41542..8feeff378f0ca3bf9416a8164aceea33c77eea7b 100644
--- a/Filters/Parallel/vtkTransmitRectilinearGridPiece.cxx
+++ b/Filters/Parallel/vtkTransmitRectilinearGridPiece.cxx
@@ -14,356 +14,22 @@
 =========================================================================*/
 #include "vtkTransmitRectilinearGridPiece.h"
 
-#include "vtkCellData.h"
-#include "vtkExtractRectilinearGrid.h"
-#include "vtkInformation.h"
-#include "vtkInformationVector.h"
-#include "vtkMultiProcessController.h"
 #include "vtkObjectFactory.h"
-#include "vtkPointData.h"
-#include "vtkStreamingDemandDrivenPipeline.h"
-#include "vtkRectilinearGrid.h"
-#include "vtkDoubleArray.h"
 
 vtkStandardNewMacro(vtkTransmitRectilinearGridPiece);
 
-vtkCxxSetObjectMacro(vtkTransmitRectilinearGridPiece,Controller,
-                     vtkMultiProcessController);
-
 //----------------------------------------------------------------------------
 vtkTransmitRectilinearGridPiece::vtkTransmitRectilinearGridPiece()
 {
-  this->Controller = NULL;
-  this->CreateGhostCells = 1;
-  this->SetNumberOfInputPorts(1);
-  this->SetController(vtkMultiProcessController::GetGlobalController());
-  if (this->Controller)
-    {
-    if (this->Controller->GetLocalProcessId() != 0)
-      {
-      this->SetNumberOfInputPorts(0);
-      }
-    }
 }
 
 //----------------------------------------------------------------------------
 vtkTransmitRectilinearGridPiece::~vtkTransmitRectilinearGridPiece()
 {
-  this->SetController(NULL);
-}
-
-//----------------------------------------------------------------------------
-int vtkTransmitRectilinearGridPiece::RequestInformation(
-  vtkInformation *vtkNotUsed(request),
-  vtkInformationVector **inputVector,
-  vtkInformationVector *outputVector)
-{
-  if (this->Controller == NULL)
-    {
-    return 1;
-    }
-  else
-    {
-    int wExtent[6] = {0,-1,0,-1,0,-1};
-
-    vtkInformation *outInfo = outputVector->GetInformationObject(0);
-
-    if (this->Controller->GetLocalProcessId() == 0)
-      {
-      //Root sends meta-information to the satellites.
-      vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
-      inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wExtent);
-
-      int numProcs = this->Controller->GetNumberOfProcesses();
-      for (int i = 1; i < numProcs; ++i)
-        {
-        this->Controller->Send(wExtent, 6, i, 22342);
-        }
-      }
-    else
-      {
-      //Satellites ask root for meta-info, because they do not read it themselves.
-      this->Controller->Receive(wExtent, 6, 0, 22342);
-
-      vtkRectilinearGrid *output = vtkRectilinearGrid::SafeDownCast(
-         outInfo->Get(vtkDataObject::DATA_OBJECT()));
-      output->SetExtent(wExtent);
-      }
-
-    outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),
-                 wExtent,
-                 6);
-    return 1;
-    }
-}
-
-//----------------------------------------------------------------------------
-int vtkTransmitRectilinearGridPiece::RequestUpdateExtent(
-  vtkInformation *vtkNotUsed(request),
-  vtkInformationVector **inputVector,
-  vtkInformationVector *vtkNotUsed(outputVector))
-{
-  // get the info object
-  if (this->Controller == NULL)
-    {
-    vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
-
-    inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),
-                inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()),
-                6);
-
-    inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(),
-                0);
-    return 1;
-    }
-
-  if (this->Controller->GetLocalProcessId() == 0)
-    { // Request everything.
-    vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
-    inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),
-                inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()),
-                6);
-
-    inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(),
-                0);
-    }
-  else
-    { // Request nothing, get it from root instead.
-    }
-
-  return 1;
-}
-
-
-//----------------------------------------------------------------------------
-int vtkTransmitRectilinearGridPiece::RequestData(
-  vtkInformation *vtkNotUsed(request),
-  vtkInformationVector **inputVector,
-  vtkInformationVector *outputVector)
-{
-  vtkInformation *outInfo = outputVector->GetInformationObject(0);
-  vtkRectilinearGrid *output = vtkRectilinearGrid::SafeDownCast(
-    outInfo->Get(vtkDataObject::DATA_OBJECT()));
-
-  int procId;
-
-  if (this->Controller == NULL)
-    {
-    vtkErrorMacro("Could not find Controller.");
-    return 1;
-    }
-
-  procId = this->Controller->GetLocalProcessId();
-  if (procId == 0)
-    {
-    vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
-    vtkRectilinearGrid *input = vtkRectilinearGrid::SafeDownCast(
-      inInfo->Get(vtkDataObject::DATA_OBJECT()));
-    this->RootExecute(input, output, outInfo);
-    }
-  else
-    {
-    this->SatelliteExecute(procId, output, outInfo);
-    }
-
-  // TODO (berk)
-  // Fix this
-  /*
-    int ghostLevel = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS());
-  if (ghostLevel > 0 && this->CreateGhostCells)
-    {
-    int updatePiece = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER());
-    int updateNumPieces = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES());
-    vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
-    int* wholeExt = inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT());
-
-    vtkExtentTranslator* et = vtkStreamingDemandDrivenPipeline::GetExtentTranslator(inInfo);
-    output->GenerateGhostLevelArray(updatePiece,
-                                    updateNumPieces,
-                                    ghostLevel,
-                                    wholeExt,
-                                    et);
-    }
-  */
-
-  return 1;
-}
-
-//----------------------------------------------------------------------------
-void vtkTransmitRectilinearGridPiece::RootExecute(vtkRectilinearGrid *input,
-                                                   vtkRectilinearGrid *output,
-                                                   vtkInformation *outInfo)
-{
-  vtkRectilinearGrid *tmp = vtkRectilinearGrid::New();
-  vtkExtractRectilinearGrid *extract = vtkExtractRectilinearGrid::New();
-  int ext[7];
-  int numProcs, i;
-
-  int outExtent[6];
-  outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), outExtent);
-
-  vtkStreamingDemandDrivenPipeline *extractExecutive =
-    vtkStreamingDemandDrivenPipeline::SafeDownCast(extract->GetExecutive());
-
-  // First, set up the pipeline and handle local request.
-  tmp->ShallowCopy(input);
-  extract->SetInputData(tmp);
-  extractExecutive->UpdateDataObject();
-
-  vtkInformation *extractOutInfo = extractExecutive->GetOutputInformation(0);
-
-  extractOutInfo->Set(
-    vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),
-    outInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()),
-    6);
-  extractOutInfo->Set(
-    vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(),
-    outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS()));
-  extractOutInfo->Set(
-    vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT_INITIALIZED(), 1);
-  extract->Update();
-
-  // Copy geometry without copying information.
-  output->CopyStructure(extract->GetOutput());
-  output->GetPointData()->PassData(extract->GetOutput()->GetPointData());
-  output->GetCellData()->PassData(extract->GetOutput()->GetCellData());
-  vtkFieldData*  inFd = extract->GetOutput()->GetFieldData();
-  vtkFieldData* outFd = output->GetFieldData();
-  if (inFd && outFd)
-    {
-    outFd->PassData(inFd);
-    }
-
-  // Now do each of the satellite requests.
-  numProcs = this->Controller->GetNumberOfProcesses();
-  for (i = 1; i < numProcs; ++i)
-    {
-    this->Controller->Receive(ext, 7, i, 22341);
-    extractOutInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),
-                        ext,
-                        6);
-    extractOutInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(),
-                        ext[6]);
-    extract->Modified();
-    extract->Update();
-    this->Controller->Send(extract->GetOutput(), i, 22342);
-    }
-
-  //clean up the structures we've used here
-  tmp->Delete();
-  extract->Delete();
-}
-
-//----------------------------------------------------------------------------
-void vtkTransmitRectilinearGridPiece::SatelliteExecute(
-  int, vtkRectilinearGrid *output, vtkInformation *outInfo)
-{
-  vtkRectilinearGrid *tmp = vtkRectilinearGrid::New();
-
-  //decide what we want to ask for and ask root for it
-  int uExtent[7];
-  outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), uExtent);
-  uExtent[6] = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS());
-  this->Controller->Send(uExtent, 7, 0, 22341);
-
-  int wExtent[6];
-  outInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wExtent);
-
-  //receive root's response
-  this->Controller->Receive(tmp, 0, 22342);
-
-  //recover structure
-  int ext[6];
-  tmp->GetExtent(ext);
-
-  output->SetExtent(wExtent);
-
-  //create coordinate array of whole size, but only fill in
-  //out piece with what root sent to us
-  vtkDataArray *ida = tmp->GetZCoordinates();
-  vtkDataArray *oda = ida->NewInstance();
-  oda->SetNumberOfComponents(ida->GetNumberOfComponents());
-  oda->SetNumberOfTuples(wExtent[5]-wExtent[4]+1);
-  for (int i = uExtent[4]; i <= uExtent[5]; i++)
-    {
-    oda->SetTuple(i, ida->GetTuple(i-uExtent[4]));
-    }
-  output->SetZCoordinates(oda);
-  oda->Delete();
-
-  ida = tmp->GetYCoordinates();
-  oda = ida->NewInstance();
-  oda->SetNumberOfComponents(ida->GetNumberOfComponents());
-  oda->SetNumberOfTuples(wExtent[3]-wExtent[2]+1);
-  for (int i = uExtent[2]; i <= uExtent[3]; i++)
-    {
-    oda->SetTuple(i, ida->GetTuple(i-uExtent[2]));
-    }
-  output->SetYCoordinates(oda);
-  oda->Delete();
-
-  ida = tmp->GetXCoordinates();
-  oda = ida->NewInstance();
-  oda->SetNumberOfComponents(ida->GetNumberOfComponents());
-  oda->SetNumberOfTuples(wExtent[1]-wExtent[0]+1);
-  for (int i = uExtent[0]; i <= uExtent[1]; i++)
-    {
-    oda->SetTuple(i, ida->GetTuple(i-uExtent[0]));
-    }
-  output->SetXCoordinates(oda);
-  oda->Delete();
-
-  //copy in retrieved attributes from sent region
-  int usizek = uExtent[5]-uExtent[4]+1;
-  int usizej = uExtent[3]-uExtent[2]+1;
-  int usizei = uExtent[1]-uExtent[0]+1;
-  int usize  = usizek*usizej*usizei;
-
-  vtkPointData *ipd = tmp->GetPointData();
-  vtkPointData *opd = output->GetPointData();
-  opd->CopyAllocate(ipd, usize, 1000);
-
-  vtkCellData *icd = tmp->GetCellData();
-  vtkCellData *ocd = output->GetCellData();
-  ocd->CopyAllocate(icd, usize, 1000);
-
-  vtkIdType ptCtr = 0;
-  vtkIdType clCtr = 0;
-  for (int k = uExtent[4]; k <= uExtent[5]; k++)
-    {
-    for (int j = uExtent[2]; j <= uExtent[3]; j++)
-      {
-      for (int i = uExtent[0]; i <= uExtent[1]; i++)
-        {
-        int ijk[3] = {i,j,k};
-        vtkIdType oPointId = output->ComputePointId(ijk);
-        opd->CopyData(ipd, ptCtr++, oPointId);
-        vtkIdType oCellId = output->ComputeCellId(ijk);
-        ocd->CopyData(icd, clCtr++, oCellId);
-        }
-      }
-    }
-
-  //copy in retrieved field data
-  vtkFieldData*  inFd = tmp->GetFieldData();
-  vtkFieldData* outFd = output->GetFieldData();
-  if (inFd && outFd)
-    {
-    outFd->PassData(inFd);
-    }
-
-  //clean up the structures we've used here
-  tmp->Delete();
 }
 
 //----------------------------------------------------------------------------
 void vtkTransmitRectilinearGridPiece::PrintSelf(ostream& os, vtkIndent indent)
 {
   this->Superclass::PrintSelf(os,indent);
-
-  os << indent << "Create Ghost Cells: " << (this->CreateGhostCells ? "On\n" : "Off\n");
-
-  os << indent << "Controller: (" << this->Controller << ")\n";
-
 }
-
diff --git a/Filters/Parallel/vtkTransmitRectilinearGridPiece.h b/Filters/Parallel/vtkTransmitRectilinearGridPiece.h
index 4f44cdc3743885da51b7b6d6548b59e7661aebac..9468f5c62e6307393408dd66c219ce009a173353 100644
--- a/Filters/Parallel/vtkTransmitRectilinearGridPiece.h
+++ b/Filters/Parallel/vtkTransmitRectilinearGridPiece.h
@@ -12,58 +12,37 @@
      PURPOSE.  See the above copyright notice for more information.
 
 =========================================================================*/
-// .NAME vtkTransmitRectilinearGridPiece - For parallel processing, restrict
-// IO to the first process in the cluster.
+// .NAME vtkTransmitRectilinearGridPiece - Redistributes data produced
+// by serial readers
 //
 // .SECTION Description
-// This filter updates the appropriate piece by requesting the piece from
-// process 0.  Process 0 always updates all of the data.  It is important that
-// Execute get called on all processes, otherwise the filter will deadlock.
+// This filter can be used to redistribute data from producers that can't
+// produce data in parallel. All data is produced on first process and
+// the distributed to others using the multiprocess controller.
+//
+// Note that this class is legacy. The superclass does all the work and
+// can be used directly instead.
 
 
 #ifndef __vtkTransmitRectilinearGridPiece_h
 #define __vtkTransmitRectilinearGridPiece_h
 
 #include "vtkFiltersParallelModule.h" // For export macro
-#include "vtkRectilinearGridAlgorithm.h"
+#include "vtkTransmitStructuredDataPiece.h"
 
 class vtkMultiProcessController;
 
-class VTKFILTERSPARALLEL_EXPORT vtkTransmitRectilinearGridPiece : public vtkRectilinearGridAlgorithm
+class VTKFILTERSPARALLEL_EXPORT vtkTransmitRectilinearGridPiece : public vtkTransmitStructuredDataPiece
 {
 public:
   static vtkTransmitRectilinearGridPiece *New();
-  vtkTypeMacro(vtkTransmitRectilinearGridPiece, vtkRectilinearGridAlgorithm);
+  vtkTypeMacro(vtkTransmitRectilinearGridPiece, vtkTransmitStructuredDataPiece);
   void PrintSelf(ostream& os, vtkIndent indent);
 
-  // Description:
-  // By defualt this filter uses the global controller,
-  // but this method can be used to set another instead.
-  virtual void SetController(vtkMultiProcessController*);
-  vtkGetObjectMacro(Controller, vtkMultiProcessController);
-
-  // Description:
-  // Turn on/off creating ghost cells (on by default).
-  vtkSetMacro(CreateGhostCells, int);
-  vtkGetMacro(CreateGhostCells, int);
-  vtkBooleanMacro(CreateGhostCells, int);
-
 protected:
   vtkTransmitRectilinearGridPiece();
   ~vtkTransmitRectilinearGridPiece();
 
-  // Data generation method
-  virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *);
-  void RootExecute(vtkRectilinearGrid *input, vtkRectilinearGrid *output,
-                   vtkInformation *outInfo);
-  void SatelliteExecute(int procId, vtkRectilinearGrid *output,
-                        vtkInformation *outInfo);
-  virtual int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *);
-  virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *);
-
-  int CreateGhostCells;
-  vtkMultiProcessController *Controller;
-
 private:
   vtkTransmitRectilinearGridPiece(const vtkTransmitRectilinearGridPiece&); // Not implemented
   void operator=(const vtkTransmitRectilinearGridPiece&); // Not implemented
diff --git a/Filters/Parallel/vtkTransmitStructuredDataPiece.cxx b/Filters/Parallel/vtkTransmitStructuredDataPiece.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..b393921ff3a7d04237586d5d0624a64dde9127df
--- /dev/null
+++ b/Filters/Parallel/vtkTransmitStructuredDataPiece.cxx
@@ -0,0 +1,209 @@
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    vtkTransmitStructuredDataPiece.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 "vtkTransmitStructuredDataPiece.h"
+
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkMultiProcessController.h"
+#include "vtkObjectFactory.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+#include "vtkDataSet.h"
+#include "vtkExtentTranslator.h"
+
+vtkStandardNewMacro(vtkTransmitStructuredDataPiece);
+
+vtkCxxSetObjectMacro(vtkTransmitStructuredDataPiece,Controller,
+                     vtkMultiProcessController);
+
+//----------------------------------------------------------------------------
+vtkTransmitStructuredDataPiece::vtkTransmitStructuredDataPiece()
+{
+  this->Controller = NULL;
+  this->CreateGhostCells = 1;
+  this->SetNumberOfInputPorts(1);
+  this->SetController(vtkMultiProcessController::GetGlobalController());
+}
+
+//----------------------------------------------------------------------------
+vtkTransmitStructuredDataPiece::~vtkTransmitStructuredDataPiece()
+{
+  this->SetController(NULL);
+}
+
+//----------------------------------------------------------------------------
+int vtkTransmitStructuredDataPiece::RequestInformation(
+  vtkInformation *vtkNotUsed(request),
+  vtkInformationVector **inputVector,
+  vtkInformationVector *outputVector)
+{
+  if (this->Controller)
+    {
+    int wExt[6];
+    if (this->Controller->GetLocalProcessId() == 0)
+      {
+      vtkInformation* inInfo = inputVector[0]->GetInformationObject(0);
+      inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wExt);
+      }
+    this->Controller->Broadcast(wExt, 6, 0);
+    vtkInformation* outInfo = outputVector->GetInformationObject(0);
+    outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wExt, 6);
+    }
+  return 1;
+}
+
+//----------------------------------------------------------------------------
+int vtkTransmitStructuredDataPiece::RequestUpdateExtent(
+  vtkInformation *vtkNotUsed(request),
+  vtkInformationVector **inputVector,
+  vtkInformationVector *vtkNotUsed(outputVector))
+{
+  if (this->Controller)
+    {
+    if (this->Controller->GetLocalProcessId() > 0)
+      {
+      int wExt[6] = {0, -1, 0, -1, 0, -1};
+      inputVector[0]->GetInformationObject(0)->Set(
+        vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), wExt, 6);
+      }
+    }
+  return 1;
+}
+
+//----------------------------------------------------------------------------
+int vtkTransmitStructuredDataPiece::RequestData(
+  vtkInformation *vtkNotUsed(request),
+  vtkInformationVector **inputVector,
+  vtkInformationVector *outputVector)
+{
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+  vtkDataSet *output = vtkDataSet::GetData(outputVector);
+
+  int procId;
+
+  if (this->Controller == NULL)
+    {
+    vtkErrorMacro("Could not find Controller.");
+    return 1;
+    }
+
+  procId = this->Controller->GetLocalProcessId();
+  if (procId == 0)
+    {
+    vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
+    vtkDataSet *input = vtkDataSet::GetData(inputVector[0]);
+    this->RootExecute(input, output, outInfo);
+    }
+  else
+    {
+    this->SatelliteExecute(procId, output, outInfo);
+    }
+
+  return 1;
+}
+
+//----------------------------------------------------------------------------
+void vtkTransmitStructuredDataPiece::RootExecute(vtkDataSet *input,
+                                                 vtkDataSet *output,
+                                                 vtkInformation *outInfo)
+{
+  vtkDataSet *tmp = input->NewInstance();
+  int numProcs, i;
+
+  int updatePiece = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER());
+  int updateNumPieces = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES());
+  int updatedGhost = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS());
+  if (!this->CreateGhostCells)
+    {
+    updatedGhost = 0;
+    }
+  int* wholeExt = input->GetInformation()->Get(vtkDataObject::DATA_EXTENT());
+
+  vtkExtentTranslator* et = vtkExtentTranslator::New();
+
+  int newExt[6];
+  et->PieceToExtentThreadSafe(updatePiece, updateNumPieces, updatedGhost,
+                              wholeExt, newExt, vtkExtentTranslator::BLOCK_MODE, 0);
+  output->ShallowCopy(input);
+  output->Crop(newExt);
+
+  if (updatedGhost > 0)
+    {
+    // Create ghost array
+    int zeroExt[6];
+    et->PieceToExtentThreadSafe(updatePiece, updateNumPieces, 0,
+                                wholeExt, zeroExt, vtkExtentTranslator::BLOCK_MODE, 0);
+    output->GenerateGhostLevelArray(zeroExt);
+    }
+
+  numProcs = this->Controller->GetNumberOfProcesses();
+  for (i = 1; i < numProcs; ++i)
+    {
+    int updateInfo[3];
+    this->Controller->Receive(updateInfo, 3, i, 22341);
+    et->PieceToExtentThreadSafe(updateInfo[0], updateInfo[1], updateInfo[2],
+                                wholeExt, newExt, vtkExtentTranslator::BLOCK_MODE, 0);
+    tmp->ShallowCopy(input);
+    tmp->Crop(newExt);
+
+    if (updateInfo[2] > 0)
+      {
+      // Create ghost array
+      int zeroExt[6];
+      et->PieceToExtentThreadSafe(updateInfo[0], updateInfo[1], 0,
+                                  wholeExt, zeroExt, vtkExtentTranslator::BLOCK_MODE, 0);
+      tmp->GenerateGhostLevelArray(zeroExt);
+      }
+
+    this->Controller->Send(tmp, i, 22342);
+    }
+
+  //clean up the structures we've used here
+  tmp->Delete();
+  et->Delete();
+}
+
+//----------------------------------------------------------------------------
+void vtkTransmitStructuredDataPiece::SatelliteExecute(
+  int, vtkDataSet *output, vtkInformation *outInfo)
+{
+  int updatePiece = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER());
+  int updateNumPieces = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES());
+  int updatedGhost = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS());
+  if (!this->CreateGhostCells)
+    {
+    updatedGhost = 0;
+    }
+
+  int updateInfo[3];
+  updateInfo[0] = updatePiece;
+  updateInfo[1] = updateNumPieces;
+  updateInfo[2] = updatedGhost;
+
+  this->Controller->Send(updateInfo, 3, 0, 22341);
+
+  //receive root's response
+  this->Controller->Receive(output, 0, 22342);
+}
+
+//----------------------------------------------------------------------------
+void vtkTransmitStructuredDataPiece::PrintSelf(ostream& os, vtkIndent indent)
+{
+  this->Superclass::PrintSelf(os,indent);
+
+  os << indent << "Create Ghost Cells: " << (this->CreateGhostCells ? "On\n" : "Off\n");
+
+  os << indent << "Controller: (" << this->Controller << ")\n";
+
+}
diff --git a/Filters/Parallel/vtkTransmitStructuredDataPiece.h b/Filters/Parallel/vtkTransmitStructuredDataPiece.h
new file mode 100644
index 0000000000000000000000000000000000000000..36cc61ea8d51c19882fe2236cb908d713cb0310f
--- /dev/null
+++ b/Filters/Parallel/vtkTransmitStructuredDataPiece.h
@@ -0,0 +1,72 @@
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    vtkTransmitStructuredDataPiece.h
+
+  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
+  All rights reserved.
+  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notice for more information.
+
+=========================================================================*/
+// .NAME vtkTransmitRectilinearGridPiece - Redistributes data produced
+// by serial readers
+//
+// .SECTION Description
+// This filter can be used to redistribute data from producers that can't
+// produce data in parallel. All data is produced on first process and
+// the distributed to others using the multiprocess controller.
+
+
+#ifndef __vtkTransmitStructuredDataPiece_h
+#define __vtkTransmitStructuredDataPiece_h
+
+#include "vtkFiltersParallelModule.h" // For export macro
+#include "vtkDataSetAlgorithm.h"
+
+class vtkMultiProcessController;
+
+class VTKFILTERSPARALLEL_EXPORT vtkTransmitStructuredDataPiece : public vtkDataSetAlgorithm
+{
+public:
+  static vtkTransmitStructuredDataPiece *New();
+  vtkTypeMacro(vtkTransmitStructuredDataPiece, vtkDataSetAlgorithm);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // By defualt this filter uses the global controller,
+  // but this method can be used to set another instead.
+  virtual void SetController(vtkMultiProcessController*);
+  vtkGetObjectMacro(Controller, vtkMultiProcessController);
+
+  // Description:
+  // Turn on/off creating ghost cells (on by default).
+  vtkSetMacro(CreateGhostCells, int);
+  vtkGetMacro(CreateGhostCells, int);
+  vtkBooleanMacro(CreateGhostCells, int);
+
+protected:
+  vtkTransmitStructuredDataPiece();
+  ~vtkTransmitStructuredDataPiece();
+
+  // Data generation method
+  virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *);
+  void RootExecute(vtkDataSet *input, vtkDataSet *output,
+                   vtkInformation *outInfo);
+  void SatelliteExecute(int procId, vtkDataSet *output,
+                        vtkInformation *outInfo);
+  virtual int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *);
+  virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *);
+
+  int CreateGhostCells;
+  vtkMultiProcessController *Controller;
+
+private:
+  vtkTransmitStructuredDataPiece(const vtkTransmitStructuredDataPiece&); // Not implemented
+  void operator=(const vtkTransmitStructuredDataPiece&); // Not implemented
+};
+
+#endif
diff --git a/Filters/Parallel/vtkTransmitStructuredGridPiece.cxx b/Filters/Parallel/vtkTransmitStructuredGridPiece.cxx
index d7831ce88b1299f8f9f4b9845a0b82915c710b04..bdc409423d6431fff7aad11b2ece4f4f5f6b19ad 100644
--- a/Filters/Parallel/vtkTransmitStructuredGridPiece.cxx
+++ b/Filters/Parallel/vtkTransmitStructuredGridPiece.cxx
@@ -14,355 +14,22 @@
 =========================================================================*/
 #include "vtkTransmitStructuredGridPiece.h"
 
-#include "vtkCellData.h"
-#include "vtkExtractGrid.h"
-#include "vtkInformation.h"
-#include "vtkInformationVector.h"
-#include "vtkMultiProcessController.h"
 #include "vtkObjectFactory.h"
-#include "vtkPointData.h"
-#include "vtkStreamingDemandDrivenPipeline.h"
-#include "vtkStructuredGrid.h"
-#include "vtkDoubleArray.h"
 
 vtkStandardNewMacro(vtkTransmitStructuredGridPiece);
 
-vtkCxxSetObjectMacro(vtkTransmitStructuredGridPiece,Controller,
-                     vtkMultiProcessController);
-
 //----------------------------------------------------------------------------
 vtkTransmitStructuredGridPiece::vtkTransmitStructuredGridPiece()
 {
-  this->Controller = NULL;
-  this->CreateGhostCells = 1;
-  this->SetNumberOfInputPorts(1);
-  this->SetController(vtkMultiProcessController::GetGlobalController());
-  if (this->Controller)
-    {
-    if (this->Controller->GetLocalProcessId() != 0)
-      {
-      this->SetNumberOfInputPorts(0);
-      }
-    }
 }
 
 //----------------------------------------------------------------------------
 vtkTransmitStructuredGridPiece::~vtkTransmitStructuredGridPiece()
 {
-  this->SetController(NULL);
-}
-
-//----------------------------------------------------------------------------
-int vtkTransmitStructuredGridPiece::RequestInformation(
-  vtkInformation *vtkNotUsed(request),
-  vtkInformationVector **inputVector,
-  vtkInformationVector *outputVector)
-{
-  if (this->Controller == NULL)
-    {
-    return 1;
-    }
-  else
-    {
-    int wExtent[6] = {0,-1,0,-1,0,-1};
-    int dims[3];
-
-    vtkInformation *outInfo = outputVector->GetInformationObject(0);
-
-    if (this->Controller->GetLocalProcessId() == 0)
-      {
-      //Root sends meta-information to the satellites.
-
-      vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
-      inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wExtent);
-
-      vtkStructuredGrid *input = vtkStructuredGrid::SafeDownCast(
-        inInfo->Get(vtkDataObject::DATA_OBJECT()));
-      input->GetDimensions(dims);
-
-      int numProcs = this->Controller->GetNumberOfProcesses();
-      for (int i = 1; i < numProcs; ++i)
-        {
-        this->Controller->Send(wExtent, 6, i, 22342);
-        this->Controller->Send(dims, 3, i, 22342);
-        }
-      }
-    else
-      {
-      //Satellites ask root for meta-info, because they do not read it themselves.
-
-      this->Controller->Receive(wExtent, 6, 0, 22342);
-      this->Controller->Receive(dims, 3, 0, 22342);
-
-      vtkStructuredGrid *output = vtkStructuredGrid::SafeDownCast(
-         outInfo->Get(vtkDataObject::DATA_OBJECT()));
-
-      output->SetExtent(wExtent);
-      output->SetDimensions(dims);
-      }
-
-    outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),
-                 wExtent,
-                 6);
-
-    return 1;
-    }
-}
-
-//----------------------------------------------------------------------------
-int vtkTransmitStructuredGridPiece::RequestUpdateExtent(
-  vtkInformation *vtkNotUsed(request),
-  vtkInformationVector **inputVector,
-  vtkInformationVector *vtkNotUsed(outputVector))
-{
-  if (this->Controller == NULL)
-    {
-    vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
-
-    inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),
-                inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()),
-                6);
-
-    inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(),
-                0);
-    return 1;
-    }
-
-  if (this->Controller->GetLocalProcessId() == 0)
-    { // Request everything.
-    vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
-    inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),
-                inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()),
-                6);
-
-    inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(),
-                0);
-    }
-  else
-    { // Request nothing from input, will get it from root
-    }
-
-  return 1;
-}
-
-
-//----------------------------------------------------------------------------
-int vtkTransmitStructuredGridPiece::RequestData(
-  vtkInformation *vtkNotUsed(request),
-  vtkInformationVector **inputVector,
-  vtkInformationVector *outputVector)
-{
-  vtkInformation *outInfo = outputVector->GetInformationObject(0);
-  vtkStructuredGrid *output = vtkStructuredGrid::SafeDownCast(
-    outInfo->Get(vtkDataObject::DATA_OBJECT()));
-
-  int procId;
-
-  if (this->Controller == NULL)
-    {
-    vtkErrorMacro("Could not find Controller.");
-    return 1;
-    }
-
-  procId = this->Controller->GetLocalProcessId();
-  if (procId == 0)
-    {
-    vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
-    vtkStructuredGrid *input = vtkStructuredGrid::SafeDownCast(
-      inInfo->Get(vtkDataObject::DATA_OBJECT()));
-
-    this->RootExecute(input, output, outInfo);
-    }
-  else
-    {
-    this->SatelliteExecute(procId, output, outInfo);
-    }
-
-  // TODO (berk)
-  // Fix this
-  /*
-  int ghostLevel = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS());
-  if (ghostLevel > 0 && this->CreateGhostCells)
-    {
-    int updatePiece = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER());
-    int updateNumPieces = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES());
-    vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
-    int* wholeExt = inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT());
-    vtkExtentTranslator* et = vtkStreamingDemandDrivenPipeline::GetExtentTranslator(inInfo);
-    output->GenerateGhostLevelArray(updatePiece,
-                                    updateNumPieces,
-                                    ghostLevel,
-                                    wholeExt,
-                                    et);
-    }
-  */
-
-  return 1;
-}
-
-//----------------------------------------------------------------------------
-void vtkTransmitStructuredGridPiece::RootExecute(vtkStructuredGrid *input,
-                                                   vtkStructuredGrid *output,
-                                                   vtkInformation *outInfo)
-{
-  vtkStructuredGrid *tmp = vtkStructuredGrid::New();
-  vtkExtractGrid *extract = vtkExtractGrid::New();
-  int ext[7];
-  int numProcs, i;
-
-  int outExtent[6];
-  outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), outExtent);
-
-  vtkStreamingDemandDrivenPipeline *extractExecutive =
-    vtkStreamingDemandDrivenPipeline::SafeDownCast(extract->GetExecutive());
-
-  // First, set up the pipeline and handle local request.
-  tmp->ShallowCopy(input);
-  extract->SetInputData(tmp);
-  extractExecutive->UpdateDataObject();
-
-  vtkInformation *extractOutInfo = extractExecutive->GetOutputInformation(0);
-
-  extractOutInfo->Set(
-    vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),
-    outInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()),
-    6);
-  extractOutInfo->Set(
-    vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(),
-    outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS()));
-  extractOutInfo->Set(
-    vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT_INITIALIZED(), 1);
-  extract->Update();
-
-  output->CopyStructure(extract->GetOutput());
-  output->GetPointData()->PassData(extract->GetOutput()->GetPointData());
-  output->GetCellData()->PassData(extract->GetOutput()->GetCellData());
-  vtkFieldData*  inFd = extract->GetOutput()->GetFieldData();
-  vtkFieldData* outFd = output->GetFieldData();
-  if (inFd && outFd)
-    {
-    outFd->PassData(inFd);
-    }
-
-  // Now do each of the satellite requests.
-  numProcs = this->Controller->GetNumberOfProcesses();
-  for (i = 1; i < numProcs; ++i)
-    {
-    this->Controller->Receive(ext, 7, i, 22341);
-    extractOutInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),
-                        ext,
-                        6);
-    extractOutInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(),
-                        ext[6]);
-    extract->Modified();
-    extract->Update();
-    this->Controller->Send(extract->GetOutput(), i, 22342);
-    }
-
-  //clean up the structures we've used here
-  tmp->Delete();
-  extract->Delete();
-}
-
-//----------------------------------------------------------------------------
-void vtkTransmitStructuredGridPiece::SatelliteExecute(
-  int, vtkStructuredGrid *output, vtkInformation *outInfo)
-{
-  vtkStructuredGrid *tmp = vtkStructuredGrid::New();
-
-  //decide what we want to ask for and ask root for it
-  int uExtent[7];
-  outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), uExtent);
-  uExtent[6] = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS());
-  this->Controller->Send(uExtent, 7, 0, 22341);
-
-  int wExtent[6];
-  outInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wExtent);
-
-  //receive root's response
-  this->Controller->Receive(tmp, 0, 22342);
-
-  // Retrieve Structure within requested region.
-  int ext[6];
-  tmp->GetExtent(ext);
-  output->SetExtent(wExtent);
-
-  int wsizek = wExtent[5]-wExtent[4]+1;
-  int wsizej = wExtent[3]-wExtent[2]+1;
-  int wsizei = wExtent[1]-wExtent[0]+1;
-  int wsize  = wsizek*wsizej*wsizei;
-  int wcsize  = (wsizek-1)*(wsizej-1)*(wsizei-1);
-
-  vtkPoints *ip = tmp->GetPoints();
-  vtkPoints *op = vtkPoints::New();
-  op->SetNumberOfPoints(wsize);
-
-  double coords[3];
-  vtkIdType pCtr = 0;
-  for (int k = uExtent[4]; k <= uExtent[5]; k++)
-    {
-    for (int j = uExtent[2]; j <= uExtent[3]; j++)
-      {
-      for (int i = uExtent[0]; i <= uExtent[1]; i++)
-        {
-        vtkIdType pointId = k*wsizej*wsizei +  j*wsizei + i;
-        ip->GetPoint(pCtr++, coords);
-        op->SetPoint(pointId, coords);
-        }
-      }
-    }
-  op->Squeeze();
-  output->SetPoints(op);
-  op->Delete();
-
-  // Retrieve attributes within requested region.
-  vtkPointData *ipd = tmp->GetPointData();
-  vtkPointData *opd = output->GetPointData();
-  opd->CopyAllocate(ipd, wsize, 1000);
-
-  vtkCellData *icd = tmp->GetCellData();
-  vtkCellData *ocd = output->GetCellData();
-  ocd->CopyAllocate(icd, wcsize, 1000);
-
-  vtkIdType ptCtr = 0;
-  vtkIdType clCtr = 0;
-  for (int k = uExtent[4]; k <= uExtent[5]; k++)
-    {
-    for (int j = uExtent[2]; j <= uExtent[3]; j++)
-      {
-      for (int i = uExtent[0]; i <= uExtent[1]; i++)
-        {
-        vtkIdType pointId = k*wsizej*wsizei +  j*wsizei + i;
-        opd->CopyData(ipd, ptCtr++, pointId);
-        if ((k != uExtent[5]) && (j != uExtent[3]) && (i != uExtent[1]))
-          {
-          vtkIdType cellId = k*(wsizej-1)*(wsizei-1) +  j*(wsizei-1) + i;
-          ocd->CopyData(icd, clCtr++, cellId);
-          }
-        }
-      }
-    }
-
-  // Retrieve field data.
-  vtkFieldData*  inFd = tmp->GetFieldData();
-  vtkFieldData* outFd = output->GetFieldData();
-  if (inFd && outFd)
-    {
-    outFd->PassData(inFd);
-    }
-
-  //clean up the structures we've used here
-  tmp->Delete();
 }
 
 //----------------------------------------------------------------------------
 void vtkTransmitStructuredGridPiece::PrintSelf(ostream& os, vtkIndent indent)
 {
   this->Superclass::PrintSelf(os,indent);
-
-  os << indent << "Create Ghost Cells: " << (this->CreateGhostCells ? "On\n" : "Off\n");
-
-  os << indent << "Controller: (" << this->Controller << ")\n";
-
 }
-
diff --git a/Filters/Parallel/vtkTransmitStructuredGridPiece.h b/Filters/Parallel/vtkTransmitStructuredGridPiece.h
index 3dab0f4aafc8f977b7927b724d8bcdcc82b1cefc..e1f35a21e915d0ecdb7b220ffac80cd20aaf5956 100644
--- a/Filters/Parallel/vtkTransmitStructuredGridPiece.h
+++ b/Filters/Parallel/vtkTransmitStructuredGridPiece.h
@@ -12,58 +12,37 @@
      PURPOSE.  See the above copyright notice for more information.
 
 =========================================================================*/
-// .NAME vtkTransmitStructuredGridPiece - For parallel processing, restrict
-// IO to the first process in the cluster.
+// .NAME vtkTransmitRectilinearGridPiece - Redistributes data produced
+// by serial readers
 //
 // .SECTION Description
-// This filter updates the appropriate piece by requesting the piece from
-// process 0.  Process 0 always updates all of the data.  It is important that
-// Execute get called on all processes, otherwise the filter will deadlock.
+// This filter can be used to redistribute data from producers that can't
+// produce data in parallel. All data is produced on first process and
+// the distributed to others using the multiprocess controller.
+//
+// Note that this class is legacy. The superclass does all the work and
+// can be used directly instead.
 
 
 #ifndef __vtkTransmitStructuredGridPiece_h
 #define __vtkTransmitStructuredGridPiece_h
 
 #include "vtkFiltersParallelModule.h" // For export macro
-#include "vtkStructuredGridAlgorithm.h"
+#include "vtkTransmitStructuredDataPiece.h"
 
 class vtkMultiProcessController;
 
-class VTKFILTERSPARALLEL_EXPORT vtkTransmitStructuredGridPiece : public vtkStructuredGridAlgorithm
+class VTKFILTERSPARALLEL_EXPORT vtkTransmitStructuredGridPiece : public vtkTransmitStructuredDataPiece
 {
 public:
   static vtkTransmitStructuredGridPiece *New();
-  vtkTypeMacro(vtkTransmitStructuredGridPiece, vtkStructuredGridAlgorithm);
+  vtkTypeMacro(vtkTransmitStructuredGridPiece, vtkTransmitStructuredDataPiece);
   void PrintSelf(ostream& os, vtkIndent indent);
 
-  // Description:
-  // By defualt this filter uses the global controller,
-  // but this method can be used to set another instead.
-  virtual void SetController(vtkMultiProcessController*);
-  vtkGetObjectMacro(Controller, vtkMultiProcessController);
-
-  // Description:
-  // Turn on/off creating ghost cells (on by default).
-  vtkSetMacro(CreateGhostCells, int);
-  vtkGetMacro(CreateGhostCells, int);
-  vtkBooleanMacro(CreateGhostCells, int);
-
 protected:
   vtkTransmitStructuredGridPiece();
   ~vtkTransmitStructuredGridPiece();
 
-  // Data generation method
-  virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *);
-  void RootExecute(vtkStructuredGrid *input, vtkStructuredGrid *output,
-                   vtkInformation *outInfo);
-  void SatelliteExecute(int procId, vtkStructuredGrid *output,
-                        vtkInformation *outInfo);
-  virtual int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *);
-  virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *);
-
-  int CreateGhostCells;
-  vtkMultiProcessController *Controller;
-
 private:
   vtkTransmitStructuredGridPiece(const vtkTransmitStructuredGridPiece&); // Not implemented
   void operator=(const vtkTransmitStructuredGridPiece&); // Not implemented
diff --git a/Filters/Parallel/vtkTransmitUnstructuredGridPiece.cxx b/Filters/Parallel/vtkTransmitUnstructuredGridPiece.cxx
index 085ae305d450f9450270ec9910710323f5d73f13..11138356ac24f8776b63695d484374a9991beec6 100644
--- a/Filters/Parallel/vtkTransmitUnstructuredGridPiece.cxx
+++ b/Filters/Parallel/vtkTransmitUnstructuredGridPiece.cxx
@@ -45,48 +45,6 @@ vtkTransmitUnstructuredGridPiece::~vtkTransmitUnstructuredGridPiece()
   this->SetController(NULL);
 }
 
-//----------------------------------------------------------------------------
-int vtkTransmitUnstructuredGridPiece::RequestUpdateExtent(
-  vtkInformation *vtkNotUsed(request),
-  vtkInformationVector **inputVector,
-  vtkInformationVector *vtkNotUsed(outputVector))
-{
-  // get the info object
-  vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
-
-  if (this->Controller == NULL)
-    {
-    inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(),
-                1);
-    inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(),
-                0);
-    inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(),
-                0);
-    return 1;
-    }
-
-  if (this->Controller->GetLocalProcessId() == 0)
-    { // Request everything.
-    inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(),
-                1);
-    inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(),
-                0);
-    inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(),
-                0);
-    }
-  else
-    { // Request nothing.
-    inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(),
-                0);
-    inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(),
-                0);
-    inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(),
-                0);
-    }
-
-  return 1;
-}
-
 //----------------------------------------------------------------------------
 int vtkTransmitUnstructuredGridPiece::RequestData(
   vtkInformation *vtkNotUsed(request),
diff --git a/Filters/Parallel/vtkTransmitUnstructuredGridPiece.h b/Filters/Parallel/vtkTransmitUnstructuredGridPiece.h
index 4e9da5d5c2c628a3657947a955edd657e7369949..ad0f133456a2cee33274e3b604fbcf86ed820b26 100644
--- a/Filters/Parallel/vtkTransmitUnstructuredGridPiece.h
+++ b/Filters/Parallel/vtkTransmitUnstructuredGridPiece.h
@@ -12,12 +12,13 @@
      PURPOSE.  See the above copyright notice for more information.
 
 =========================================================================*/
-// .NAME vtkTransmitUnstructuredGridPiece - Return specified piece, including specified
-// number of ghost levels.
+// .NAME vtkTransmitRectilinearGridPiece - Redistributes data produced
+// by serial readers
+//
 // .SECTION Description
-// This filter updates the appropriate piece by requesting the piece from
-// process 0.  Process 0 always updates all of the data.  It is important that
-// Execute get called on all processes, otherwise the filter will deadlock.
+// This filter can be used to redistribute data from producers that can't
+// produce data in parallel. All data is produced on first process and
+// the distributed to others using the multiprocess controller.
 
 
 #ifndef __vtkTransmitUnstructuredGridPiece_h
@@ -57,7 +58,6 @@ protected:
                    vtkInformation *outInfo);
   void SatelliteExecute(int procId, vtkUnstructuredGrid *output,
                         vtkInformation *outInfo);
-  virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *);
 
   int CreateGhostCells;
   vtkMultiProcessController *Controller;
diff --git a/Filters/ParallelImaging/vtkTransmitImageDataPiece.cxx b/Filters/ParallelImaging/vtkTransmitImageDataPiece.cxx
index ac38e1630b6730e4a0fbd5bafad0712fd3d8c377..0ad19f53d32006448a011e1a15d32404305a3613 100644
--- a/Filters/ParallelImaging/vtkTransmitImageDataPiece.cxx
+++ b/Filters/ParallelImaging/vtkTransmitImageDataPiece.cxx
@@ -14,337 +14,22 @@
 =========================================================================*/
 #include "vtkTransmitImageDataPiece.h"
 
-#include "vtkCellData.h"
-#include "vtkImageClip.h"
-#include "vtkInformation.h"
-#include "vtkInformationVector.h"
-#include "vtkMultiProcessController.h"
 #include "vtkObjectFactory.h"
-#include "vtkPointData.h"
-#include "vtkStreamingDemandDrivenPipeline.h"
-#include "vtkImageData.h"
-#include "vtkDoubleArray.h"
 
 vtkStandardNewMacro(vtkTransmitImageDataPiece);
 
-vtkCxxSetObjectMacro(vtkTransmitImageDataPiece,Controller,
-                     vtkMultiProcessController);
-
 //----------------------------------------------------------------------------
 vtkTransmitImageDataPiece::vtkTransmitImageDataPiece()
 {
-  this->Controller = NULL;
-  this->CreateGhostCells = 1;
-  this->SetNumberOfInputPorts(1);
-  this->SetController(vtkMultiProcessController::GetGlobalController());
 }
 
 //----------------------------------------------------------------------------
 vtkTransmitImageDataPiece::~vtkTransmitImageDataPiece()
 {
-  this->SetController(NULL);
-}
-
-//----------------------------------------------------------------------------
-int vtkTransmitImageDataPiece::RequestInformation(
-  vtkInformation *vtkNotUsed(request),
-  vtkInformationVector **inputVector,
-  vtkInformationVector *outputVector)
-{
-  if (this->Controller == NULL)
-    {
-    return 1;
-    }
-  else
-    {
-    int wExtent[6] = {0,-1,0,-1,0,-1};
-    int dims[3];
-    double spacing[3];
-    double origin[3];
-
-    vtkInformation *outInfo = outputVector->GetInformationObject(0);
-
-    if (this->Controller->GetLocalProcessId() == 0)
-      {
-      //Root sends meta-information to the satellites.
-
-      vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
-      inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wExtent);
-
-      vtkImageData *input = vtkImageData::SafeDownCast(
-        inInfo->Get(vtkDataObject::DATA_OBJECT()));
-      input->GetDimensions(dims);
-      input->GetSpacing(spacing);
-      input->GetOrigin(origin);
-
-      int numProcs = this->Controller->GetNumberOfProcesses();
-      for (int i = 1; i < numProcs; ++i)
-        {
-        this->Controller->Send(wExtent, 6, i, 22342);
-        this->Controller->Send(dims, 3, i, 22342);
-        this->Controller->Send(spacing, 3, i, 22342);
-        this->Controller->Send(origin, 3, i, 22342);
-        }
-      }
-    else
-      {
-      //Satellites ask root for meta-info, because they do not read it themselves.
-
-      this->Controller->Receive(wExtent, 6, 0, 22342);
-      this->Controller->Receive(dims, 3, 0, 22342);
-      this->Controller->Receive(spacing, 3, 0, 22342);
-      this->Controller->Receive(origin, 3, 0, 22342);
-
-      vtkImageData *output = vtkImageData::SafeDownCast(
-         outInfo->Get(vtkDataObject::DATA_OBJECT()));
-
-      output->SetExtent(wExtent);
-      output->SetDimensions(dims);
-      output->SetSpacing(spacing);
-      output->SetOrigin(origin);
-      }
-
-    outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),
-                 wExtent,
-                 6);
-
-    return 1;
-    }
-}
-
-//----------------------------------------------------------------------------
-int vtkTransmitImageDataPiece::RequestUpdateExtent(
-  vtkInformation *vtkNotUsed(request),
-  vtkInformationVector **inputVector,
-  vtkInformationVector *vtkNotUsed(outputVector))
-{
-
-  if (this->Controller == NULL)
-    {
-    vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
-
-    inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),
-                inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()),
-                6);
-
-    inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(),
-                0);
-    return 1;
-    }
-
-  if (this->Controller->GetLocalProcessId() == 0)
-    { // Request everything.
-    vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
-
-    inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),
-                inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()),
-                6);
-
-    inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(),
-                0);
-    }
-  else
-    { // Request nothing, get it from root instead.
-    }
-
-  return 1;
-}
-
-
-//----------------------------------------------------------------------------
-int vtkTransmitImageDataPiece::RequestData(
-  vtkInformation *vtkNotUsed(request),
-  vtkInformationVector **inputVector,
-  vtkInformationVector *outputVector)
-{
-  vtkInformation *outInfo = outputVector->GetInformationObject(0);
-  vtkImageData *output = vtkImageData::SafeDownCast(
-    outInfo->Get(vtkDataObject::DATA_OBJECT()));
-
-  int procId;
-
-  if (this->Controller == NULL)
-    {
-    vtkErrorMacro("Could not find Controller.");
-    return 1;
-    }
-
-  procId = this->Controller->GetLocalProcessId();
-  if (procId == 0)
-    {
-    vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
-    vtkImageData *input = vtkImageData::SafeDownCast(
-      inInfo->Get(vtkDataObject::DATA_OBJECT()));
-
-    this->RootExecute(input, output, outInfo);
-    }
-  else
-    {
-    this->SatelliteExecute(procId, output, outInfo);
-    }
-
-  // TODO (berk)
-  // Fix this
-  /*
-  int ghostLevel = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS());
-  if (ghostLevel > 0 && this->CreateGhostCells)
-    {
-    int updatePiece = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER());
-    int updateNumPieces = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES());
-    vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
-    int* wholeExt = inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT());
-    vtkExtentTranslator* et = vtkStreamingDemandDrivenPipeline::GetExtentTranslator(inInfo);
-    output->GenerateGhostLevelArray(updatePiece,
-                                    updateNumPieces,
-                                    ghostLevel,
-                                    wholeExt,
-                                    et);
-    }
-  */
-
-  return 1;
-}
-
-//----------------------------------------------------------------------------
-void vtkTransmitImageDataPiece::RootExecute(vtkImageData *input,
-                                            vtkImageData *output,
-                                            vtkInformation *outInfo)
-{
-  vtkImageData *tmp = vtkImageData::New();
-  vtkImageClip *extract = vtkImageClip::New();
-  extract->ClipDataOn();
-
-  int ext[7];
-  int numProcs, i;
-
-  int outExtent[6];
-  outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), outExtent);
-
-  vtkStreamingDemandDrivenPipeline *extractExecutive =
-    vtkStreamingDemandDrivenPipeline::SafeDownCast(extract->GetExecutive());
-
-  // First, set up the pipeline and handle local request.
-  tmp->ShallowCopy(input);
-  extract->SetInputData(tmp);
-  extractExecutive->UpdateDataObject();
-
-  vtkInformation *extractOutInfo = extractExecutive->GetOutputInformation(0);
-
-  extractOutInfo->Set(
-    vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),
-    outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()),
-    6);
-  extractOutInfo->Set(
-    vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(),
-    outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS()));
-  extractOutInfo->Set(
-    vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT_INITIALIZED(), 1);
-  extract->Update();
-
-  // Copy geometry without copying information.
-  output->CopyStructure(extract->GetOutput());
-  output->GetPointData()->PassData(extract->GetOutput()->GetPointData());
-  output->GetCellData()->PassData(extract->GetOutput()->GetCellData());
-  vtkFieldData*  inFd = extract->GetOutput()->GetFieldData();
-  vtkFieldData* outFd = output->GetFieldData();
-  if (inFd && outFd)
-    {
-    outFd->PassData(inFd);
-    }
-
-  // Now do each of the satellite requests.
-  numProcs = this->Controller->GetNumberOfProcesses();
-  for (i = 1; i < numProcs; ++i)
-    {
-    this->Controller->Receive(ext, 7, i, 22341);
-    extractOutInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),
-                        ext,
-                        6);
-    extractOutInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(),
-                        ext[6]);
-    extract->Modified();
-    extract->Update();
-    this->Controller->Send(extract->GetOutput(), i, 22342);
-    }
-
-  //clean up the structures we've used here
-  tmp->Delete();
-  extract->Delete();
-}
-
-//----------------------------------------------------------------------------
-void vtkTransmitImageDataPiece::SatelliteExecute(
-  int, vtkImageData *output, vtkInformation *outInfo)
-{
-  vtkImageData *tmp = vtkImageData::New();
-
-  //decide what we want to ask for and ask root for it
-  int uExtent[7];
-  outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), uExtent);
-  uExtent[6] = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS());
-  this->Controller->Send(uExtent, 7, 0, 22341);
-
-  int wExtent[6];
-  outInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wExtent);
-
-  //receive root's response
-  this->Controller->Receive(tmp, 0, 22342);
-
-  //recover structure
-  int ext[6];
-  tmp->GetExtent(ext);
-  output->SetExtent(wExtent);
-
-  //copy in retrieved attributes from sent region
-  int usizek = uExtent[5]-uExtent[4]+1;
-  int usizej = uExtent[3]-uExtent[2]+1;
-  int usizei = uExtent[1]-uExtent[0]+1;
-  int usize  = usizek*usizej*usizei;
-
-  vtkPointData *ipd = tmp->GetPointData();
-  vtkPointData *opd = output->GetPointData();
-  opd->CopyAllocate(ipd, usize, 1000);
-
-  vtkCellData *icd = tmp->GetCellData();
-  vtkCellData *ocd = output->GetCellData();
-  ocd->CopyAllocate(icd, usize, 1000);
-
-  vtkIdType ptCtr = 0;
-  vtkIdType clCtr = 0;
-  for (int k = uExtent[4]; k <= uExtent[5]; k++)
-    {
-    for (int j = uExtent[2]; j <= uExtent[3]; j++)
-      {
-      for (int i = uExtent[0]; i <= uExtent[1]; i++)
-        {
-        int ijk[3] = {i,j,k};
-        vtkIdType oPointId = output->ComputePointId(ijk);
-        opd->CopyData(ipd, ptCtr++, oPointId);
-        vtkIdType oCellId = output->ComputeCellId(ijk);
-        ocd->CopyData(icd, clCtr++, oCellId);
-        }
-      }
-    }
-
-  //copy in retrieved field data
-  vtkFieldData*  inFd = tmp->GetFieldData();
-  vtkFieldData* outFd = output->GetFieldData();
-  if (inFd && outFd)
-    {
-    outFd->PassData(inFd);
-    }
-
-  //clean up the structures we've used here
-  tmp->Delete();
 }
 
 //----------------------------------------------------------------------------
 void vtkTransmitImageDataPiece::PrintSelf(ostream& os, vtkIndent indent)
 {
   this->Superclass::PrintSelf(os,indent);
-
-  os << indent << "Create Ghost Cells: " << (this->CreateGhostCells ? "On\n" : "Off\n");
-
-  os << indent << "Controller: (" << this->Controller << ")\n";
-
 }
diff --git a/Filters/ParallelImaging/vtkTransmitImageDataPiece.h b/Filters/ParallelImaging/vtkTransmitImageDataPiece.h
index a2f32468e44e5df3fd92b534be54e5ac1e8c1d54..a537c5d50fcba048c28fe661e71a8e80f1552ef6 100644
--- a/Filters/ParallelImaging/vtkTransmitImageDataPiece.h
+++ b/Filters/ParallelImaging/vtkTransmitImageDataPiece.h
@@ -12,58 +12,37 @@
      PURPOSE.  See the above copyright notice for more information.
 
 =========================================================================*/
-// .NAME vtkTransmitImageDataPiece - For parallel processing, restrict IO to
-// the first process in the cluste.r
+// .NAME vtkTransmitRectilinearGridPiece - Redistributes data produced
+// by serial readers
 //
 // .SECTION Description
-// This filter updates the appropriate piece by requesting the piece from
-// process 0.  Process 0 always updates all of the data.  It is important that
-// Execute get called on all processes, otherwise the filter will deadlock.
+// This filter can be used to redistribute data from producers that can't
+// produce data in parallel. All data is produced on first process and
+// the distributed to others using the multiprocess controller.
+//
+// Note that this class is legacy. The superclass does all the work and
+// can be used directly instead.
 
 
 #ifndef __vtkTransmitImageDataPiece_h
 #define __vtkTransmitImageDataPiece_h
 
 #include "vtkFiltersParallelImagingModule.h" // For export macro
-#include "vtkImageAlgorithm.h"
+#include "vtkTransmitStructuredDataPiece.h"
 
 class vtkMultiProcessController;
 
-class VTKFILTERSPARALLELIMAGING_EXPORT vtkTransmitImageDataPiece : public vtkImageAlgorithm
+class VTKFILTERSPARALLELIMAGING_EXPORT vtkTransmitImageDataPiece : public vtkTransmitStructuredDataPiece
 {
 public:
   static vtkTransmitImageDataPiece *New();
-  vtkTypeMacro(vtkTransmitImageDataPiece, vtkImageAlgorithm);
+  vtkTypeMacro(vtkTransmitImageDataPiece, vtkTransmitStructuredDataPiece);
   void PrintSelf(ostream& os, vtkIndent indent);
 
-  // Description:
-  // By defualt this filter uses the global controller,
-  // but this method can be used to set another instead.
-  virtual void SetController(vtkMultiProcessController*);
-  vtkGetObjectMacro(Controller, vtkMultiProcessController);
-
-  // Description:
-  // Turn on/off creating ghost cells (on by default).
-  vtkSetMacro(CreateGhostCells, int);
-  vtkGetMacro(CreateGhostCells, int);
-  vtkBooleanMacro(CreateGhostCells, int);
-
 protected:
   vtkTransmitImageDataPiece();
   ~vtkTransmitImageDataPiece();
 
-  // Data generation method
-  virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *);
-  void RootExecute(vtkImageData *input, vtkImageData *output,
-                   vtkInformation *outInfo);
-  void SatelliteExecute(int procId, vtkImageData *output,
-                        vtkInformation *outInfo);
-  virtual int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *);
-  virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *);
-
-  int CreateGhostCells;
-  vtkMultiProcessController *Controller;
-
 private:
   vtkTransmitImageDataPiece(const vtkTransmitImageDataPiece&); // Not implemented
   void operator=(const vtkTransmitImageDataPiece&); // Not implemented
diff --git a/IO/ParallelXML/module.cmake b/IO/ParallelXML/module.cmake
index b20e3b8716aa0cf357722a2e478ef49d1619a989..16b25838a5aa8721ef33590754372b51d4b63abc 100644
--- a/IO/ParallelXML/module.cmake
+++ b/IO/ParallelXML/module.cmake
@@ -6,4 +6,6 @@ vtk_module(vtkIOParallelXML
     vtkParallelCore
   PRIVATE_DEPENDS
     vtksys
+  TEST_DEPENDS
+    vtkParallelMPI
   )