<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/
/* $Id$ */

//-----------------------------------------------------------------------------
/// \class AliMFTGeometry
///
/// Geometry mananger for the MFT
///
// author Raphael Tieulent <raphael.tieulent@cern.ch>
//-----------------------------------------------------------------------------

#include "TSystem.h"
#include "TGeoManager.h"
#include "TGeoVolume.h"

#include "AliMFTGeometry.h"
#include "AliMFTConstants.h"
#include "AliMFTGeometryBuilder.h"
#include "AliMFTSegmentation.h"
#include "AliMFTHalfSegmentation.h"
#include "AliMFTHalfDiskSegmentation.h"
#include "AliMFTLadderSegmentation.h"
#include "AliMFTChipSegmentation.h"
#include "AliLog.h"

/// \cond CLASSIMP
ClassImp(AliMFTGeometry);
/// \endcond

const Double_t AliMFTGeometry::kSensorLength=3.; //[cm]
const Double_t AliMFTGeometry::kSensorHeight=1.5; //[cm]
const Double_t AliMFTGeometry::kXPixelPitch=29.250e-4; // 29.15 micron // TODO : Check that
const Double_t AliMFTGeometry::kYPixelPitch=26.880e-4; // 26.88 micron // TODO : Check that
const Double_t AliMFTGeometry::kSensorMargin=29.120e-4; // 29.12 micron // TODO : Check that

const Double_t AliMFTGeometry::kSensorActiveWidth  = kNPixelX * kXPixelPitch; //[cm]
const Double_t AliMFTGeometry::kSensorActiveHeight = kNPixelY * kYPixelPitch; //[cm]

const Double_t AliMFTGeometry::kSensorInterspace = 0.01; //[cm]  Offset between two adjacent chip on a ladder
const Double_t AliMFTGeometry::kSensorSideOffset = 0.04; // [cm] Side Offset between the ladder edge and the chip edge
const Double_t AliMFTGeometry::kSensorTopOffset = 0.04; // [cm] Top Offset between the ladder edge and the chip edge
const Double_t AliMFTGeometry::kLadderOffsetToEnd = 4.7; // [cm] Offset between the last Chip and the end of the ladder toward the DAQ connector
const Double_t AliMFTGeometry::kSensorThickness = 50.e-4; // 50 microns

const Double_t AliMFTGeometry::fHeightActive = 1.3;
const Double_t AliMFTGeometry::fHeightReadout = 0.2;

// Allmost everything you wanted to know about the FPC
const Double_t AliMFTGeometry::kLineWidth= 100.e-4;         // line width, 100 microns
const Double_t AliMFTGeometry::kVarnishThickness= 20.e-4;   // 20 micron
const Double_t AliMFTGeometry::kAluThickness = 25.e-4;      // 25 microns
const Double_t AliMFTGeometry::kKaptonThickness = 75.e-4;   // 75 microns
const Double_t AliMFTGeometry::kFlexThickness = kKaptonThickness + 2*kAluThickness + 2*kVarnishThickness; // total thickness of a FPC
const Double_t AliMFTGeometry::kFlexHeight = 1.68;
const Double_t AliMFTGeometry::kClearance=300.e-4;      // 300 microns clearance without any conducting metal all around the FPC
const Double_t AliMFTGeometry::kRadiusHole1=0.125;      // diameter of the FPC crew, closest to the FPC electric connector
const Double_t AliMFTGeometry::kRadiusHole2=0.1;        // diameter of the FPC pin locator, after the previous hole crew
const Double_t AliMFTGeometry::kHoleShift1=2.8;        // shift of the FPC crew
const Double_t AliMFTGeometry::kHoleShift2=3.6;        // shift of the FPC pin locator
const Double_t AliMFTGeometry::kConnectorOffset=0.4;    // distance between the connector and the start of the FPC
const Double_t AliMFTGeometry::kCapacitorDx=0.05;
const Double_t AliMFTGeometry::kCapacitorDy=0.1;
const Double_t AliMFTGeometry::kCapacitorDz=0.05;
const Double_t AliMFTGeometry::kConnectorLength=0.1;
const Double_t AliMFTGeometry::kConnectorWidth=0.025;
const Double_t AliMFTGeometry::kConnectorHeight=0.1;
const Double_t AliMFTGeometry::kConnectorThickness=0.01;
const Double_t AliMFTGeometry::kShiftDDGNDline=0.4; // positionning of the line to separate AVDD/DVDD et AGND/DGND on the FPC
const Double_t AliMFTGeometry::kShiftline=0.025; // positionning of the line along the FPC side
const Double_t AliMFTGeometry::kEpsilon=0.0001; // to see the removed volumes produced by TGeoSubtraction
const Double_t AliMFTGeometry::kRohacell=-0.001; // to modify the thickness of the rohacell

const Double_t AliMFTGeometry::kGlueThickness=50.e-4; // 50 microns
const Double_t AliMFTGeometry::kGlueEdge=300.e-4; // in case the glue is not spreaded on the whole surface of the sensor

//____________________________________________________________________

AliMFTGeometry* AliMFTGeometry::fgInstance = 0;

//____________________________________________________________________
/// \brief Singleton access
AliMFTGeometry*
AliMFTGeometry::Instance()
{
  if (!fgInstance) fgInstance = new AliMFTGeometry("MFT");
  return fgInstance;
}

//____________________________________________________________________
/// \brief Constructor
AliMFTGeometry::AliMFTGeometry()
: AliGeometry("MFT", "Muon Forward Tracker"),
fBuilder(NULL),
fSegmentation(NULL),
fSensorVolumeId(0)
{

}

//____________________________________________________________________
/// \brief Default Constructor
AliMFTGeometry::AliMFTGeometry(const char* )
: AliGeometry("MFT", "Muon Forward Tracker"),
fBuilder(NULL),
fSegmentation(NULL),
fSensorVolumeId(0)
{

}
//____________________________________________________________________

AliMFTGeometry::~AliMFTGeometry() {
  delete fBuilder;
  delete fSegmentation;
}

//____________________________________________________________________
/// \brief Builf both the Virtual segmentation and the real volumes
/// Real part is delegates to AliMFTGeometryBuilder class
void AliMFTGeometry::Build()
{
  LoadSegmentation();

  if (!fBuilder) fBuilder = new AliMFTGeometryBuilder();
  fBuilder->BuildGeometry();
  delete fBuilder;

}
//____________________________________________________________________
/// \brief Creates the virtual Segmentation from the XML file
/// $(ALICE_ROOT)/ITSMFT/MFT/data/AliMFTGeometry.xml
void AliMFTGeometry::LoadSegmentation() {

  if(!fSegmentation) fSegmentation = new AliMFTSegmentation(gSystem->ExpandPathName("$(ALICE_ROOT)/ITSMFT/MFT/data/AliMFTGeometry.xml" ));

}
//____________________________________________________________________
/// \brief Returns the object Unique ID
/// \param [in] type: Type of the object (see AliMFTGeometry::ObjectTypes)
/// \param [in] half: Half-MFT ID
/// \param [in] disk: Half-Disk ID
/// \param [in] ladder: Ladder ID
/// \param [in] chip: Sensor ID

UInt_t AliMFTGeometry::GetObjectID(ObjectTypes type, Int_t half, Int_t disk, Int_t ladder, Int_t chip) const{

  UInt_t uniqueID = (type<<14) +  (half<<13) + (disk<<10) + (ladder<<4) + chip;

  return uniqueID;
}
//____________________________________________________________________
/// \brief Returns the pixel ID corresponding to a hit at (x,y,z) in the ALICE global frame
///
/// \param [in] xHit Double_t : x Position of the Hit
/// \param [in] yHit Double_t : y Position of the Hit
/// \param [in] zHit Double_t : z Position of the Hit
/// \param [in] detElemID Int_t : Sensor Unique ID in which the hit occured
///
/// \param [out] xPixel Int_t : x position of the pixel hit on the sensor matrix
/// \param [out] yPixel Int_t : y position of the pixel hit on the sensor matrix
/// \retval <kTRUE> if hit into the active part of the sensor
/// \retval <kFALSE> if hit outside the active part

Bool_t AliMFTGeometry::Hit2PixelID(Double_t xHit, Double_t yHit, Double_t zHit, Int_t detElemID, Int_t &xPixel, Int_t &yPixel) const{

  return (fSegmentation->Hit2PixelID(xHit, yHit, zHit,
                                     GetHalfMFTID(detElemID), GetHalfDiskID(detElemID), GetLadderID(detElemID), GetSensorID(detElemID),
                                     xPixel,  yPixel));
}

//____________________________________________________________________
/// \brief Returns the center of the pixel position in the ALICE global frame
///
/// \param [in] xPixel Int_t : x position of the pixel hit on the sensor matrix
/// \param [in] yPixel Int_t : y position of the pixel hit on the sensor matrix
/// \param [in] detElemID Int_t : Sensor Unique ID in which the hit occured
/// \param [out] xCenter,yCenter,zCenter Double_t : (x,y,z) Position of the Hit in ALICE global frame

void AliMFTGeometry::GetPixelCenter(Int_t xPixel, Int_t yPixel, Int_t detElemID, Double_t &xCenter, Double_t &yCenter, Double_t &zCenter ) const{

  Double_t local[3];
  local[0] = (0.5+xPixel) * AliMFTConstants::kXPixelPitch + AliMFTConstants::kSensorMargin;
  local[1] = (0.5+yPixel) * AliMFTConstants::kYPixelPitch + (AliMFTConstants::kSensorHeight-AliMFTConstants::kSensorActiveHeight+ AliMFTConstants::kSensorMargin);
  local[2] = AliMFTConstants::kSensorThickness/2.;

  Double_t master[3];

  AliMFTHalfSegmentation * halfSeg = fSegmentation->GetHalf(GetHalfMFTID(detElemID));
  AliMFTHalfDiskSegmentation * diskSeg = halfSeg->GetHalfDisk(GetHalfDiskID(detElemID));
  AliMFTLadderSegmentation * ladderSeg = diskSeg->GetLadder(GetLadderID(detElemID));
  AliMFTChipSegmentation * chipSeg = ladderSeg->GetSensor(GetSensorID(detElemID));

  chipSeg->GetTransformation()->LocalToMaster(local, master);
  for (int i=0; i<3; i++) local[i] = master[i];
  ladderSeg->GetTransformation()->LocalToMaster(local, master);
  for (int i=0; i<3; i++) local[i] = master[i];
  diskSeg->GetTransformation()->LocalToMaster(local, master);
  for (int i=0; i<3; i++) local[i] = master[i];
  halfSeg->GetTransformation()->LocalToMaster(local, master);

  xCenter = master[0];
  yCenter = master[1];
  zCenter = master[2];

}
//____________________________________________________________________
/// \brief Returns the number of sensors on the entire disk (top+bottom)
/// \param [in] diskId Int_t: Disk ID = [0,4]
Int_t AliMFTGeometry::GetDiskNSensors(Int_t diskId) const{

  Int_t nSensors = 0;
  for (int iHalf=0; iHalf<2; iHalf++) {
    AliMFTHalfDiskSegmentation * diskSeg = fSegmentation->GetHalf(iHalf)->GetHalfDisk(diskId);
    if(diskSeg) nSensors += diskSeg->GetNChips();

  }
  return nSensors;
}

//____________________________________________________________________
/// \brief Returns the local ID of the sensor on the disk
/// \param [in] detElemID Int_t: Sensor Unique ID

Int_t AliMFTGeometry::GetDetElemLocalID(Int_t detElemID) const{

  return  fSegmentation->GetDetElemLocalID(GetHalfMFTID(detElemID), GetHalfDiskID(detElemID), GetLadderID(detElemID), GetSensorID(detElemID));

}

<commit_msg>New glue thickness and encapsulation layers (glue and kapton)<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/
/* $Id$ */

//-----------------------------------------------------------------------------
/// \class AliMFTGeometry
///
/// Geometry mananger for the MFT
///
// author Raphael Tieulent <raphael.tieulent@cern.ch>
//-----------------------------------------------------------------------------

#include "TSystem.h"
#include "TGeoManager.h"
#include "TGeoVolume.h"

#include "AliMFTGeometry.h"
#include "AliMFTConstants.h"
#include "AliMFTGeometryBuilder.h"
#include "AliMFTSegmentation.h"
#include "AliMFTHalfSegmentation.h"
#include "AliMFTHalfDiskSegmentation.h"
#include "AliMFTLadderSegmentation.h"
#include "AliMFTChipSegmentation.h"
#include "AliLog.h"

/// \cond CLASSIMP
ClassImp(AliMFTGeometry);
/// \endcond

const Double_t AliMFTGeometry::kSensorLength=3.; //[cm]
const Double_t AliMFTGeometry::kSensorHeight=1.5; //[cm]
const Double_t AliMFTGeometry::kXPixelPitch=29.250e-4; // 29.15 micron // TODO : Check that
const Double_t AliMFTGeometry::kYPixelPitch=26.880e-4; // 26.88 micron // TODO : Check that
const Double_t AliMFTGeometry::kSensorMargin=29.120e-4; // 29.12 micron // TODO : Check that

const Double_t AliMFTGeometry::kSensorActiveWidth  = kNPixelX * kXPixelPitch; //[cm]
const Double_t AliMFTGeometry::kSensorActiveHeight = kNPixelY * kYPixelPitch; //[cm]

const Double_t AliMFTGeometry::kSensorInterspace = 0.01; //[cm]  Offset between two adjacent chip on a ladder
const Double_t AliMFTGeometry::kSensorSideOffset = 0.04; // [cm] Side Offset between the ladder edge and the chip edge
const Double_t AliMFTGeometry::kSensorTopOffset = 0.04; // [cm] Top Offset between the ladder edge and the chip edge
const Double_t AliMFTGeometry::kLadderOffsetToEnd = 4.7; // [cm] Offset between the last Chip and the end of the ladder toward the DAQ connector
const Double_t AliMFTGeometry::kSensorThickness = 50.e-4; // 50 microns

const Double_t AliMFTGeometry::fHeightActive = 1.3;
const Double_t AliMFTGeometry::fHeightReadout = 0.2;

// Allmost everything you wanted to know about the FPC
const Double_t AliMFTGeometry::kLineWidth= 100.e-4;         // line width, 100 microns
const Double_t AliMFTGeometry::kVarnishThickness= 45.e-4;   // 20 micron FPC + 25 microns of glue for encapsulation
const Double_t AliMFTGeometry::kAluThickness = 25.e-4;      // 25 microns
const Double_t AliMFTGeometry::kKaptonThickness = 88.e-4;   // 75 microns FPC + 13 microns of kapton for encapsulation
const Double_t AliMFTGeometry::kFlexThickness = kKaptonThickness + 2*kAluThickness + 2*kVarnishThickness; // total thickness of a FPC
const Double_t AliMFTGeometry::kFlexHeight = 1.68;
const Double_t AliMFTGeometry::kClearance=300.e-4;      // 300 microns clearance without any conducting metal all around the FPC
const Double_t AliMFTGeometry::kRadiusHole1=0.125;      // diameter of the FPC crew, closest to the FPC electric connector
const Double_t AliMFTGeometry::kRadiusHole2=0.1;        // diameter of the FPC pin locator, after the previous hole crew
const Double_t AliMFTGeometry::kHoleShift1=2.8;        // shift of the FPC crew
const Double_t AliMFTGeometry::kHoleShift2=3.6;        // shift of the FPC pin locator
const Double_t AliMFTGeometry::kConnectorOffset=0.4;    // distance between the connector and the start of the FPC
const Double_t AliMFTGeometry::kCapacitorDx=0.05;
const Double_t AliMFTGeometry::kCapacitorDy=0.1;
const Double_t AliMFTGeometry::kCapacitorDz=0.05;
const Double_t AliMFTGeometry::kConnectorLength=0.1;
const Double_t AliMFTGeometry::kConnectorWidth=0.025;
const Double_t AliMFTGeometry::kConnectorHeight=0.1;
const Double_t AliMFTGeometry::kConnectorThickness=0.01;
const Double_t AliMFTGeometry::kShiftDDGNDline=0.4; // positionning of the line to separate AVDD/DVDD et AGND/DGND on the FPC
const Double_t AliMFTGeometry::kShiftline=0.025; // positionning of the line along the FPC side
const Double_t AliMFTGeometry::kEpsilon=0.0001; // to see the removed volumes produced by TGeoSubtraction
const Double_t AliMFTGeometry::kRohacell=-0.001; // to modify the thickness of the rohacell

const Double_t AliMFTGeometry::kGlueThickness=100.e-4; // 100 microns of SE4445 to be confirmed
const Double_t AliMFTGeometry::kGlueEdge=300.e-4; // in case the glue is not spreaded on the whole surface of the sensor

//____________________________________________________________________

AliMFTGeometry* AliMFTGeometry::fgInstance = 0;

//____________________________________________________________________
/// \brief Singleton access
AliMFTGeometry*
AliMFTGeometry::Instance()
{
  if (!fgInstance) fgInstance = new AliMFTGeometry("MFT");
  return fgInstance;
}

//____________________________________________________________________
/// \brief Constructor
AliMFTGeometry::AliMFTGeometry()
: AliGeometry("MFT", "Muon Forward Tracker"),
fBuilder(NULL),
fSegmentation(NULL),
fSensorVolumeId(0)
{

}

//____________________________________________________________________
/// \brief Default Constructor
AliMFTGeometry::AliMFTGeometry(const char* )
: AliGeometry("MFT", "Muon Forward Tracker"),
fBuilder(NULL),
fSegmentation(NULL),
fSensorVolumeId(0)
{

}
//____________________________________________________________________

AliMFTGeometry::~AliMFTGeometry() {
  delete fBuilder;
  delete fSegmentation;
}

//____________________________________________________________________
/// \brief Builf both the Virtual segmentation and the real volumes
/// Real part is delegates to AliMFTGeometryBuilder class
void AliMFTGeometry::Build()
{
  LoadSegmentation();

  if (!fBuilder) fBuilder = new AliMFTGeometryBuilder();
  fBuilder->BuildGeometry();
  delete fBuilder;

}
//____________________________________________________________________
/// \brief Creates the virtual Segmentation from the XML file
/// $(ALICE_ROOT)/ITSMFT/MFT/data/AliMFTGeometry.xml
void AliMFTGeometry::LoadSegmentation() {

  if(!fSegmentation) fSegmentation = new AliMFTSegmentation(gSystem->ExpandPathName("$(ALICE_ROOT)/ITSMFT/MFT/data/AliMFTGeometry.xml" ));

}
//____________________________________________________________________
/// \brief Returns the object Unique ID
/// \param [in] type: Type of the object (see AliMFTGeometry::ObjectTypes)
/// \param [in] half: Half-MFT ID
/// \param [in] disk: Half-Disk ID
/// \param [in] ladder: Ladder ID
/// \param [in] chip: Sensor ID

UInt_t AliMFTGeometry::GetObjectID(ObjectTypes type, Int_t half, Int_t disk, Int_t ladder, Int_t chip) const{

  UInt_t uniqueID = (type<<14) +  (half<<13) + (disk<<10) + (ladder<<4) + chip;

  return uniqueID;
}
//____________________________________________________________________
/// \brief Returns the pixel ID corresponding to a hit at (x,y,z) in the ALICE global frame
///
/// \param [in] xHit Double_t : x Position of the Hit
/// \param [in] yHit Double_t : y Position of the Hit
/// \param [in] zHit Double_t : z Position of the Hit
/// \param [in] detElemID Int_t : Sensor Unique ID in which the hit occured
///
/// \param [out] xPixel Int_t : x position of the pixel hit on the sensor matrix
/// \param [out] yPixel Int_t : y position of the pixel hit on the sensor matrix
/// \retval <kTRUE> if hit into the active part of the sensor
/// \retval <kFALSE> if hit outside the active part

Bool_t AliMFTGeometry::Hit2PixelID(Double_t xHit, Double_t yHit, Double_t zHit, Int_t detElemID, Int_t &xPixel, Int_t &yPixel) const{

  return (fSegmentation->Hit2PixelID(xHit, yHit, zHit,
                                     GetHalfMFTID(detElemID), GetHalfDiskID(detElemID), GetLadderID(detElemID), GetSensorID(detElemID),
                                     xPixel,  yPixel));
}

//____________________________________________________________________
/// \brief Returns the center of the pixel position in the ALICE global frame
///
/// \param [in] xPixel Int_t : x position of the pixel hit on the sensor matrix
/// \param [in] yPixel Int_t : y position of the pixel hit on the sensor matrix
/// \param [in] detElemID Int_t : Sensor Unique ID in which the hit occured
/// \param [out] xCenter,yCenter,zCenter Double_t : (x,y,z) Position of the Hit in ALICE global frame

void AliMFTGeometry::GetPixelCenter(Int_t xPixel, Int_t yPixel, Int_t detElemID, Double_t &xCenter, Double_t &yCenter, Double_t &zCenter ) const{

  Double_t local[3];
  local[0] = (0.5+xPixel) * AliMFTConstants::kXPixelPitch + AliMFTConstants::kSensorMargin;
  local[1] = (0.5+yPixel) * AliMFTConstants::kYPixelPitch + (AliMFTConstants::kSensorHeight-AliMFTConstants::kSensorActiveHeight+ AliMFTConstants::kSensorMargin);
  local[2] = AliMFTConstants::kSensorThickness/2.;

  Double_t master[3];

  AliMFTHalfSegmentation * halfSeg = fSegmentation->GetHalf(GetHalfMFTID(detElemID));
  AliMFTHalfDiskSegmentation * diskSeg = halfSeg->GetHalfDisk(GetHalfDiskID(detElemID));
  AliMFTLadderSegmentation * ladderSeg = diskSeg->GetLadder(GetLadderID(detElemID));
  AliMFTChipSegmentation * chipSeg = ladderSeg->GetSensor(GetSensorID(detElemID));

  chipSeg->GetTransformation()->LocalToMaster(local, master);
  for (int i=0; i<3; i++) local[i] = master[i];
  ladderSeg->GetTransformation()->LocalToMaster(local, master);
  for (int i=0; i<3; i++) local[i] = master[i];
  diskSeg->GetTransformation()->LocalToMaster(local, master);
  for (int i=0; i<3; i++) local[i] = master[i];
  halfSeg->GetTransformation()->LocalToMaster(local, master);

  xCenter = master[0];
  yCenter = master[1];
  zCenter = master[2];

}
//____________________________________________________________________
/// \brief Returns the number of sensors on the entire disk (top+bottom)
/// \param [in] diskId Int_t: Disk ID = [0,4]
Int_t AliMFTGeometry::GetDiskNSensors(Int_t diskId) const{

  Int_t nSensors = 0;
  for (int iHalf=0; iHalf<2; iHalf++) {
    AliMFTHalfDiskSegmentation * diskSeg = fSegmentation->GetHalf(iHalf)->GetHalfDisk(diskId);
    if(diskSeg) nSensors += diskSeg->GetNChips();

  }
  return nSensors;
}

//____________________________________________________________________
/// \brief Returns the local ID of the sensor on the disk
/// \param [in] detElemID Int_t: Sensor Unique ID

Int_t AliMFTGeometry::GetDetElemLocalID(Int_t detElemID) const{

  return  fSegmentation->GetDetElemLocalID(GetHalfMFTID(detElemID), GetHalfDiskID(detElemID), GetLadderID(detElemID), GetSensorID(detElemID));

}

<|endoftext|>


<commit_before><commit_msg>single metric value in the computation of measure[Tri/Tet]Quality], implemented.<commit_after><|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkImageContinuousErode3D.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 "vtkImageContinuousErode3D.h"

#include "vtkDataArray.h"
#include "vtkImageData.h"
#include "vtkImageEllipsoidSource.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"

vtkCxxRevisionMacro(vtkImageContinuousErode3D, "1.26");
vtkStandardNewMacro(vtkImageContinuousErode3D);

//----------------------------------------------------------------------------
// Construct an instance of vtkImageContinuousErode3D fitler.
// By default zero values are eroded.
vtkImageContinuousErode3D::vtkImageContinuousErode3D()
{
  this->HandleBoundaries = 1;
  this->KernelSize[0] = 1;
  this->KernelSize[1] = 1;
  this->KernelSize[2] = 1;

  this->Ellipse = vtkImageEllipsoidSource::New();
  // Setup the Ellipse to default size
  this->SetKernelSize(1, 1, 1);
}

//----------------------------------------------------------------------------
vtkImageContinuousErode3D::~vtkImageContinuousErode3D()
{
  if (this->Ellipse)
    {
    this->Ellipse->Delete();
    this->Ellipse = NULL;
    }
}

//----------------------------------------------------------------------------
void vtkImageContinuousErode3D::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
  if (this->InputScalarsSelection)
    {
    os << indent << "InputScalarsSelection: "
       << this->InputScalarsSelection << endl;
    }
}

//----------------------------------------------------------------------------
// This method sets the size of the neighborhood.  It also sets the
// default middle of the neighborhood and computes the eliptical foot print.
void vtkImageContinuousErode3D::SetKernelSize(int size0, int size1, int size2)
{
  int modified = 0;

  if (this->KernelSize[0] != size0)
    {
    modified = 1;
    this->KernelSize[0] = size0;
    this->KernelMiddle[0] = size0 / 2;
    }
  if (this->KernelSize[1] != size1)
    {
    modified = 1;
    this->KernelSize[1] = size1;
    this->KernelMiddle[1] = size1 / 2;
    }
  if (this->KernelSize[2] != size2)
    {
    modified = 1;
    this->KernelSize[2] = size2;
    this->KernelMiddle[2] = size2 / 2;
    }

  if (modified)
    {
    this->Modified();
    this->Ellipse->SetWholeExtent(0, this->KernelSize[0]-1,
                                  0, this->KernelSize[1]-1,
                                  0, this->KernelSize[2]-1);
    this->Ellipse->SetCenter((float)(this->KernelSize[0]-1)*0.5,
                             (float)(this->KernelSize[1]-1)*0.5,
                             (float)(this->KernelSize[2]-1)*0.5);
    this->Ellipse->SetRadius((float)(this->KernelSize[0])*0.5,
                             (float)(this->KernelSize[1])*0.5,
                             (float)(this->KernelSize[2])*0.5);
    // make sure scalars have been allocated (needed if multithreaded is used)
    this->Ellipse->GetOutput()->SetUpdateExtent(0, this->KernelSize[0]-1,
                                                0, this->KernelSize[1]-1,
                                                0, this->KernelSize[2]-1);
    this->Ellipse->GetOutput()->Update();
    }
}

//----------------------------------------------------------------------------
// This templated function executes the filter on any region,
// whether it needs boundary checking or not.
// If the filter needs to be faster, the function could be duplicated
// for strictly center (no boundary ) processing.
template <class T>
void vtkImageContinuousErode3DExecute(vtkImageContinuousErode3D *self,
                                      vtkImageData *mask,
                                      vtkImageData *inData, T *inPtr,
                                      vtkImageData *outData,
                                      int *outExt, T *outPtr, int id,
                                      const char* inputScalars)
{
  int *kernelMiddle, *kernelSize;
  // For looping though output (and input) pixels.
  int outMin0, outMax0, outMin1, outMax1, outMin2, outMax2;
  int outIdx0, outIdx1, outIdx2;
  int inInc0, inInc1, inInc2;
  int outInc0, outInc1, outInc2;
  T *inPtr0, *inPtr1, *inPtr2;
  T *outPtr0, *outPtr1, *outPtr2;
  int numComps, outIdxC;
  // For looping through hood pixels
  int hoodMin0, hoodMax0, hoodMin1, hoodMax1, hoodMin2, hoodMax2;
  int hoodIdx0, hoodIdx1, hoodIdx2;
  T *hoodPtr0, *hoodPtr1, *hoodPtr2;
  // For looping through the mask.
  unsigned char *maskPtr, *maskPtr0, *maskPtr1, *maskPtr2;
  int maskInc0, maskInc1, maskInc2;
  // The extent of the whole input image
  int inImageMin0, inImageMin1, inImageMin2;
  int inImageMax0, inImageMax1, inImageMax2;
  // to compute the range
  T pixelMin;
  unsigned long count = 0;
  unsigned long target;
  vtkDataArray *inArray;
  int *inExt = inData->GetExtent();

  inArray = inData->GetPointData()->GetScalars(inputScalars);

  // Get information to march through data
  inData->GetIncrements(inInc0, inInc1, inInc2);
  self->GetInput()->GetWholeExtent(inImageMin0, inImageMax0, inImageMin1,
                                   inImageMax1, inImageMin2, inImageMax2);
  outData->GetIncrements(outInc0, outInc1, outInc2);
  outMin0 = outExt[0];   outMax0 = outExt[1];
  outMin1 = outExt[2];   outMax1 = outExt[3];
  outMin2 = outExt[4];   outMax2 = outExt[5];
  numComps = outData->GetNumberOfScalarComponents();

  // Get ivars of this object (easier than making friends)
  kernelSize = self->GetKernelSize();
  kernelMiddle = self->GetKernelMiddle();
  hoodMin0 = - kernelMiddle[0];
  hoodMin1 = - kernelMiddle[1];
  hoodMin2 = - kernelMiddle[2];
  hoodMax0 = hoodMin0 + kernelSize[0] - 1;
  hoodMax1 = hoodMin1 + kernelSize[1] - 1;
  hoodMax2 = hoodMin2 + kernelSize[2] - 1;

  // Setup mask info
  maskPtr = (unsigned char *)(mask->GetScalarPointer());
  mask->GetIncrements(maskInc0, maskInc1, maskInc2);

  // in and out should be marching through corresponding pixels.
  inPtr = (T *)(inArray->GetVoidPointer((outMin0-inExt[0])*inInc0 +
                                        (outMin1-inExt[2])*inInc1 +
                                        (outMin2-inExt[4])*inInc2));

  target = (unsigned long)(numComps*(outMax2-outMin2+1)*
                           (outMax1-outMin1+1)/50.0);
  target++;

  // loop through components
  for (outIdxC = 0; outIdxC < numComps; ++outIdxC)
    {
    // loop through pixels of output
    outPtr2 = outPtr;
    inPtr2 = inPtr;
    for (outIdx2 = outMin2; outIdx2 <= outMax2; ++outIdx2)
      {
      outPtr1 = outPtr2;
      inPtr1 = inPtr2;
      for (outIdx1 = outMin1;
           !self->AbortExecute && outIdx1 <= outMax1; ++outIdx1)
        {
        if (!id)
          {
          if (!(count%target))
            {
            self->UpdateProgress(count/(50.0*target));
            }
          count++;
          }
        outPtr0 = outPtr1;
        inPtr0 = inPtr1;
        for (outIdx0 = outMin0; outIdx0 <= outMax0; ++outIdx0)
          {

          // Find min
          pixelMin = *inPtr0;
          // loop through neighborhood pixels
          // as sort of a hack to handle boundaries,
          // input pointer will be marching through data that does not exist.
          hoodPtr2 = inPtr0 - kernelMiddle[0] * inInc0
            - kernelMiddle[1] * inInc1 - kernelMiddle[2] * inInc2;
          maskPtr2 = maskPtr;
          for (hoodIdx2 = hoodMin2; hoodIdx2 <= hoodMax2; ++hoodIdx2)
            {
            hoodPtr1 = hoodPtr2;
            maskPtr1 = maskPtr2;
            for (hoodIdx1 = hoodMin1; hoodIdx1 <= hoodMax1; ++hoodIdx1)
              {
              hoodPtr0 = hoodPtr1;
              maskPtr0 = maskPtr1;
              for (hoodIdx0 = hoodMin0; hoodIdx0 <= hoodMax0; ++hoodIdx0)
                {
                // A quick but rather expensive way to handle boundaries
                if ( outIdx0 + hoodIdx0 >= inImageMin0 &&
                     outIdx0 + hoodIdx0 <= inImageMax0 &&
                     outIdx1 + hoodIdx1 >= inImageMin1 &&
                     outIdx1 + hoodIdx1 <= inImageMax1 &&
                     outIdx2 + hoodIdx2 >= inImageMin2 &&
                     outIdx2 + hoodIdx2 <= inImageMax2)
                  {
                  if (*maskPtr0)
                    {
                    if (*hoodPtr0 < pixelMin)
                      {
                      pixelMin = *hoodPtr0;
                      }
                    }
                  }

                hoodPtr0 += inInc0;
                maskPtr0 += maskInc0;
                }
              hoodPtr1 += inInc1;
              maskPtr1 += maskInc1;
              }
            hoodPtr2 += inInc2;
            maskPtr2 += maskInc2;
            }
          *outPtr0 = pixelMin;

          inPtr0 += inInc0;
          outPtr0 += outInc0;
          }
        inPtr1 += inInc1;
        outPtr1 += outInc1;
        }
      inPtr2 += inInc2;
      outPtr2 += outInc2;
      }
    ++inPtr;
    ++outPtr;
    }
}

//----------------------------------------------------------------------------
// This method contains the first switch statement that calls the correct
// templated function for the input and output Data types.
// It hanldes image boundaries, so the image does not shrink.
void vtkImageContinuousErode3D::ThreadedExecute(vtkImageData *inData,
                                                vtkImageData *outData,
                                                int outExt[6], int id)
{
  int inExt[6];
  this->ComputeInputUpdateExtent(inExt,outExt);
  void *inPtr;
  void *outPtr = outData->GetScalarPointerForExtent(outExt);
  vtkImageData *mask;
  vtkDataArray *inArray;

  inArray = inData->GetPointData()->GetScalars(this->InputScalarsSelection);
  // The inPtr is reset anyway, so just get the id 0 pointer.
  inPtr = inArray->GetVoidPointer(0);

  // Error checking on mask
  this->Ellipse->GetOutput()->Update();
  mask = this->Ellipse->GetOutput();
  if (mask->GetScalarType() != VTK_UNSIGNED_CHAR)
    {
    vtkErrorMacro(<< "Execute: mask has wrong scalar type");
    return;
    }

  // this filter expects the output type to be same as input
  if (outData->GetScalarType() != inArray->GetDataType())
    {
    vtkErrorMacro(<< "Execute: output ScalarType, "
      << vtkImageScalarTypeNameMacro(outData->GetScalarType())
      << " must match input array data type");
    return;
    }

  switch (inArray->GetDataType())
    {
    vtkTemplateMacro9(vtkImageContinuousErode3DExecute, this, mask,
                      inData, (VTK_TT *)(inPtr), outData, outExt,
                      (VTK_TT *)(outPtr),id, this->InputScalarsSelection);
    default:
      vtkErrorMacro(<< "Execute: Unknown ScalarType");
      return;
    }
}

<commit_msg>new pipeline<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkImageContinuousErode3D.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 "vtkImageContinuousErode3D.h"

#include "vtkDataArray.h"
#include "vtkImageData.h"
#include "vtkImageEllipsoidSource.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"

vtkCxxRevisionMacro(vtkImageContinuousErode3D, "1.26.10.1");
vtkStandardNewMacro(vtkImageContinuousErode3D);

//----------------------------------------------------------------------------
// Construct an instance of vtkImageContinuousErode3D fitler.
// By default zero values are eroded.
vtkImageContinuousErode3D::vtkImageContinuousErode3D()
{
  this->HandleBoundaries = 1;
  this->KernelSize[0] = 1;
  this->KernelSize[1] = 1;
  this->KernelSize[2] = 1;

  this->Ellipse = vtkImageEllipsoidSource::New();
  // Setup the Ellipse to default size
  this->SetKernelSize(1, 1, 1);
}

//----------------------------------------------------------------------------
vtkImageContinuousErode3D::~vtkImageContinuousErode3D()
{
  if (this->Ellipse)
    {
    this->Ellipse->Delete();
    this->Ellipse = NULL;
    }
}

//----------------------------------------------------------------------------
void vtkImageContinuousErode3D::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
  if (this->InputScalarsSelection)
    {
    os << indent << "InputScalarsSelection: "
       << this->InputScalarsSelection << endl;
    }
}

//----------------------------------------------------------------------------
// This method sets the size of the neighborhood.  It also sets the
// default middle of the neighborhood and computes the eliptical foot print.
void vtkImageContinuousErode3D::SetKernelSize(int size0, int size1, int size2)
{
  int modified = 0;

  if (this->KernelSize[0] != size0)
    {
    modified = 1;
    this->KernelSize[0] = size0;
    this->KernelMiddle[0] = size0 / 2;
    }
  if (this->KernelSize[1] != size1)
    {
    modified = 1;
    this->KernelSize[1] = size1;
    this->KernelMiddle[1] = size1 / 2;
    }
  if (this->KernelSize[2] != size2)
    {
    modified = 1;
    this->KernelSize[2] = size2;
    this->KernelMiddle[2] = size2 / 2;
    }

  if (modified)
    {
    this->Modified();
    this->Ellipse->SetWholeExtent(0, this->KernelSize[0]-1,
                                  0, this->KernelSize[1]-1,
                                  0, this->KernelSize[2]-1);
    this->Ellipse->SetCenter((float)(this->KernelSize[0]-1)*0.5,
                             (float)(this->KernelSize[1]-1)*0.5,
                             (float)(this->KernelSize[2]-1)*0.5);
    this->Ellipse->SetRadius((float)(this->KernelSize[0])*0.5,
                             (float)(this->KernelSize[1])*0.5,
                             (float)(this->KernelSize[2])*0.5);
    // make sure scalars have been allocated (needed if multithreaded is used)
    this->Ellipse->GetOutput()->SetUpdateExtent(0, this->KernelSize[0]-1,
                                                0, this->KernelSize[1]-1,
                                                0, this->KernelSize[2]-1);
    this->Ellipse->GetOutput()->Update();
    }
}

//----------------------------------------------------------------------------
// This templated function executes the filter on any region,
// whether it needs boundary checking or not.
// If the filter needs to be faster, the function could be duplicated
// for strictly center (no boundary ) processing.
template <class T>
void vtkImageContinuousErode3DExecute(vtkImageContinuousErode3D *self,
                                      vtkImageData *mask,
                                      vtkImageData *inData,
                                      vtkImageData *outData,
                                      int *outExt, T *outPtr, int id,
                                      const char* inputScalars)
{
  int *kernelMiddle, *kernelSize;
  // For looping though output (and input) pixels.
  int outMin0, outMax0, outMin1, outMax1, outMin2, outMax2;
  int outIdx0, outIdx1, outIdx2;
  int inInc0, inInc1, inInc2;
  int outInc0, outInc1, outInc2;
  T *inPtr, *inPtr0, *inPtr1, *inPtr2;
  T *outPtr0, *outPtr1, *outPtr2;
  int numComps, outIdxC;
  // For looping through hood pixels
  int hoodMin0, hoodMax0, hoodMin1, hoodMax1, hoodMin2, hoodMax2;
  int hoodIdx0, hoodIdx1, hoodIdx2;
  T *hoodPtr0, *hoodPtr1, *hoodPtr2;
  // For looping through the mask.
  unsigned char *maskPtr, *maskPtr0, *maskPtr1, *maskPtr2;
  int maskInc0, maskInc1, maskInc2;
  // The extent of the whole input image
  int inImageMin0, inImageMin1, inImageMin2;
  int inImageMax0, inImageMax1, inImageMax2;
  // to compute the range
  T pixelMin;
  unsigned long count = 0;
  unsigned long target;
  vtkDataArray *inArray;
  int *inExt = inData->GetExtent();

  inArray = inData->GetPointData()->GetScalars(inputScalars);

  // Get information to march through data
  inData->GetIncrements(inInc0, inInc1, inInc2);
  inData->GetWholeExtent(inImageMin0, inImageMax0, inImageMin1,
                         inImageMax1, inImageMin2, inImageMax2);
  outData->GetIncrements(outInc0, outInc1, outInc2);
  outMin0 = outExt[0];   outMax0 = outExt[1];
  outMin1 = outExt[2];   outMax1 = outExt[3];
  outMin2 = outExt[4];   outMax2 = outExt[5];
  numComps = outData->GetNumberOfScalarComponents();

  // Get ivars of this object (easier than making friends)
  kernelSize = self->GetKernelSize();
  kernelMiddle = self->GetKernelMiddle();
  hoodMin0 = - kernelMiddle[0];
  hoodMin1 = - kernelMiddle[1];
  hoodMin2 = - kernelMiddle[2];
  hoodMax0 = hoodMin0 + kernelSize[0] - 1;
  hoodMax1 = hoodMin1 + kernelSize[1] - 1;
  hoodMax2 = hoodMin2 + kernelSize[2] - 1;

  // Setup mask info
  maskPtr = (unsigned char *)(mask->GetScalarPointer());
  mask->GetIncrements(maskInc0, maskInc1, maskInc2);

  // in and out should be marching through corresponding pixels.
  inPtr = (T *)(inArray->GetVoidPointer((outMin0-inExt[0])*inInc0 +
                                        (outMin1-inExt[2])*inInc1 +
                                        (outMin2-inExt[4])*inInc2));

  target = (unsigned long)(numComps*(outMax2-outMin2+1)*
                           (outMax1-outMin1+1)/50.0);
  target++;

  // loop through components
  for (outIdxC = 0; outIdxC < numComps; ++outIdxC)
    {
    // loop through pixels of output
    outPtr2 = outPtr;
    inPtr2 = inPtr;
    for (outIdx2 = outMin2; outIdx2 <= outMax2; ++outIdx2)
      {
      outPtr1 = outPtr2;
      inPtr1 = inPtr2;
      for (outIdx1 = outMin1;
           !self->AbortExecute && outIdx1 <= outMax1; ++outIdx1)
        {
        if (!id)
          {
          if (!(count%target))
            {
            self->UpdateProgress(count/(50.0*target));
            }
          count++;
          }
        outPtr0 = outPtr1;
        inPtr0 = inPtr1;
        for (outIdx0 = outMin0; outIdx0 <= outMax0; ++outIdx0)
          {

          // Find min
          pixelMin = *inPtr0;
          // loop through neighborhood pixels
          // as sort of a hack to handle boundaries,
          // input pointer will be marching through data that does not exist.
          hoodPtr2 = inPtr0 - kernelMiddle[0] * inInc0
            - kernelMiddle[1] * inInc1 - kernelMiddle[2] * inInc2;
          maskPtr2 = maskPtr;
          for (hoodIdx2 = hoodMin2; hoodIdx2 <= hoodMax2; ++hoodIdx2)
            {
            hoodPtr1 = hoodPtr2;
            maskPtr1 = maskPtr2;
            for (hoodIdx1 = hoodMin1; hoodIdx1 <= hoodMax1; ++hoodIdx1)
              {
              hoodPtr0 = hoodPtr1;
              maskPtr0 = maskPtr1;
              for (hoodIdx0 = hoodMin0; hoodIdx0 <= hoodMax0; ++hoodIdx0)
                {
                // A quick but rather expensive way to handle boundaries
                if ( outIdx0 + hoodIdx0 >= inImageMin0 &&
                     outIdx0 + hoodIdx0 <= inImageMax0 &&
                     outIdx1 + hoodIdx1 >= inImageMin1 &&
                     outIdx1 + hoodIdx1 <= inImageMax1 &&
                     outIdx2 + hoodIdx2 >= inImageMin2 &&
                     outIdx2 + hoodIdx2 <= inImageMax2)
                  {
                  if (*maskPtr0)
                    {
                    if (*hoodPtr0 < pixelMin)
                      {
                      pixelMin = *hoodPtr0;
                      }
                    }
                  }

                hoodPtr0 += inInc0;
                maskPtr0 += maskInc0;
                }
              hoodPtr1 += inInc1;
              maskPtr1 += maskInc1;
              }
            hoodPtr2 += inInc2;
            maskPtr2 += maskInc2;
            }
          *outPtr0 = pixelMin;

          inPtr0 += inInc0;
          outPtr0 += outInc0;
          }
        inPtr1 += inInc1;
        outPtr1 += outInc1;
        }
      inPtr2 += inInc2;
      outPtr2 += outInc2;
      }
    ++inPtr;
    ++outPtr;
    }
}

//----------------------------------------------------------------------------
// This method contains the first switch statement that calls the correct
// templated function for the input and output Data types.
// It hanldes image boundaries, so the image does not shrink.
void vtkImageContinuousErode3D::ThreadedExecute(vtkImageData *inData,
                                                vtkImageData *outData,
                                                int outExt[6], int id)
{
  void *outPtr = outData->GetScalarPointerForExtent(outExt);
  vtkImageData *mask;
  vtkDataArray *inArray;

  inArray = inData->GetPointData()->GetScalars(this->InputScalarsSelection);

  // Error checking on mask
  this->Ellipse->GetOutput()->Update();
  mask = this->Ellipse->GetOutput();
  if (mask->GetScalarType() != VTK_UNSIGNED_CHAR)
    {
    vtkErrorMacro(<< "Execute: mask has wrong scalar type");
    return;
    }

  // this filter expects the output type to be same as input
  if (outData->GetScalarType() != inArray->GetDataType())
    {
    vtkErrorMacro(<< "Execute: output ScalarType, "
      << vtkImageScalarTypeNameMacro(outData->GetScalarType())
      << " must match input array data type");
    return;
    }

  switch (inArray->GetDataType())
    {
    vtkTemplateMacro8(vtkImageContinuousErode3DExecute, this, mask,
                      inData, outData, outExt,
                      (VTK_TT *)(outPtr),id, this->InputScalarsSelection);
    default:
      vtkErrorMacro(<< "Execute: Unknown ScalarType");
      return;
    }
}

<|endoftext|>


<commit_before>/*

Copyright (c) 2003-2012, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_PEER_INFO_HPP_INCLUDED
#define TORRENT_PEER_INFO_HPP_INCLUDED

#include "libtorrent/socket.hpp"
#include "libtorrent/deadline_timer.hpp"
#include "libtorrent/peer_id.hpp"
#include "libtorrent/size_type.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/bitfield.hpp"

namespace libtorrent
{
	struct TORRENT_EXPORT peer_info
	{
		enum
		{
			interesting = 0x1,
			choked = 0x2,
			remote_interested = 0x4,
			remote_choked = 0x8,
			supports_extensions = 0x10,
			local_connection = 0x20,
			handshake = 0x40,
			connecting = 0x80,
			queued = 0x100,
			on_parole = 0x200,
			seed = 0x400,
			optimistic_unchoke = 0x800,
			snubbed = 0x1000,
			upload_only = 0x2000,
			endgame_mode = 0x4000,
			holepunched = 0x8000
#ifndef TORRENT_DISABLE_ENCRYPTION
			, rc4_encrypted = 0x100000,
			plaintext_encrypted = 0x200000
#endif
		};

		unsigned int flags;

		enum peer_source_flags
		{
			tracker = 0x1,
			dht = 0x2,
			pex = 0x4,
			lsd = 0x8,
			resume_data = 0x10,
			incoming = 0x20
		};

		int source;

		// bw_idle: the channel is not used
		// bw_limit: the channel is waiting for quota
		// bw_network: the channel is waiting for an async write
		//   or read operation to complete
		// bw_disk: the peer is waiting for the disk io thread
		// this is a bitmask, a peer can wait for network, rate-limiter
		// and disk at the same time!
		enum bw_state { bw_idle = 0, bw_limit = 1, bw_network = 2, bw_disk = 4 };
#ifndef TORRENT_NO_DEPRECATE
		enum bw_state_deprecated { bw_torrent = bw_limit, bw_global = bw_limit };
#endif

		char read_state;
		char write_state;

		tcp::endpoint ip;
		int up_speed;
		int down_speed;
		int payload_up_speed;
		int payload_down_speed;
		size_type total_download;
		size_type total_upload;
		peer_id pid;
		bitfield pieces;
#ifndef TORRENT_NO_DEPRECATE
		int upload_limit;
		int download_limit;
#endif

		// time since last request
		time_duration last_request;

		// time since last download or upload
		time_duration last_active;

		// the time until all blocks in the request
		// queue will be d
		time_duration download_queue_time;
		int queue_bytes;

		// the number of seconds until the current
		// pending request times out
		int request_timeout;

		// the size of the send buffer for this peer, in bytes
		int send_buffer_size;
		// the number bytes that's actually used of the send buffer
		int used_send_buffer;

		int receive_buffer_size;
		int used_receive_buffer;

		// the number of failed hashes for this peer
		int num_hashfails;

#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
		// in case the session settings is set
		// to resolve countries, this is set to
		// the two character country code this
		// peer resides in.
		char country[2];
#endif

#ifndef TORRENT_DISABLE_GEO_IP
		// atonomous system this peer belongs to
		std::string inet_as_name;
		int inet_as;
#endif

#ifndef TORRENT_NO_DEPRECATE
		size_type load_balancing;
#endif

		// this is the number of requests
		// we have sent to this peer
		// that we haven't got a response
		// for yet
		int download_queue_length;

		// the number of block requests that have
		// timed out, and are still in the download
		// queue
		int timed_out_requests;

		// the number of busy requests in the download
		// queue. A budy request is a request for a block
		// we've also requested from a different peer
		int busy_requests;

		// the number of request messages
		// waiting to be sent inside the send buffer
		int requests_in_buffer;

		// the number of requests that is
		// tried to be maintained (this is
		// typically a function of download speed)
		int target_dl_queue_length;

		// this is the number of requests
		// the peer has sent to us
		// that we haven't sent yet
		int upload_queue_length;

		// the number of times this IP
		// has failed to connect
		int failcount;

		// the currently downloading piece
		// if piece index is -1 all associated
		// members are just set to 0
		int downloading_piece_index;
		int downloading_block_index;
		int downloading_progress;
		int downloading_total;

		std::string client;

		enum
		{
			standard_bittorrent = 0,
			web_seed = 1,
			http_seed = 2,
			bittorrent_utp = 3
		};
		int connection_type;

		// approximate peer download rate
		int remote_dl_rate;

		// number of bytes this peer has in
		// the disk write queue
		int pending_disk_bytes;
		// number of outstanding bytes to read
		// from disk
		int pending_disk_read_bytes;

		// numbers used for bandwidth limiting
		int send_quota;
		int receive_quota;

		// estimated rtt to peer, in milliseconds
		int rtt;

		// the number of pieces this peer has
		int num_pieces;

		// the highest transfer rates seen for this peer
		int download_rate_peak;
		int upload_rate_peak;

		// the peers progress
		float progress; // [0, 1]
		int progress_ppm; // [0, 1000000]

		int estimated_reciprocation_rate;

		tcp::endpoint local_endpoint;
	};

	struct TORRENT_EXPORT peer_list_entry
	{
		enum flags_t
		{
			banned = 1
		};

		tcp::endpoint ip;
		int flags;
		boost::uint8_t failcount;
		boost::uint8_t source;
	};

	// defined in policy.cpp
	int source_rank(int source_bitmask);
}

#endif // TORRENT_PEER_INFO_HPP_INCLUDED
<commit_msg>make encryption related enums available even when not building with encryption enabled<commit_after>/*

Copyright (c) 2003-2012, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_PEER_INFO_HPP_INCLUDED
#define TORRENT_PEER_INFO_HPP_INCLUDED

#include "libtorrent/socket.hpp"
#include "libtorrent/deadline_timer.hpp"
#include "libtorrent/peer_id.hpp"
#include "libtorrent/size_type.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/bitfield.hpp"

namespace libtorrent
{
	struct TORRENT_EXPORT peer_info
	{
		enum
		{
			interesting = 0x1,
			choked = 0x2,
			remote_interested = 0x4,
			remote_choked = 0x8,
			supports_extensions = 0x10,
			local_connection = 0x20,
			handshake = 0x40,
			connecting = 0x80,
			queued = 0x100,
			on_parole = 0x200,
			seed = 0x400,
			optimistic_unchoke = 0x800,
			snubbed = 0x1000,
			upload_only = 0x2000,
			endgame_mode = 0x4000,
			holepunched = 0x8000,
			rc4_encrypted = 0x100000,
			plaintext_encrypted = 0x200000
		};

		unsigned int flags;

		enum peer_source_flags
		{
			tracker = 0x1,
			dht = 0x2,
			pex = 0x4,
			lsd = 0x8,
			resume_data = 0x10,
			incoming = 0x20
		};

		int source;

		// bw_idle: the channel is not used
		// bw_limit: the channel is waiting for quota
		// bw_network: the channel is waiting for an async write
		//   or read operation to complete
		// bw_disk: the peer is waiting for the disk io thread
		// this is a bitmask, a peer can wait for network, rate-limiter
		// and disk at the same time!
		enum bw_state { bw_idle = 0, bw_limit = 1, bw_network = 2, bw_disk = 4 };
#ifndef TORRENT_NO_DEPRECATE
		enum bw_state_deprecated { bw_torrent = bw_limit, bw_global = bw_limit };
#endif

		char read_state;
		char write_state;

		tcp::endpoint ip;
		int up_speed;
		int down_speed;
		int payload_up_speed;
		int payload_down_speed;
		size_type total_download;
		size_type total_upload;
		peer_id pid;
		bitfield pieces;
#ifndef TORRENT_NO_DEPRECATE
		int upload_limit;
		int download_limit;
#endif

		// time since last request
		time_duration last_request;

		// time since last download or upload
		time_duration last_active;

		// the time until all blocks in the request
		// queue will be d
		time_duration download_queue_time;
		int queue_bytes;

		// the number of seconds until the current
		// pending request times out
		int request_timeout;

		// the size of the send buffer for this peer, in bytes
		int send_buffer_size;
		// the number bytes that's actually used of the send buffer
		int used_send_buffer;

		int receive_buffer_size;
		int used_receive_buffer;

		// the number of failed hashes for this peer
		int num_hashfails;

#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
		// in case the session settings is set
		// to resolve countries, this is set to
		// the two character country code this
		// peer resides in.
		char country[2];
#endif

#ifndef TORRENT_DISABLE_GEO_IP
		// atonomous system this peer belongs to
		std::string inet_as_name;
		int inet_as;
#endif

#ifndef TORRENT_NO_DEPRECATE
		size_type load_balancing;
#endif

		// this is the number of requests
		// we have sent to this peer
		// that we haven't got a response
		// for yet
		int download_queue_length;

		// the number of block requests that have
		// timed out, and are still in the download
		// queue
		int timed_out_requests;

		// the number of busy requests in the download
		// queue. A budy request is a request for a block
		// we've also requested from a different peer
		int busy_requests;

		// the number of request messages
		// waiting to be sent inside the send buffer
		int requests_in_buffer;

		// the number of requests that is
		// tried to be maintained (this is
		// typically a function of download speed)
		int target_dl_queue_length;

		// this is the number of requests
		// the peer has sent to us
		// that we haven't sent yet
		int upload_queue_length;

		// the number of times this IP
		// has failed to connect
		int failcount;

		// the currently downloading piece
		// if piece index is -1 all associated
		// members are just set to 0
		int downloading_piece_index;
		int downloading_block_index;
		int downloading_progress;
		int downloading_total;

		std::string client;

		enum
		{
			standard_bittorrent = 0,
			web_seed = 1,
			http_seed = 2,
			bittorrent_utp = 3
		};
		int connection_type;

		// approximate peer download rate
		int remote_dl_rate;

		// number of bytes this peer has in
		// the disk write queue
		int pending_disk_bytes;
		// number of outstanding bytes to read
		// from disk
		int pending_disk_read_bytes;

		// numbers used for bandwidth limiting
		int send_quota;
		int receive_quota;

		// estimated rtt to peer, in milliseconds
		int rtt;

		// the number of pieces this peer has
		int num_pieces;

		// the highest transfer rates seen for this peer
		int download_rate_peak;
		int upload_rate_peak;

		// the peer's progress
		float progress; // [0, 1]
		int progress_ppm; // [0, 1000000]

		int estimated_reciprocation_rate;

		tcp::endpoint local_endpoint;
	};

	struct TORRENT_EXPORT peer_list_entry
	{
		enum flags_t
		{
			banned = 1
		};

		tcp::endpoint ip;
		int flags;
		boost::uint8_t failcount;
		boost::uint8_t source;
	};

	// defined in policy.cpp
	int source_rank(int source_bitmask);
}

#endif // TORRENT_PEER_INFO_HPP_INCLUDED
<|endoftext|>


<commit_before>#pragma once

#include <set>
#include <string_view>
#include <vector>

#include "Runtime/RetroTypes.hpp"

namespace urde {
class CPrimitive;
class IMetaAnim;

class CAnimationDatabase {
public:
  virtual const std::shared_ptr<IMetaAnim>& GetMetaAnim(s32) const = 0;
  virtual u32 GetNumMetaAnims() const = 0;
  virtual const char* GetMetaAnimName(s32) const = 0;
  virtual void GetAllUniquePrimitives(std::vector<CPrimitive>&) const = 0;
  virtual void GetUniquePrimitivesFromMetaAnim(std::set<CPrimitive>&, std::string_view) const = 0;
};

} // namespace urde
<commit_msg>CAnimationDatabase: Add virtual destructor<commit_after>#pragma once

#include <set>
#include <string_view>
#include <vector>

#include "Runtime/RetroTypes.hpp"

namespace urde {
class CPrimitive;
class IMetaAnim;

class CAnimationDatabase {
public:
  virtual ~CAnimationDatabase() = default;
  virtual const std::shared_ptr<IMetaAnim>& GetMetaAnim(s32) const = 0;
  virtual u32 GetNumMetaAnims() const = 0;
  virtual const char* GetMetaAnimName(s32) const = 0;
  virtual void GetAllUniquePrimitives(std::vector<CPrimitive>&) const = 0;
  virtual void GetUniquePrimitivesFromMetaAnim(std::set<CPrimitive>&, std::string_view) const = 0;
};

} // namespace urde
<|endoftext|>


<commit_before>/*     Copyright 2015-2018 Egor Yusov
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
 *
 *  In no event and under no legal theory, whether in tort (including negligence),
 *  contract, or otherwise, unless required by applicable law (such as deliberate
 *  and grossly negligent acts) or agreed to in writing, shall any Contributor be
 *  liable for any damages, including any direct, indirect, special, incidental,
 *  or consequential damages of any character arising as a result of this License or
 *  out of the use or inability to use the software (including but not limited to damages
 *  for loss of goodwill, work stoppage, computer failure or malfunction, or any and
 *  all other commercial damages or losses), even if such Contributor has been advised
 *  of the possibility of such damages.
 */

#include <memory>
#include <iomanip>
#include <Windows.h>
#include "SampleBase.h"
#include "RenderDeviceFactoryD3D11.h"
#include "RenderDeviceFactoryD3D12.h"
#include "RenderDeviceFactoryOpenGL.h"
#include "Timer.h"
#include "StringTools.h"

using namespace Diligent;

#include "AntTweakBar.h"

std::unique_ptr<SampleBase> g_pSample;

LRESULT CALLBACK MessageProc(HWND, UINT, WPARAM, LPARAM);

// Create Direct3D device and swap chain
void InitDevice(HWND hWnd, IRenderDevice **ppRenderDevice, std::vector<IDeviceContext*> &ppContexts,  ISwapChain **ppSwapChain, DeviceType DevType)
{
    SwapChainDesc SCDesc;
    SCDesc.SamplesCount = 1;
    Uint32 NumDeferredCtx = 0;
    switch (DevType)
    {
        case DeviceType::D3D11:
        {
            EngineD3D11Attribs DeviceAttribs;
            g_pSample->GetEngineInitializationAttribs(DevType, DeviceAttribs, NumDeferredCtx);

#ifdef ENGINE_DLL
            GetEngineFactoryD3D11Type GetEngineFactoryD3D11 = nullptr;
            // Load the dll and import GetEngineFactoryD3D11() function
            LoadGraphicsEngineD3D11(GetEngineFactoryD3D11);
#endif
            auto *pFactoryD3D11 = GetEngineFactoryD3D11();
            ppContexts.resize(1 + NumDeferredCtx);
            pFactoryD3D11->CreateDeviceAndContextsD3D11( DeviceAttribs, ppRenderDevice, ppContexts.data(), NumDeferredCtx );
            pFactoryD3D11->CreateSwapChainD3D11( *ppRenderDevice, ppContexts[0], SCDesc, hWnd, ppSwapChain );
        }
        break;

        case DeviceType::D3D12:
        {
#ifdef ENGINE_DLL
            GetEngineFactoryD3D12Type GetEngineFactoryD3D12 = nullptr;
            // Load the dll and import GetEngineFactoryD3D12() function
            LoadGraphicsEngineD3D12(GetEngineFactoryD3D12);
#endif

            auto *pFactoryD3D12 = GetEngineFactoryD3D12();
            EngineD3D12Attribs EngD3D12Attribs;
            g_pSample->GetEngineInitializationAttribs(DevType, EngD3D12Attribs, NumDeferredCtx);
            ppContexts.resize(1 + NumDeferredCtx);
            pFactoryD3D12->CreateDeviceAndContextsD3D12( EngD3D12Attribs, ppRenderDevice, ppContexts.data(), NumDeferredCtx);
            pFactoryD3D12->CreateSwapChainD3D12( *ppRenderDevice, ppContexts[0], SCDesc, hWnd, ppSwapChain );
        }
        break;

        case DeviceType::OpenGL:
        {
#ifdef ENGINE_DLL
            // Declare function pointer
            GetEngineFactoryOpenGLType GetEngineFactoryOpenGL = nullptr;
            // Load the dll and import GetEngineFactoryOpenGL() function
            LoadGraphicsEngineOpenGL(GetEngineFactoryOpenGL);
#endif
            EngineCreationAttribs CreationAttribs;
            g_pSample->GetEngineInitializationAttribs(DevType, CreationAttribs, NumDeferredCtx);
            if(NumDeferredCtx != 0)
            {
                LOG_ERROR_MESSAGE("Deferred contexts are not supported in OpenGL mode");
                NumDeferredCtx = 0;
            }
            ppContexts.resize(1 + NumDeferredCtx);
            GetEngineFactoryOpenGL()->CreateDeviceAndSwapChainGL(
                CreationAttribs, ppRenderDevice, ppContexts.data(), SCDesc, hWnd, ppSwapChain );
        }
        break;

        default:
            LOG_ERROR_AND_THROW("Unknown device type");
        break;
    }
}

ISwapChain *g_pSwapChain;

// Main
int WINAPI WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int cmdShow)
{
#if defined(_DEBUG) || defined(DEBUG)
    _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif

    g_pSample.reset( CreateSample() );
    std::wstring Title = WidenString(g_pSample->GetSampleName());

    DeviceType DevType = DeviceType::Undefined;
    std::wstring CmdLine = GetCommandLine();
    std::wstring Key = L"mode=";
    auto pos = CmdLine.find( Key );
    if( pos != std::string::npos )
    {
        pos += Key.length();
        auto Val = CmdLine.substr( pos );
        if( _wcsicmp(Val.c_str(), L"D3D11") == 0)
        {
            DevType = DeviceType::D3D11;
        }
        else if( _wcsicmp(Val.c_str(), L"D3D12") == 0)
        {
            DevType = DeviceType::D3D12;
        }
        else if( _wcsicmp(Val.c_str(), L"GL") == 0)
        {
            DevType = DeviceType::OpenGL;
        }
        else
        {
            LOG_ERROR("Unknown device type. Only the following types are supported: D3D11, D3D12, GL");
            return -1;
        }
    }
    else
    {
        LOG_INFO_MESSAGE("Device type is not specified. Using D3D11 device");
        DevType = DeviceType::D3D11;
    }

    switch (DevType)
    {
        case DeviceType::D3D11: Title.append( L" (D3D11)" ); break;
        case DeviceType::D3D12: Title.append( L" (D3D12)" ); break;
        case DeviceType::OpenGL: Title.append( L" (OpenGL)" ); break;
        default: UNEXPECTED("Unknown device type");
    }

    // Register our window class
    WNDCLASSEX wcex = { sizeof(WNDCLASSEX), CS_HREDRAW|CS_VREDRAW, MessageProc,
                        0L, 0L, instance, NULL, NULL, NULL, NULL, L"SampleApp", NULL };
    RegisterClassEx(&wcex);

    // Create a window
    RECT rc = { 0, 0, 1280, 1024 };
    AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
    HWND wnd = CreateWindow(L"SampleApp", Title.c_str(),
                            WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
                            rc.right-rc.left, rc.bottom-rc.top, NULL, NULL, instance, NULL);
    if (!wnd)
    {
        MessageBox(NULL, L"Cannot create window", L"Error", MB_OK|MB_ICONERROR);
        return 0;
    }
    ShowWindow(wnd, cmdShow);
    UpdateWindow(wnd);

    RefCntAutoPtr<IRenderDevice> pRenderDevice;
    Diligent::RefCntAutoPtr<ISwapChain> pSwapChain;
    std::vector<IDeviceContext*> ppContexts;
    InitDevice( wnd, &pRenderDevice, ppContexts, &pSwapChain, DevType );
    RefCntAutoPtr<IDeviceContext> pImmediateContext;
    pImmediateContext.Attach(ppContexts[0]);
    std::vector<RefCntAutoPtr<IDeviceContext>> ppDeferredCtx(ppContexts.size()-1);
    for(size_t ctx = 0; ctx < ppContexts.size()-1; ++ctx)
        ppDeferredCtx[ctx].Attach(ppContexts[1+ctx]);

    g_pSwapChain = pSwapChain;

    // Initialize AntTweakBar
    // TW_OPENGL and TW_OPENGL_CORE were designed to select rendering with
    // very old GL specification. Using these modes results in applying some
    // odd offsets which distorts everything
    // Latest OpenGL works very much like Direct3D11, and
    // Tweak Bar will never know if D3D or OpenGL is actually used
    if (!TwInit(TW_DIRECT3D11, pRenderDevice.RawPtr(), pImmediateContext.RawPtr(), pSwapChain->GetDesc().ColorBufferFormat))
    {
        MessageBoxA(wnd, TwGetLastError(), "AntTweakBar initialization failed", MB_OK|MB_ICONERROR);
        return 0;
    }
    TwDefine(" TW_HELP visible=false ");

    g_pSample->Initialize(pRenderDevice, ppContexts.data(), static_cast<Uint32>(ppContexts.size() - 1), pSwapChain);
    g_pSample->WindowResize( g_pSwapChain->GetDesc().Width, g_pSwapChain->GetDesc().Height );

    Timer Timer;
    auto PrevTime = Timer.GetElapsedTime();
    double filteredFrameTime = 0.0;

    // Main message loop
    MSG msg = {0};
    while (WM_QUIT != msg.message)
    {
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else
        {
            auto CurrTime = Timer.GetElapsedTime();
            auto ElapsedTime = CurrTime - PrevTime;
            PrevTime = CurrTime;
            g_pSample->Update(CurrTime, ElapsedTime);
            g_pSample->Render();

	        // Draw tweak bars
            // Restore default render target in case the sample has changed it
            pImmediateContext->SetRenderTargets(0, nullptr, nullptr);
            TwDraw();

            pSwapChain->Present();

            double filterScale = 0.2;
            filteredFrameTime = filteredFrameTime * (1.0 - filterScale) + filterScale * ElapsedTime;
            std::wstringstream fpsCounterSS;
            fpsCounterSS << " - " << std::fixed << std::setprecision(1) << filteredFrameTime * 1000;
            fpsCounterSS << " ms (" << 1.0 / filteredFrameTime << " fps)";
            SetWindowText(wnd, (Title + fpsCounterSS.str()).c_str());
        }
    }

    TwTerminate();

	//pDeviceContext->Flush();
    g_pSample.reset();
    ppDeferredCtx.clear();
    pImmediateContext.Release();
    pRenderDevice.Release();

    return (int)msg.wParam;
}

// Called every time the application receives a message
LRESULT CALLBACK MessageProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    // Send event message to AntTweakBar
    if (TwEventWin(wnd, message, wParam, lParam))
        return 0; // Event has been handled by AntTweakBar

    switch (message)
    {
        case WM_PAINT:
            {
                PAINTSTRUCT ps;
                BeginPaint(wnd, &ps);
                EndPaint(wnd, &ps);
                return 0;
            }
        case WM_SIZE: // Window size has been changed
            if( g_pSwapChain )
            {
                g_pSwapChain->Resize(LOWORD(lParam), HIWORD(lParam));
                g_pSample->WindowResize( g_pSwapChain->GetDesc().Width, g_pSwapChain->GetDesc().Height );
            }
            return 0;
        case WM_CHAR:
            if (wParam == VK_ESCAPE)
                PostQuitMessage(0);
            return 0;
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        default:
        {
            struct WindowMessageData
            {
                HWND hWnd;
                UINT message;
                WPARAM wParam;
                LPARAM lParam;
            }msg{wnd, message, wParam, lParam};
            if (g_pSample != nullptr && g_pSample->HandleNativeMessage(&msg) )
                return 0;
            else
                return DefWindowProc(wnd, message, wParam, lParam);
        }
    }
}
<commit_msg>Updated WinMain for new GL initialization<commit_after>/*     Copyright 2015-2018 Egor Yusov
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
 *
 *  In no event and under no legal theory, whether in tort (including negligence),
 *  contract, or otherwise, unless required by applicable law (such as deliberate
 *  and grossly negligent acts) or agreed to in writing, shall any Contributor be
 *  liable for any damages, including any direct, indirect, special, incidental,
 *  or consequential damages of any character arising as a result of this License or
 *  out of the use or inability to use the software (including but not limited to damages
 *  for loss of goodwill, work stoppage, computer failure or malfunction, or any and
 *  all other commercial damages or losses), even if such Contributor has been advised
 *  of the possibility of such damages.
 */

#include <memory>
#include <iomanip>
#include <Windows.h>
#include "SampleBase.h"
#include "RenderDeviceFactoryD3D11.h"
#include "RenderDeviceFactoryD3D12.h"
#include "RenderDeviceFactoryOpenGL.h"
#include "Timer.h"
#include "StringTools.h"

using namespace Diligent;

#include "AntTweakBar.h"

std::unique_ptr<SampleBase> g_pSample;

LRESULT CALLBACK MessageProc(HWND, UINT, WPARAM, LPARAM);

// Create Direct3D device and swap chain
void InitDevice(HWND hWnd, IRenderDevice **ppRenderDevice, std::vector<IDeviceContext*> &ppContexts,  ISwapChain **ppSwapChain, DeviceType DevType)
{
    SwapChainDesc SCDesc;
    SCDesc.SamplesCount = 1;
    Uint32 NumDeferredCtx = 0;
    switch (DevType)
    {
        case DeviceType::D3D11:
        {
            EngineD3D11Attribs DeviceAttribs;
            g_pSample->GetEngineInitializationAttribs(DevType, DeviceAttribs, NumDeferredCtx);

#ifdef ENGINE_DLL
            GetEngineFactoryD3D11Type GetEngineFactoryD3D11 = nullptr;
            // Load the dll and import GetEngineFactoryD3D11() function
            LoadGraphicsEngineD3D11(GetEngineFactoryD3D11);
#endif
            auto *pFactoryD3D11 = GetEngineFactoryD3D11();
            ppContexts.resize(1 + NumDeferredCtx);
            pFactoryD3D11->CreateDeviceAndContextsD3D11( DeviceAttribs, ppRenderDevice, ppContexts.data(), NumDeferredCtx );
            pFactoryD3D11->CreateSwapChainD3D11( *ppRenderDevice, ppContexts[0], SCDesc, hWnd, ppSwapChain );
        }
        break;

        case DeviceType::D3D12:
        {
#ifdef ENGINE_DLL
            GetEngineFactoryD3D12Type GetEngineFactoryD3D12 = nullptr;
            // Load the dll and import GetEngineFactoryD3D12() function
            LoadGraphicsEngineD3D12(GetEngineFactoryD3D12);
#endif

            auto *pFactoryD3D12 = GetEngineFactoryD3D12();
            EngineD3D12Attribs EngD3D12Attribs;
            g_pSample->GetEngineInitializationAttribs(DevType, EngD3D12Attribs, NumDeferredCtx);
            ppContexts.resize(1 + NumDeferredCtx);
            pFactoryD3D12->CreateDeviceAndContextsD3D12( EngD3D12Attribs, ppRenderDevice, ppContexts.data(), NumDeferredCtx);
            pFactoryD3D12->CreateSwapChainD3D12( *ppRenderDevice, ppContexts[0], SCDesc, hWnd, ppSwapChain );
        }
        break;

        case DeviceType::OpenGL:
        {
#ifdef ENGINE_DLL
            // Declare function pointer
            GetEngineFactoryOpenGLType GetEngineFactoryOpenGL = nullptr;
            // Load the dll and import GetEngineFactoryOpenGL() function
            LoadGraphicsEngineOpenGL(GetEngineFactoryOpenGL);
#endif
            EngineGLAttribs CreationAttribs;
            CreationAttribs.pNativeWndHandle = hWnd;
            g_pSample->GetEngineInitializationAttribs(DevType, CreationAttribs, NumDeferredCtx);
            if(NumDeferredCtx != 0)
            {
                LOG_ERROR_MESSAGE("Deferred contexts are not supported in OpenGL mode");
                NumDeferredCtx = 0;
            }
            ppContexts.resize(1 + NumDeferredCtx);
            GetEngineFactoryOpenGL()->CreateDeviceAndSwapChainGL(
                CreationAttribs, ppRenderDevice, ppContexts.data(), SCDesc, ppSwapChain );
        }
        break;

        default:
            LOG_ERROR_AND_THROW("Unknown device type");
        break;
    }
}

ISwapChain *g_pSwapChain;

// Main
int WINAPI WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int cmdShow)
{
#if defined(_DEBUG) || defined(DEBUG)
    _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif

    g_pSample.reset( CreateSample() );
    std::wstring Title = WidenString(g_pSample->GetSampleName());

    DeviceType DevType = DeviceType::Undefined;
    std::wstring CmdLine = GetCommandLine();
    std::wstring Key = L"mode=";
    auto pos = CmdLine.find( Key );
    if( pos != std::string::npos )
    {
        pos += Key.length();
        auto Val = CmdLine.substr( pos );
        if( _wcsicmp(Val.c_str(), L"D3D11") == 0)
        {
            DevType = DeviceType::D3D11;
        }
        else if( _wcsicmp(Val.c_str(), L"D3D12") == 0)
        {
            DevType = DeviceType::D3D12;
        }
        else if( _wcsicmp(Val.c_str(), L"GL") == 0)
        {
            DevType = DeviceType::OpenGL;
        }
        else
        {
            LOG_ERROR("Unknown device type. Only the following types are supported: D3D11, D3D12, GL");
            return -1;
        }
    }
    else
    {
        LOG_INFO_MESSAGE("Device type is not specified. Using D3D11 device");
        DevType = DeviceType::D3D11;
    }

    switch (DevType)
    {
        case DeviceType::D3D11: Title.append( L" (D3D11)" ); break;
        case DeviceType::D3D12: Title.append( L" (D3D12)" ); break;
        case DeviceType::OpenGL: Title.append( L" (OpenGL)" ); break;
        default: UNEXPECTED("Unknown device type");
    }

    // Register our window class
    WNDCLASSEX wcex = { sizeof(WNDCLASSEX), CS_HREDRAW|CS_VREDRAW, MessageProc,
                        0L, 0L, instance, NULL, NULL, NULL, NULL, L"SampleApp", NULL };
    RegisterClassEx(&wcex);

    // Create a window
    RECT rc = { 0, 0, 1280, 1024 };
    AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
    HWND wnd = CreateWindow(L"SampleApp", Title.c_str(),
                            WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
                            rc.right-rc.left, rc.bottom-rc.top, NULL, NULL, instance, NULL);
    if (!wnd)
    {
        MessageBox(NULL, L"Cannot create window", L"Error", MB_OK|MB_ICONERROR);
        return 0;
    }
    ShowWindow(wnd, cmdShow);
    UpdateWindow(wnd);

    RefCntAutoPtr<IRenderDevice> pRenderDevice;
    Diligent::RefCntAutoPtr<ISwapChain> pSwapChain;
    std::vector<IDeviceContext*> ppContexts;
    InitDevice( wnd, &pRenderDevice, ppContexts, &pSwapChain, DevType );
    RefCntAutoPtr<IDeviceContext> pImmediateContext;
    pImmediateContext.Attach(ppContexts[0]);
    std::vector<RefCntAutoPtr<IDeviceContext>> ppDeferredCtx(ppContexts.size()-1);
    for(size_t ctx = 0; ctx < ppContexts.size()-1; ++ctx)
        ppDeferredCtx[ctx].Attach(ppContexts[1+ctx]);

    g_pSwapChain = pSwapChain;

    // Initialize AntTweakBar
    // TW_OPENGL and TW_OPENGL_CORE were designed to select rendering with
    // very old GL specification. Using these modes results in applying some
    // odd offsets which distorts everything
    // Latest OpenGL works very much like Direct3D11, and
    // Tweak Bar will never know if D3D or OpenGL is actually used
    if (!TwInit(TW_DIRECT3D11, pRenderDevice.RawPtr(), pImmediateContext.RawPtr(), pSwapChain->GetDesc().ColorBufferFormat))
    {
        MessageBoxA(wnd, TwGetLastError(), "AntTweakBar initialization failed", MB_OK|MB_ICONERROR);
        return 0;
    }
    TwDefine(" TW_HELP visible=false ");

    g_pSample->Initialize(pRenderDevice, ppContexts.data(), static_cast<Uint32>(ppContexts.size() - 1), pSwapChain);
    g_pSample->WindowResize( g_pSwapChain->GetDesc().Width, g_pSwapChain->GetDesc().Height );

    Timer Timer;
    auto PrevTime = Timer.GetElapsedTime();
    double filteredFrameTime = 0.0;

    // Main message loop
    MSG msg = {0};
    while (WM_QUIT != msg.message)
    {
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else
        {
            auto CurrTime = Timer.GetElapsedTime();
            auto ElapsedTime = CurrTime - PrevTime;
            PrevTime = CurrTime;
            g_pSample->Update(CurrTime, ElapsedTime);
            g_pSample->Render();

	        // Draw tweak bars
            // Restore default render target in case the sample has changed it
            pImmediateContext->SetRenderTargets(0, nullptr, nullptr);
            TwDraw();

            pSwapChain->Present();

            double filterScale = 0.2;
            filteredFrameTime = filteredFrameTime * (1.0 - filterScale) + filterScale * ElapsedTime;
            std::wstringstream fpsCounterSS;
            fpsCounterSS << " - " << std::fixed << std::setprecision(1) << filteredFrameTime * 1000;
            fpsCounterSS << " ms (" << 1.0 / filteredFrameTime << " fps)";
            SetWindowText(wnd, (Title + fpsCounterSS.str()).c_str());
        }
    }

    TwTerminate();

	//pDeviceContext->Flush();
    g_pSample.reset();
    ppDeferredCtx.clear();
    pImmediateContext.Release();
    pRenderDevice.Release();

    return (int)msg.wParam;
}

// Called every time the application receives a message
LRESULT CALLBACK MessageProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    // Send event message to AntTweakBar
    if (TwEventWin(wnd, message, wParam, lParam))
        return 0; // Event has been handled by AntTweakBar

    switch (message)
    {
        case WM_PAINT:
            {
                PAINTSTRUCT ps;
                BeginPaint(wnd, &ps);
                EndPaint(wnd, &ps);
                return 0;
            }
        case WM_SIZE: // Window size has been changed
            if( g_pSwapChain )
            {
                g_pSwapChain->Resize(LOWORD(lParam), HIWORD(lParam));
                g_pSample->WindowResize( g_pSwapChain->GetDesc().Width, g_pSwapChain->GetDesc().Height );
            }
            return 0;
        case WM_CHAR:
            if (wParam == VK_ESCAPE)
                PostQuitMessage(0);
            return 0;
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        default:
        {
            struct WindowMessageData
            {
                HWND hWnd;
                UINT message;
                WPARAM wParam;
                LPARAM lParam;
            }msg{wnd, message, wParam, lParam};
            if (g_pSample != nullptr && g_pSample->HandleNativeMessage(&msg) )
                return 0;
            else
                return DefWindowProc(wnd, message, wParam, lParam);
        }
    }
}
<|endoftext|>


<commit_before>/*
 * Delegate helper pooling.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "Stock.hxx"
#include "stock/MapStock.hxx"
#include "stock/Class.hxx"
#include "stock/Item.hxx"
#include "async.hxx"
#include "failure.hxx"
#include "system/fd_util.h"
#include "event/Event.hxx"
#include "event/Callback.hxx"
#include "spawn/Spawn.hxx"
#include "spawn/Prepared.hxx"
#include "spawn/ChildOptions.hxx"
#include "gerrno.h"
#include "pool.hxx"

#include <daemon/log.h>

#include <assert.h>
#include <unistd.h>
#include <sys/un.h>
#include <sys/socket.h>

struct DelegateArgs {
    const ChildOptions *options;

    PreparedChildProcess child;
};

struct DelegateProcess final : HeapStockItem {
    const char *const uri;

    const pid_t pid;
    const int fd;

    Event event;

    explicit DelegateProcess(CreateStockItem c,
                             const char *_uri,
                             pid_t _pid, int _fd)
        :HeapStockItem(c), uri(_uri), pid(_pid), fd(_fd) {
        event.Set(fd, EV_READ|EV_TIMEOUT,
                  MakeEventCallback(DelegateProcess, EventCallback), this);
    }

    ~DelegateProcess() override {
        if (fd >= 0) {
            event.Delete();
            close(fd);
        }
    }

    void EventCallback(int fd, short event);

    /* virtual methods from class StockItem */
    bool Borrow(gcc_unused void *ctx) override {
        event.Delete();
        return true;
    }

    bool Release(gcc_unused void *ctx) override {
        static constexpr struct timeval tv = {
            .tv_sec = 60,
            .tv_usec = 0,
        };

        event.Add(tv);
        return true;
    }
};

/*
 * libevent callback
 *
 */

inline void
DelegateProcess::EventCallback(gcc_unused int _fd, short events)
{
    assert(_fd == fd);

    if ((events & EV_TIMEOUT) == 0) {
        assert((events & EV_READ) != 0);

        char buffer;
        ssize_t nbytes = recv(fd, &buffer, sizeof(buffer), MSG_DONTWAIT);
        if (nbytes < 0)
            daemon_log(2, "error on idle delegate process: %s\n",
                       strerror(errno));
        else if (nbytes > 0)
            daemon_log(2, "unexpected data from idle delegate process\n");
    }

    InvokeIdleDisconnect();
    pool_commit();
}

/*
 * stock class
 *
 */

static void
delegate_stock_create(gcc_unused void *ctx,
                      gcc_unused struct pool &parent_pool, CreateStockItem c,
                      const char *uri, void *_info,
                      gcc_unused struct pool &caller_pool,
                      gcc_unused struct async_operation_ref &async_ref)
{
    auto *const info = (DelegateArgs *)_info;

    int fds[2];
    if (socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
        GError *error = new_error_errno_msg("socketpair() failed: %s");
        c.InvokeCreateError(error);
        return;
    }

    info->child.stdin_fd = fds[1];

    pid_t pid = SpawnChildProcess(std::move(info->child));
    if (pid < 0) {
        GError *error = new_error_errno_msg2(-pid, "clone() failed");
        close(fds[0]);
        c.InvokeCreateError(error);
        return;
    }

    auto *process = new DelegateProcess(c, uri, pid, fds[0]);
    process->InvokeCreateSuccess();
}

static constexpr StockClass delegate_stock_class = {
    .create = delegate_stock_create,
};

/*
 * interface
 *
 */

StockMap *
delegate_stock_new(struct pool *pool)
{
    return hstock_new(*pool, delegate_stock_class, nullptr, 0, 16);
}

StockItem *
delegate_stock_get(StockMap *delegate_stock, struct pool *pool,
                   const char *helper,
                   const ChildOptions &options,
                   GError **error_r)
{
    const char *uri = helper;

    char options_buffer[4096];
    *options.MakeId(options_buffer) = 0;
    if (*options_buffer != 0)
        uri = p_strcat(pool, helper, "|", options_buffer, nullptr);

    DelegateArgs args;
    args.options = &options;

    args.child.Append(helper);
    if (!options.CopyTo(args.child, true, nullptr, error_r))
        return nullptr;

    return hstock_get_now(*delegate_stock, *pool, uri, &args, error_r);
}

void
delegate_stock_put(StockMap *delegate_stock,
                   StockItem &item, bool destroy)
{
    auto *process = (DelegateProcess *)&item;

    hstock_put(*delegate_stock, process->uri, item, destroy);
}

int
delegate_stock_item_get(StockItem &item)
{
    auto *process = (DelegateProcess *)&item;

    return process->fd;
}
<commit_msg>delegate/Stock: convert pointer to reference<commit_after>/*
 * Delegate helper pooling.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "Stock.hxx"
#include "stock/MapStock.hxx"
#include "stock/Class.hxx"
#include "stock/Item.hxx"
#include "async.hxx"
#include "failure.hxx"
#include "system/fd_util.h"
#include "event/Event.hxx"
#include "event/Callback.hxx"
#include "spawn/Spawn.hxx"
#include "spawn/Prepared.hxx"
#include "spawn/ChildOptions.hxx"
#include "gerrno.h"
#include "pool.hxx"

#include <daemon/log.h>

#include <assert.h>
#include <unistd.h>
#include <sys/un.h>
#include <sys/socket.h>

struct DelegateArgs {
    const ChildOptions *options;

    PreparedChildProcess child;
};

struct DelegateProcess final : HeapStockItem {
    const char *const uri;

    const pid_t pid;
    const int fd;

    Event event;

    explicit DelegateProcess(CreateStockItem c,
                             const char *_uri,
                             pid_t _pid, int _fd)
        :HeapStockItem(c), uri(_uri), pid(_pid), fd(_fd) {
        event.Set(fd, EV_READ|EV_TIMEOUT,
                  MakeEventCallback(DelegateProcess, EventCallback), this);
    }

    ~DelegateProcess() override {
        if (fd >= 0) {
            event.Delete();
            close(fd);
        }
    }

    void EventCallback(int fd, short event);

    /* virtual methods from class StockItem */
    bool Borrow(gcc_unused void *ctx) override {
        event.Delete();
        return true;
    }

    bool Release(gcc_unused void *ctx) override {
        static constexpr struct timeval tv = {
            .tv_sec = 60,
            .tv_usec = 0,
        };

        event.Add(tv);
        return true;
    }
};

/*
 * libevent callback
 *
 */

inline void
DelegateProcess::EventCallback(gcc_unused int _fd, short events)
{
    assert(_fd == fd);

    if ((events & EV_TIMEOUT) == 0) {
        assert((events & EV_READ) != 0);

        char buffer;
        ssize_t nbytes = recv(fd, &buffer, sizeof(buffer), MSG_DONTWAIT);
        if (nbytes < 0)
            daemon_log(2, "error on idle delegate process: %s\n",
                       strerror(errno));
        else if (nbytes > 0)
            daemon_log(2, "unexpected data from idle delegate process\n");
    }

    InvokeIdleDisconnect();
    pool_commit();
}

/*
 * stock class
 *
 */

static void
delegate_stock_create(gcc_unused void *ctx,
                      gcc_unused struct pool &parent_pool, CreateStockItem c,
                      const char *uri, void *_info,
                      gcc_unused struct pool &caller_pool,
                      gcc_unused struct async_operation_ref &async_ref)
{
    auto &info = *(DelegateArgs *)_info;

    int fds[2];
    if (socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
        GError *error = new_error_errno_msg("socketpair() failed: %s");
        c.InvokeCreateError(error);
        return;
    }

    info.child.stdin_fd = fds[1];

    pid_t pid = SpawnChildProcess(std::move(info.child));
    if (pid < 0) {
        GError *error = new_error_errno_msg2(-pid, "clone() failed");
        close(fds[0]);
        c.InvokeCreateError(error);
        return;
    }

    auto *process = new DelegateProcess(c, uri, pid, fds[0]);
    process->InvokeCreateSuccess();
}

static constexpr StockClass delegate_stock_class = {
    .create = delegate_stock_create,
};

/*
 * interface
 *
 */

StockMap *
delegate_stock_new(struct pool *pool)
{
    return hstock_new(*pool, delegate_stock_class, nullptr, 0, 16);
}

StockItem *
delegate_stock_get(StockMap *delegate_stock, struct pool *pool,
                   const char *helper,
                   const ChildOptions &options,
                   GError **error_r)
{
    const char *uri = helper;

    char options_buffer[4096];
    *options.MakeId(options_buffer) = 0;
    if (*options_buffer != 0)
        uri = p_strcat(pool, helper, "|", options_buffer, nullptr);

    DelegateArgs args;
    args.options = &options;

    args.child.Append(helper);
    if (!options.CopyTo(args.child, true, nullptr, error_r))
        return nullptr;

    return hstock_get_now(*delegate_stock, *pool, uri, &args, error_r);
}

void
delegate_stock_put(StockMap *delegate_stock,
                   StockItem &item, bool destroy)
{
    auto *process = (DelegateProcess *)&item;

    hstock_put(*delegate_stock, process->uri, item, destroy);
}

int
delegate_stock_item_get(StockItem &item)
{
    auto *process = (DelegateProcess *)&item;

    return process->fd;
}
<|endoftext|>