<commit_before>// @(#)root/geom:$Name:  $:$Id: TGeoPhysicalNode.cxx,v 1.7 2005/11/18 16:07:58 brun Exp $
// Author: Andrei Gheata   17/02/04

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

////////////////////////////////////////////////////////////////////////////////
// TGeoPhysicalNode
//_________

#include "TGeoManager.h"
#include "TGeoCache.h"
#include "TGeoMatrix.h"
#include "TGeoShape.h"
#include "TGeoVolume.h"
#include "TVirtualGeoPainter.h"

#include "TGeoPhysicalNode.h"

// statics and globals

ClassImp(TGeoPhysicalNode)

//_____________________________________________________________________________
TGeoPhysicalNode::TGeoPhysicalNode()
{
// Default constructor
   fLevel        = 0;
   fMatrices     = 0;
   fNodes        = 0;
   fMatrixOrig   = 0;
   SetVisibility(kTRUE);
   SetVisibleFull(kFALSE);
   SetIsVolAtt(kTRUE);
   SetAligned(kFALSE);
}

//_____________________________________________________________________________
TGeoPhysicalNode::TGeoPhysicalNode(const char *path)
{
// Constructor
   if (!strlen(path)) {
      Error("ctor", "path not valid");
      return;
   }
   fLevel  = 0;
   fMatrices = new TObjArray(30);
   fNodes    = new TObjArray(30);
   fMatrixOrig   = 0;
   SetPath(path);
   SetVisibility(kTRUE);
   SetVisibleFull(kFALSE);
   SetIsVolAtt(kTRUE);
   SetAligned(kFALSE);
}

//_____________________________________________________________________________
TGeoPhysicalNode::~TGeoPhysicalNode()
{
// Destructor
   if (fMatrices) {
      fMatrices->Delete();
      delete fMatrices;
   }
   if (fNodes) delete fNodes;
   if (fMatrixOrig) delete fMatrixOrig;
}

//_____________________________________________________________________________
void TGeoPhysicalNode::Align(TGeoMatrix *newmat, TGeoShape *newshape, Bool_t check)
{
   // Align a physical node with a new relative matrix/shape.
   // Example: /TOP_1/A_1/B_1/C_1
   //    node->Align(transl_1, box) will perform:
   //    - change RELATIVE translation of C_1 node (with respect to its
   //      container volume B) to transl_1
   //    - change the shape of the C volume
   // *NOTE* The operations will affect ONLY the LAST node in the branch. All
   //   volumes/nodes in the branch represented by this physical node are
   //   CLONED so the operation does not affect other possible replicas.
   if (!newmat && !newshape) return;
   TGeoNode *node = GetNode();
   if (node->IsOffset()) {
      Error("Align", "Cannot align division nodes: %s\n",node->GetName());
      return;
   }
   TGeoNode *nnode = 0;
   TGeoVolume *vm = GetVolume(0);
   TGeoVolume *vd = 0;
   Int_t i,id;
   if (!IsAligned()) {
      for (i=0; i<fLevel; i++) {
         // Get daughter node and its id inside vm
         node = GetNode(i+1);
         id = vm->GetIndex(node);
         if (id < 0) {
            Error("Align","cannot align node %s",GetNode(i+1)->GetName());
            return;
         }
         // Clone daughter volume and node
         if (!node->GetVolume()->IsReplicated()) {
            vm = node->GetVolume();
            continue;
         }
         vd = node->GetVolume()->CloneVolume();
         nnode = node->MakeCopyNode();
         // Correct pointers to mother and volume
         nnode->SetVolume(vd);
         nnode->SetMotherVolume(vm);
         // Decouple old node from mother volume and connect new one
         vm->GetNodes()->RemoveAt(id);
         vm->GetNodes()->AddAt(nnode,id);
         fNodes->RemoveAt(i+1);
         fNodes->AddAt(nnode,i+1);
         // Consider new cloned volume as mother and continue
         vm = vd;
      }
   } else {
      nnode = GetNode();
   }
   // Now nnode is a cloned node of the one that need to be aligned
   TGeoNodeMatrix *aligned = (TGeoNodeMatrix*)nnode;
   vm = nnode->GetMotherVolume();
   vd = nnode->GetVolume();
   if (newmat) {
      // Register matrix and make it the active one
      if (!newmat->IsRegistered()) newmat->RegisterYourself();
      aligned->SetMatrix(newmat);
      // Update the global matrix for the aligned node
      TGeoHMatrix *global = GetMatrix();
      TGeoHMatrix *up = GetMatrix(fLevel-1);
      *global = up;
      global->Multiply(newmat);
   }
   // Change the shape for the aligned node
   if (newshape) vd->SetShape(newshape);
   // Now we have to re-voxelize the mother volume
   TGeoVoxelFinder *voxels = vm->GetVoxels();
   if (voxels) voxels->SetNeedRebuild();
   // Eventually check for overlaps
   if (check) vm->CheckOverlaps();
   // clean current matrices from cache
   gGeoManager->CdTop();
   SetAligned(kTRUE);
}

//_____________________________________________________________________________
void TGeoPhysicalNode::cd() const
{

}

//_____________________________________________________________________________
void TGeoPhysicalNode::Draw(Option_t * /*option*/)
{
// Draw this node.
}

//_____________________________________________________________________________
TGeoNode *TGeoPhysicalNode::GetMother(Int_t levup) const
{
// Return parent at LEVUP generation
   Int_t ind = fLevel-levup;
   if (ind<0) return 0;
   return (TGeoNode*)fNodes->UncheckedAt(ind);
}

//_____________________________________________________________________________
TGeoHMatrix *TGeoPhysicalNode::GetMatrix(Int_t level) const
{
// Return global matrix for node at LEVEL.
   if (level<0) return (TGeoHMatrix*)fMatrices->UncheckedAt(fLevel);
   if (level>fLevel) return 0;
   return (TGeoHMatrix*)fMatrices->UncheckedAt(level);
}

//_____________________________________________________________________________
const char *TGeoPhysicalNode::GetName() const
{
// Retreive the name of this physical node
   static TString name;
   name = "";
   for (Int_t level=0;level<fLevel+1; level++) {
      name += "/";
      name += GetNode(level)->GetName();
   }
   return name.Data();
}

//_____________________________________________________________________________
TGeoNode *TGeoPhysicalNode::GetNode(Int_t level) const
{
// Return node in branch at LEVEL. If not specified, return last leaf.
   if (level<0) return (TGeoNode*)fNodes->UncheckedAt(fLevel);
   if (level>fLevel) return 0;
   return (TGeoNode*)fNodes->UncheckedAt(level);
}

//_____________________________________________________________________________
TGeoVolume *TGeoPhysicalNode::GetVolume(Int_t level) const
{
// Return volume associated with node at LEVEL in the branch
   TGeoNode *node = GetNode(level);
   if (node) return node->GetVolume();
   return 0;
}

//_____________________________________________________________________________
TGeoShape *TGeoPhysicalNode::GetShape(Int_t level) const
{
// Return shape associated with volume.
   TGeoVolume *vol = GetVolume(level);
   if (vol) return vol->GetShape();
   return 0;
}

//_____________________________________________________________________________
void TGeoPhysicalNode::Paint(Option_t * /*option*/)
{
// Paint this node and its content according to visualization settings.
   TVirtualGeoPainter *painter = gGeoManager->GetGeomPainter();
   if (!painter) return;
//   painter->PaintNode(this, option);
}

//_____________________________________________________________________________
void TGeoPhysicalNode::SetBranchAsState()
{
// Set node branch according to current state
   TGeoNodeCache *cache = gGeoManager->GetCache();
   if (!cache) {
      Error("SetBranchAsState","no state available");
      return;
   }
   if (!cache->IsDummy()) {
      Error("SetBranchAsState", "not implemented for full cache");
      return;
   }

   if (!fNodes)    fNodes = new TObjArray(30);
   if (!fMatrices) fMatrices = new TObjArray(30);
   fLevel = gGeoManager->GetLevel();
   TGeoHMatrix **matrices = (TGeoHMatrix **) cache->GetMatrices();
   TGeoNode **branch = (TGeoNode **) cache->GetBranch();
   for (Int_t i=0; i<=fLevel; i++) {
      fNodes->AddAt(branch[i],i);
      fMatrices->AddAt(new TGeoHMatrix(*matrices[i]),i);
   }
   TGeoNode *node = (TGeoNode*)fNodes->UncheckedAt(fLevel);
   if (!fMatrixOrig) fMatrixOrig = new TGeoHMatrix();
   *fMatrixOrig = node->GetMatrix();
}

//_____________________________________________________________________________
Bool_t TGeoPhysicalNode::SetPath(const char *path)
{
// Specify the path for this node.
   if (!gGeoManager->cd(path)) {
      Error("SetPath","wrong path -> maybe RestoreMasterVolume");
      return kFALSE;
   }
   SetBranchAsState();
   return kTRUE;
}

<commit_msg>From Andrei: a fix for the problem mentioned by Yuri Fisyak.<commit_after>// @(#)root/geom:$Name:  $:$Id: TGeoPhysicalNode.cxx,v 1.8 2005/11/28 12:55:35 brun Exp $
// Author: Andrei Gheata   17/02/04

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

////////////////////////////////////////////////////////////////////////////////
// TGeoPhysicalNode
//_________

#include "TGeoManager.h"
#include "TGeoCache.h"
#include "TGeoMatrix.h"
#include "TGeoShape.h"
#include "TGeoVolume.h"
#include "TVirtualGeoPainter.h"

#include "TGeoPhysicalNode.h"

// statics and globals

ClassImp(TGeoPhysicalNode)

//_____________________________________________________________________________
TGeoPhysicalNode::TGeoPhysicalNode()
{
// Default constructor
   fLevel        = 0;
   fMatrices     = 0;
   fNodes        = 0;
   fMatrixOrig   = 0;
   SetVisibility(kTRUE);
   SetVisibleFull(kFALSE);
   SetIsVolAtt(kTRUE);
   SetAligned(kFALSE);
}

//_____________________________________________________________________________
TGeoPhysicalNode::TGeoPhysicalNode(const char *path)
{
// Constructor
   if (!strlen(path)) {
      Error("ctor", "path not valid");
      return;
   }
   fLevel  = 0;
   fMatrices = new TObjArray(30);
   fNodes    = new TObjArray(30);
   fMatrixOrig   = 0;
   SetPath(path);
   SetVisibility(kTRUE);
   SetVisibleFull(kFALSE);
   SetIsVolAtt(kTRUE);
   SetAligned(kFALSE);
}

//_____________________________________________________________________________
TGeoPhysicalNode::~TGeoPhysicalNode()
{
// Destructor
   if (fMatrices) {
      fMatrices->Delete();
      delete fMatrices;
   }
   if (fNodes) delete fNodes;
   if (fMatrixOrig) delete fMatrixOrig;
}

//_____________________________________________________________________________
void TGeoPhysicalNode::Align(TGeoMatrix *newmat, TGeoShape *newshape, Bool_t check)
{
   // Align a physical node with a new relative matrix/shape.
   // Example: /TOP_1/A_1/B_1/C_1
   //    node->Align(transl_1, box) will perform:
   //    - change RELATIVE translation of C_1 node (with respect to its
   //      container volume B) to transl_1
   //    - change the shape of the C volume
   // *NOTE* The operations will affect ONLY the LAST node in the branch. All
   //   volumes/nodes in the branch represented by this physical node are
   //   CLONED so the operation does not affect other possible replicas.
   if (!newmat && !newshape) return;
   TGeoNode *node = GetNode();
   if (node->IsOffset()) {
      Error("Align", "Cannot align division nodes: %s\n",node->GetName());
      return;
   }
   TGeoNode *nnode = 0;
   TGeoVolume *vm = GetVolume(0);
   TGeoVolume *vd = 0;
   Int_t i,id;
   if (!IsAligned()) {
      for (i=0; i<fLevel; i++) {
         // Get daughter node and its id inside vm
         node = GetNode(i+1);
         if (id < 0) {
            Error("Align","cannot align node %s",GetNode(i+1)->GetName());
            return;
         }
         // Clone daughter volume and node
         if (!node->GetVolume()->IsReplicated()) {
            vm = node->GetVolume();
            nnode = node;
            continue;
         }
         id = vm->GetIndex(node);
         vd = node->GetVolume()->CloneVolume();
         nnode = node->MakeCopyNode();
         // Correct pointers to mother and volume
         nnode->SetVolume(vd);
         nnode->SetMotherVolume(vm);
         // Decouple old node from mother volume and connect new one
         vm->GetNodes()->RemoveAt(id);
         vm->GetNodes()->AddAt(nnode,id);
         fNodes->RemoveAt(i+1);
         fNodes->AddAt(nnode,i+1);
         // Consider new cloned volume as mother and continue
         vm = vd;
      }
   } else {
      nnode = GetNode();
   }
   // Now nnode is a cloned node of the one that need to be aligned
   TGeoNodeMatrix *aligned = (TGeoNodeMatrix*)nnode;
   vm = nnode->GetMotherVolume();
   vd = nnode->GetVolume();
   if (newmat) {
      // Register matrix and make it the active one
      if (!newmat->IsRegistered()) newmat->RegisterYourself();
      aligned->SetMatrix(newmat);
      // Update the global matrix for the aligned node
      TGeoHMatrix *global = GetMatrix();
      TGeoHMatrix *up = GetMatrix(fLevel-1);
      *global = up;
      global->Multiply(newmat);
   }
   // Change the shape for the aligned node
   if (newshape) vd->SetShape(newshape);
   // Now we have to re-voxelize the mother volume
   TGeoVoxelFinder *voxels = vm->GetVoxels();
   if (voxels) voxels->SetNeedRebuild();
   // Eventually check for overlaps
   if (check) vm->CheckOverlaps();
   // clean current matrices from cache
   gGeoManager->CdTop();
   SetAligned(kTRUE);
}

//_____________________________________________________________________________
void TGeoPhysicalNode::cd() const
{

}

//_____________________________________________________________________________
void TGeoPhysicalNode::Draw(Option_t * /*option*/)
{
// Draw this node.
}

//_____________________________________________________________________________
TGeoNode *TGeoPhysicalNode::GetMother(Int_t levup) const
{
// Return parent at LEVUP generation
   Int_t ind = fLevel-levup;
   if (ind<0) return 0;
   return (TGeoNode*)fNodes->UncheckedAt(ind);
}

//_____________________________________________________________________________
TGeoHMatrix *TGeoPhysicalNode::GetMatrix(Int_t level) const
{
// Return global matrix for node at LEVEL.
   if (level<0) return (TGeoHMatrix*)fMatrices->UncheckedAt(fLevel);
   if (level>fLevel) return 0;
   return (TGeoHMatrix*)fMatrices->UncheckedAt(level);
}

//_____________________________________________________________________________
const char *TGeoPhysicalNode::GetName() const
{
// Retreive the name of this physical node
   static TString name;
   name = "";
   for (Int_t level=0;level<fLevel+1; level++) {
      name += "/";
      name += GetNode(level)->GetName();
   }
   return name.Data();
}

//_____________________________________________________________________________
TGeoNode *TGeoPhysicalNode::GetNode(Int_t level) const
{
// Return node in branch at LEVEL. If not specified, return last leaf.
   if (level<0) return (TGeoNode*)fNodes->UncheckedAt(fLevel);
   if (level>fLevel) return 0;
   return (TGeoNode*)fNodes->UncheckedAt(level);
}

//_____________________________________________________________________________
TGeoVolume *TGeoPhysicalNode::GetVolume(Int_t level) const
{
// Return volume associated with node at LEVEL in the branch
   TGeoNode *node = GetNode(level);
   if (node) return node->GetVolume();
   return 0;
}

//_____________________________________________________________________________
TGeoShape *TGeoPhysicalNode::GetShape(Int_t level) const
{
// Return shape associated with volume.
   TGeoVolume *vol = GetVolume(level);
   if (vol) return vol->GetShape();
   return 0;
}

//_____________________________________________________________________________
void TGeoPhysicalNode::Paint(Option_t * /*option*/)
{
// Paint this node and its content according to visualization settings.
   TVirtualGeoPainter *painter = gGeoManager->GetGeomPainter();
   if (!painter) return;
//   painter->PaintNode(this, option);
}

//_____________________________________________________________________________
void TGeoPhysicalNode::SetBranchAsState()
{
// Set node branch according to current state
   TGeoNodeCache *cache = gGeoManager->GetCache();
   if (!cache) {
      Error("SetBranchAsState","no state available");
      return;
   }
   if (!cache->IsDummy()) {
      Error("SetBranchAsState", "not implemented for full cache");
      return;
   }

   if (!fNodes)    fNodes = new TObjArray(30);
   if (!fMatrices) fMatrices = new TObjArray(30);
   fLevel = gGeoManager->GetLevel();
   TGeoHMatrix **matrices = (TGeoHMatrix **) cache->GetMatrices();
   TGeoNode **branch = (TGeoNode **) cache->GetBranch();
   for (Int_t i=0; i<=fLevel; i++) {
      fNodes->AddAt(branch[i],i);
      fMatrices->AddAt(new TGeoHMatrix(*matrices[i]),i);
   }
   TGeoNode *node = (TGeoNode*)fNodes->UncheckedAt(fLevel);
   if (!fMatrixOrig) fMatrixOrig = new TGeoHMatrix();
   *fMatrixOrig = node->GetMatrix();
}

//_____________________________________________________________________________
Bool_t TGeoPhysicalNode::SetPath(const char *path)
{
// Specify the path for this node.
   if (!gGeoManager->cd(path)) {
      Error("SetPath","wrong path -> maybe RestoreMasterVolume");
      return kFALSE;
   }
   SetBranchAsState();
   return kTRUE;
}

<|endoftext|>


<commit_before>/*
    Copyright 2010 Google Inc.

    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

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
 */

#include "GrVertexBufferAllocPool.h"
#include "GrVertexBuffer.h"
#include "GrGpu.h"

#define GrVertexBufferAllocPool_MIN_BLOCK_SIZE      ((size_t)1 << 10)

GrVertexBufferAllocPool::GrVertexBufferAllocPool(GrGpu* gpu,
                                                 size_t blockSize,
                                                 int preallocBufferCnt) :
        fBlocks(GrMax(8, 2*preallocBufferCnt)) {
    GrAssert(NULL != gpu);
    fGpu = gpu;
    fGpu->ref();
    fBufferPtr = NULL;
    fMinBlockSize = GrMax(GrVertexBufferAllocPool_MIN_BLOCK_SIZE, blockSize);

    fPreallocBuffersInUse = 0;
    fFirstPreallocBuffer = 0;
    for (int i = 0; i < preallocBufferCnt; ++i) {
        GrVertexBuffer* buffer = gpu->createVertexBuffer(fMinBlockSize, true);
        if (NULL != buffer) {
            *fPreallocBuffers.append() = buffer;
            buffer->ref();
        }
    }
}

GrVertexBufferAllocPool::~GrVertexBufferAllocPool() {
    fPreallocBuffers.unrefAll();
    while (!fBlocks.empty()) {
        destroyBlock();
    }
    fGpu->unref();
}

void GrVertexBufferAllocPool::reset() {
    while (!fBlocks.empty()) {
        destroyBlock();
    }
    if (fPreallocBuffers.count()) {
        // must set this after above loop.
        fFirstPreallocBuffer = (fFirstPreallocBuffer + fPreallocBuffersInUse) %
                               fPreallocBuffers.count();
    }
    GrAssert(0 == fPreallocBuffersInUse);
}

void GrVertexBufferAllocPool::unlock() {
    GrAssert((NULL == fBufferPtr) ? (!fBlocks.empty() ||
                                     !fBlocks.back().fVertexBuffer->isLocked()) :
                                    (!fBlocks.empty() &&
                                     fBlocks.back().fVertexBuffer->isLocked()));
    if (NULL != fBufferPtr) {
        GrAssert(!fBlocks.empty());
        GrAssert(fBlocks.back().fVertexBuffer->isLocked());
        fBufferPtr = NULL;
        fBlocks.back().fVertexBuffer->unlock();
    }
#if GR_DEBUG
    for (uint32_t i = 0; i < fBlocks.count(); ++i) {
        GrAssert(!fBlocks[i].fVertexBuffer->isLocked());
    }
#endif
}

void* GrVertexBufferAllocPool::alloc(GrVertexLayout layout,
                                     uint32_t vertexCount,
                                     GrVertexBuffer** buffer,
                                     uint32_t* startVertex) {
    GrAssert(NULL != buffer);
    size_t vSize = GrDrawTarget::VertexSize(layout);
    size_t bytes = vSize * vertexCount;

    if (NULL != fBufferPtr) {
        GrAssert(!fBlocks.empty());
        GrAssert(fBlocks.back().fVertexBuffer->isLocked());
        BufferBlock& back = fBlocks.back();
        uint32_t usedBytes = back.fVertexBuffer->size() - back.fBytesFree;
        uint32_t pad = GrUIAlignUpPad(usedBytes, layout);
        if ((bytes + pad) <= back.fBytesFree) {
            usedBytes += pad;
            *startVertex = usedBytes / vSize;
            *buffer = back.fVertexBuffer;
            back.fBytesFree -= bytes + pad;
            return (void*)((intptr_t)fBufferPtr + usedBytes);
        }
    }

    if (!createBlock(GrMax(bytes, fMinBlockSize))) {
        return NULL;
    }
    *startVertex = 0;
    GrAssert(NULL != fBufferPtr);
    BufferBlock& back = fBlocks.back();
    *buffer = back.fVertexBuffer;
    back.fBytesFree -= bytes;
    return fBufferPtr;
}

int GrVertexBufferAllocPool::currentBufferVertices(GrVertexLayout layout) const {
    if (NULL != fBufferPtr) {
        GrAssert(!fBlocks.empty());
        const BufferBlock& back = fBlocks.back();
        GrAssert(back.fVertexBuffer->isLocked());
        return back.fBytesFree / GrDrawTarget::VertexSize(layout);
    } else if (fPreallocBuffersInUse < fPreallocBuffers.count()) {
        return fMinBlockSize / GrDrawTarget::VertexSize(layout);
    }
    return 0;
}

int GrVertexBufferAllocPool::preallocatedBuffersRemaining() const {
    return fPreallocBuffers.count() - fPreallocBuffersInUse;
}

int GrVertexBufferAllocPool::preallocatedBufferVertices(GrVertexLayout layout) const {
    return fPreallocBuffers.count() ?
                        (fMinBlockSize / GrDrawTarget::VertexSize(layout)) :
                        0;
}

int GrVertexBufferAllocPool::preallocatedBufferCount() const {
    return fPreallocBuffers.count();
}

void GrVertexBufferAllocPool::release(size_t bytes) {
    if (NULL != fBufferPtr) {
        GrAssert(!fBlocks.empty());
        BufferBlock& back = fBlocks.back();
        GrAssert(back.fVertexBuffer->isLocked());
        size_t bytesUsed = back.fVertexBuffer->size() - back.fBytesFree;
        if (bytes >= bytesUsed) {
            destroyBlock();
            bytes -= bytesUsed;
        } else {
            back.fBytesFree += bytes;
            return;
        }
    }
    GrAssert(NULL == fBufferPtr);
    GrAssert(fBlocks.empty() ||
             !fBlocks.back().fVertexBuffer->isLocked());
    // we don't honor release if it is within an already unlocked VB
    // Our VB semantics say locking a VB discards its previous content
    while (!fBlocks.empty() &&
           bytes >= fBlocks.back().fVertexBuffer->size()) {
        bytes -= fBlocks.back().fVertexBuffer->size();
        destroyBlock();
    }
}

bool GrVertexBufferAllocPool::createBlock(size_t size) {
    GrAssert(size >= GrVertexBufferAllocPool_MIN_BLOCK_SIZE);

    BufferBlock& block = fBlocks.push_back();

    if (size == fMinBlockSize &&
        fPreallocBuffersInUse < fPreallocBuffers.count()) {

        uint32_t nextBuffer = (fPreallocBuffersInUse + fFirstPreallocBuffer) %
                              fPreallocBuffers.count();
        block.fVertexBuffer = fPreallocBuffers[nextBuffer];
        block.fVertexBuffer->ref();
        ++fPreallocBuffersInUse;
    } else {
        block.fVertexBuffer = fGpu->createVertexBuffer(size, true);
        if (NULL == block.fVertexBuffer) {
            fBlocks.pop_back();
            return false;
        }
    }

    block.fBytesFree = size;
    if (NULL != fBufferPtr) {
        GrAssert(fBlocks.count() > 1);
        BufferBlock& prev = fBlocks.fromBack(1);
        GrAssert(prev.fVertexBuffer->isLocked());
        fBufferPtr = NULL;
        prev.fVertexBuffer->unlock();
    }
    fBufferPtr = block.fVertexBuffer->lock();
    return true;
}

void GrVertexBufferAllocPool::destroyBlock() {
    GrAssert(!fBlocks.empty());

    BufferBlock& block = fBlocks.back();
    if (fPreallocBuffersInUse > 0) {
        uint32_t prevPreallocBuffer = (fPreallocBuffersInUse +
                                       fFirstPreallocBuffer +
                                       (fPreallocBuffers.count() - 1)) %
                                      fPreallocBuffers.count();
        if (block.fVertexBuffer == fPreallocBuffers[prevPreallocBuffer]) {
            --fPreallocBuffersInUse;
        }
    }
    block.fVertexBuffer->unref();
    fBlocks.pop_back();
    fBufferPtr = NULL;
}

<commit_msg>Should be calculating alignment based on the vertex size.<commit_after>/*
    Copyright 2010 Google Inc.

    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

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
 */

#include "GrVertexBufferAllocPool.h"
#include "GrVertexBuffer.h"
#include "GrGpu.h"

#define GrVertexBufferAllocPool_MIN_BLOCK_SIZE      ((size_t)1 << 10)

GrVertexBufferAllocPool::GrVertexBufferAllocPool(GrGpu* gpu,
                                                 size_t blockSize,
                                                 int preallocBufferCnt) :
        fBlocks(GrMax(8, 2*preallocBufferCnt)) {
    GrAssert(NULL != gpu);
    fGpu = gpu;
    fGpu->ref();
    fBufferPtr = NULL;
    fMinBlockSize = GrMax(GrVertexBufferAllocPool_MIN_BLOCK_SIZE, blockSize);

    fPreallocBuffersInUse = 0;
    fFirstPreallocBuffer = 0;
    for (int i = 0; i < preallocBufferCnt; ++i) {
        GrVertexBuffer* buffer = gpu->createVertexBuffer(fMinBlockSize, true);
        if (NULL != buffer) {
            *fPreallocBuffers.append() = buffer;
            buffer->ref();
        }
    }
}

GrVertexBufferAllocPool::~GrVertexBufferAllocPool() {
    fPreallocBuffers.unrefAll();
    while (!fBlocks.empty()) {
        destroyBlock();
    }
    fGpu->unref();
}

void GrVertexBufferAllocPool::reset() {
    while (!fBlocks.empty()) {
        destroyBlock();
    }
    if (fPreallocBuffers.count()) {
        // must set this after above loop.
        fFirstPreallocBuffer = (fFirstPreallocBuffer + fPreallocBuffersInUse) %
                               fPreallocBuffers.count();
    }
    GrAssert(0 == fPreallocBuffersInUse);
}

void GrVertexBufferAllocPool::unlock() {
    GrAssert((NULL == fBufferPtr) ? (!fBlocks.empty() ||
                                     !fBlocks.back().fVertexBuffer->isLocked()) :
                                    (!fBlocks.empty() &&
                                     fBlocks.back().fVertexBuffer->isLocked()));
    if (NULL != fBufferPtr) {
        GrAssert(!fBlocks.empty());
        GrAssert(fBlocks.back().fVertexBuffer->isLocked());
        fBufferPtr = NULL;
        fBlocks.back().fVertexBuffer->unlock();
    }
#if GR_DEBUG
    for (uint32_t i = 0; i < fBlocks.count(); ++i) {
        GrAssert(!fBlocks[i].fVertexBuffer->isLocked());
    }
#endif
}

void* GrVertexBufferAllocPool::alloc(GrVertexLayout layout,
                                     uint32_t vertexCount,
                                     GrVertexBuffer** buffer,
                                     uint32_t* startVertex) {
    GrAssert(NULL != buffer);
    size_t vSize = GrDrawTarget::VertexSize(layout);
    size_t bytes = vSize * vertexCount;

    if (NULL != fBufferPtr) {
        GrAssert(!fBlocks.empty());
        GrAssert(fBlocks.back().fVertexBuffer->isLocked());
        BufferBlock& back = fBlocks.back();
        uint32_t usedBytes = back.fVertexBuffer->size() - back.fBytesFree;
        uint32_t pad = GrUIAlignUpPad(usedBytes,
                                      GrDrawTarget::VertexSize(layout));
        if ((bytes + pad) <= back.fBytesFree) {
            usedBytes += pad;
            *startVertex = usedBytes / vSize;
            *buffer = back.fVertexBuffer;
            back.fBytesFree -= bytes + pad;
            return (void*)((intptr_t)fBufferPtr + usedBytes);
        }
    }

    if (!createBlock(GrMax(bytes, fMinBlockSize))) {
        return NULL;
    }
    *startVertex = 0;
    GrAssert(NULL != fBufferPtr);
    BufferBlock& back = fBlocks.back();
    *buffer = back.fVertexBuffer;
    back.fBytesFree -= bytes;
    return fBufferPtr;
}

int GrVertexBufferAllocPool::currentBufferVertices(GrVertexLayout layout) const {
    if (NULL != fBufferPtr) {
        GrAssert(!fBlocks.empty());
        const BufferBlock& back = fBlocks.back();
        GrAssert(back.fVertexBuffer->isLocked());
        return back.fBytesFree / GrDrawTarget::VertexSize(layout);
    } else if (fPreallocBuffersInUse < fPreallocBuffers.count()) {
        return fMinBlockSize / GrDrawTarget::VertexSize(layout);
    }
    return 0;
}

int GrVertexBufferAllocPool::preallocatedBuffersRemaining() const {
    return fPreallocBuffers.count() - fPreallocBuffersInUse;
}

int GrVertexBufferAllocPool::preallocatedBufferVertices(GrVertexLayout layout) const {
    return fPreallocBuffers.count() ?
                        (fMinBlockSize / GrDrawTarget::VertexSize(layout)) :
                        0;
}

int GrVertexBufferAllocPool::preallocatedBufferCount() const {
    return fPreallocBuffers.count();
}

void GrVertexBufferAllocPool::release(size_t bytes) {
    if (NULL != fBufferPtr) {
        GrAssert(!fBlocks.empty());
        BufferBlock& back = fBlocks.back();
        GrAssert(back.fVertexBuffer->isLocked());
        size_t bytesUsed = back.fVertexBuffer->size() - back.fBytesFree;
        if (bytes >= bytesUsed) {
            destroyBlock();
            bytes -= bytesUsed;
        } else {
            back.fBytesFree += bytes;
            return;
        }
    }
    GrAssert(NULL == fBufferPtr);
    GrAssert(fBlocks.empty() ||
             !fBlocks.back().fVertexBuffer->isLocked());
    // we don't honor release if it is within an already unlocked VB
    // Our VB semantics say locking a VB discards its previous content
    while (!fBlocks.empty() &&
           bytes >= fBlocks.back().fVertexBuffer->size()) {
        bytes -= fBlocks.back().fVertexBuffer->size();
        destroyBlock();
    }
}

bool GrVertexBufferAllocPool::createBlock(size_t size) {
    GrAssert(size >= GrVertexBufferAllocPool_MIN_BLOCK_SIZE);

    BufferBlock& block = fBlocks.push_back();

    if (size == fMinBlockSize &&
        fPreallocBuffersInUse < fPreallocBuffers.count()) {

        uint32_t nextBuffer = (fPreallocBuffersInUse + fFirstPreallocBuffer) %
                              fPreallocBuffers.count();
        block.fVertexBuffer = fPreallocBuffers[nextBuffer];
        block.fVertexBuffer->ref();
        ++fPreallocBuffersInUse;
    } else {
        block.fVertexBuffer = fGpu->createVertexBuffer(size, true);
        if (NULL == block.fVertexBuffer) {
            fBlocks.pop_back();
            return false;
        }
    }

    block.fBytesFree = size;
    if (NULL != fBufferPtr) {
        GrAssert(fBlocks.count() > 1);
        BufferBlock& prev = fBlocks.fromBack(1);
        GrAssert(prev.fVertexBuffer->isLocked());
        fBufferPtr = NULL;
        prev.fVertexBuffer->unlock();
    }
    fBufferPtr = block.fVertexBuffer->lock();
    return true;
}

void GrVertexBufferAllocPool::destroyBlock() {
    GrAssert(!fBlocks.empty());

    BufferBlock& block = fBlocks.back();
    if (fPreallocBuffersInUse > 0) {
        uint32_t prevPreallocBuffer = (fPreallocBuffersInUse +
                                       fFirstPreallocBuffer +
                                       (fPreallocBuffers.count() - 1)) %
                                      fPreallocBuffers.count();
        if (block.fVertexBuffer == fPreallocBuffers[prevPreallocBuffer]) {
            --fPreallocBuffersInUse;
        }
    }
    block.fVertexBuffer->unref();
    fBlocks.pop_back();
    fBufferPtr = NULL;
}

<|endoftext|>


<commit_before>// @(#)root/gviz3d:$Id$
// Author: Tomasz Sosnicki   18/09/09

/************************************************************************
* Copyright (C) 1995-2009, Rene Brun and Fons Rademakers.               *
* All rights reserved.                                                  *
*                                                                       *
* For the licensing terms see $ROOTSYS/LICENSE.                         *
* For the list of contributors see $ROOTSYS/README/CREDITS.             *
*************************************************************************/

#include "TStructViewer.h"
#include "TStructNodeProperty.h"
#include "TStructViewerGUI.h"
#include "TStructNode.h"

#include <TDataMember.h>
#include <TVirtualCollectionProxy.h>

ClassImp(TStructViewer);

//________________________________________________________________________
//////////////////////////////////////////////////////////////////////////
//
// TStructViewer viewer represents class, struct or other type as an object in 3D space.
// At the top of the scene we can see objects which is our pointer. Under it we see
// pointers and collection elements. Collection must inherit from TCollection
// or be STL collecion.
//
// We can change the number of visible levels or objects on the scene with the  GUI or
// methods. The size of geometry objects is proportional to the memory taken by this object
// or to the number of members inside this object.
//
// An easy way to find some class in the viewer is to change the color of the type.
// We can connect for example a TF2 class with red color or connect all classes
// inheriting from TF2 by adding plus to name. For example typename "TF2+" tells us
// that all classes inheriting from TF2 will be red.
//
// Navigation in viewer is very simple like in usual GLViewer. When you put the mouse over
// some object you can see some information about it (e.g. name, size, actual level).
// When you double click this object, it becames top object on scene.
// Undo and redo operation are supported.
//
//
//////////////////////////////////////////////////////////////////////////

//________________________________________________________________________
TStructViewer::TStructViewer(TObject* ptr)
{
   // Default constructor. An argument "ptr" is a main pointer to TObject, which should be shown in the viewer

   fTopNode = NULL;

   // add default color
   fColors.Add(new TStructNodeProperty("+", 17));

   fPointer = ptr;
   Prepare();

   // creating GUI
   fGUI = new TStructViewerGUI(this, fTopNode, &fColors);
}

//________________________________________________________________________
TStructViewer::~TStructViewer()
{
   // Destructor. Clean all object after closing the viewer

   Reset();
}

//________________________________________________________________________
void TStructViewer::AddNode(TStructNode* node, ULong_t size)
{
   // Find list with nodes on specified level and add node to this list and increment list of sizes and list of members

   TList* list = (TList*)fLevelArray[node->GetLevel()];
   // if list doesn't exist -> create one
   if(!list) {
      fLevelArray[node->GetLevel()] = list = new TList();
   }
   list->Add(node);

   // increase number of members on this level
   fLevelMembersCount(node->GetLevel())++;
   // increase size of this level
   fLevelSize(node->GetLevel()) += size;
}

//________________________________________________________________________
void TStructViewer::CountMembers(TClass* cl, TStructNode* parent, void* pointer)
{
   // Count allocated memory, increase member counters, find child nodes

   if(!cl) {
      return;
   }

   if (cl->InheritsFrom("TClass")) {
      return;
   }

   //////////////////////////////////////////////////////////////////////////
   // DATA MEMBERS
   //////////////////////////////////////////////////////////////////////////
   // Set up list of RealData so TClass doesn't create a new object itself
   cl->BuildRealData(parent->GetPointer());
   TIter it(cl->GetListOfDataMembers());
   TDataMember* dm;
   while ((dm = (TDataMember*) it() ))
   {
      // increase counters in parent node
      parent->SetAllMembersCount(parent->GetAllMembersCount() + 1);
      parent->SetMembersCount(parent->GetMembersCount() + 1);

      if (dm->Property() & kIsStatic) {
         continue;
      }

      ENodeType type;
      if(dm->GetDataType()) {   // pointer to basic type
         type = kBasic;
      } else if (dm->IsSTLContainer() == TDataMember::kVector) {
         type = kSTLCollection;

//             it works only for pointer in std object (not pointer)
//             TClass* stlClass = TClass::GetClass(dm->GetTypeName());
//             if (!stlClass) {
//                continue;
//             }
//
//             TVirtualCollectionProxy* proxy = stlClass->GetCollectionProxy();
//             if (!proxy) {
//                continue;
//             }
//             void* ptr = (void*)((ULong_t)pointer + dm->GetOffset());
//             TVirtualCollectionProxy::TPushPop helper(proxy, ptr);
//
//             UInt_t count = proxy->Size();
//             parent->SetMembersCount(parent->GetMembersCount() + count);
//
//             if(!proxy->HasPointers() || proxy->GetType()) { // only objects or pointers to basic type
//                parent->SetTotalSize(parent->GetTotalSize() + count * proxy->Sizeof());
//                parent->SetAllMembersCount(parent->GetAllMembersCount() + count);
//             } else {
//                void* element;
//                for (UInt_t i = 0; i < count ; i++) {
//                   element = *(void**)proxy->At(i);
//
//                   if (!element) {
//                      continue;
//                   }
//
//                   // get size of element
//                   ULong_t size = 0;
//                   TClass* clProxy = proxy->GetValueClass();
//                   const char * name = "name";
//                   if (clProxy) {
//                      if (clProxy->InheritsFrom("TNamed")) {
//                         name = ((TNamed*) element)->GetName();
//                      } else {
//                         name = clProxy->GetName();
//                      }
//
//                      size = clProxy->Size();
//
//                   }
//
//                   // if there is no dictionary
//                   if (size == 0) {
//                      size = proxy->Sizeof();
//                   }
//
//                   // create node
//                   TStructNode* node = new TStructNode(name, name, element, parent, size, kClass);
//                   // add addition information
//                   AddNode(node, size);
//                   // increase parents counter
//                   parent->SetMembersCount(parent->GetMembersCount() + 1);
//
//                   //CountMembers(clProxy, node);
//
//                   parent->SetTotalSize(parent->GetTotalSize() + node->GetTotalSize());
//                   parent->SetAllMembersCount(parent->GetAllMembersCount() + node->GetAllMembersCount());
//                }
//             }
      } else {
         type = kClass;
      }

      if(dm->IsaPointer()) {
         TString trueTypeName = dm->GetTrueTypeName();

         // skip if pointer to pointer
         if(trueTypeName.CountChar('*') > 1) {
            continue;
         }

         if (!pointer) {
            continue;
         }

         void** pptr = (void**)((ULong_t)pointer + dm->GetOffset());
         void* ptr = *pptr;

         if (!ptr) {
            continue;
         }

         if(fPointers.GetValue((ULong_t)ptr)) {
            continue;
         } else {
            fPointers.Add((ULong_t)ptr, (ULong_t)ptr);
         }

         ULong_t size = 0;
         if (TClass* cl2 = TClass::GetClass(dm->GetTypeName())) {
            size = cl2->Size();
         }

         if(size == 0) {
            size = dm->GetUnitSize();
         }

         // creating TStructNode
         TStructNode* node = new TStructNode(dm->GetName(), dm->GetTypeName(), ptr, parent, size, type);
         AddNode(node, size);

         CountMembers(TClass::GetClass(dm->GetTypeName()), node, ptr);

         // total size = size of parent + size of nodes daughters
         parent->SetTotalSize(parent->GetTotalSize() + node->GetTotalSize() - size);
         // all members of node = all nodes of parent + nodes of daughter - 1 because node is added twice
         parent->SetAllMembersCount(parent->GetAllMembersCount() + node->GetAllMembersCount() - 1);
      } else {
         void* ptr = (void*)((ULong_t)pointer + dm->GetOffset());

         if (!ptr) {
            continue;
         }
         CountMembers(TClass::GetClass(dm->GetTypeName()), parent, ptr);
      }
   }

   //////////////////////////////////////////////////////////////////////////
   // COLLECTION
   //////////////////////////////////////////////////////////////////////////
   // if our parent node is collection
   if(cl->InheritsFrom("TCollection")) {
      // we change type of node to collection
      parent->SetNodeType(kCollection);

      // return if invalid pointer to collection
      if (!pointer) {
         return;
      }

      TIter it2((TCollection*)pointer);
      TObject* item;
      // loop through all elements in collection
      while((item = it2())) {
         // get size of element
         ULong_t size = 0;
         if (TClass* cl3 = item->IsA()){
            size = cl3->Size();
         }

         // if there is no dictionary
         if (size == 0) {
            size = sizeof(item);
         }

         // create node
         TStructNode* node = new TStructNode(item->GetName(), item->ClassName(), item, parent, size, kClass);
         // add addition information
         AddNode(node, size);
         // increase parents counter
         parent->SetMembersCount(parent->GetMembersCount() + 1);

         CountMembers(item->IsA(), node, item);

         parent->SetTotalSize(parent->GetTotalSize() + node->GetTotalSize());
         parent->SetAllMembersCount(parent->GetAllMembersCount() + node->GetAllMembersCount());
      }
   }
}

//________________________________________________________________________
void TStructViewer::Draw(Option_t *option)
{
   // Draw object if there is valid pointer
   TString opt(option);
   if(opt == "count") {

   } else if (opt == "size") {

   }

   if (fTopNode) {
      fGUI->SetNodePtr(fTopNode);
   } else {

   }
}

//________________________________________________________________________
TCanvas* TStructViewer::GetCanvas()
{
   // Returns canvas used to keep TGeoVolumes

   return fGUI->GetCanvas();
}

//________________________________________________________________________
TGMainFrame* TStructViewer::GetFrame()
{
  // Returns pointer to main window

  return fGUI;
}
//________________________________________________________________________
TObject* TStructViewer::GetPointer() const
{
   // Return main pointer

   return fPointer;
}

//________________________________________________________________________
TExMap TStructViewer::GetLevelMembersCount() const
{
   // Returns TExMap with pairs <level number, number of objects>

   return fLevelMembersCount;
}

//________________________________________________________________________
TExMap TStructViewer::GetLevelSize() const
{
   // Returns TExMap with pairs <level number, size of level in bytes>

   return fLevelSize;
}

//________________________________________________________________________
Bool_t TStructViewer::GetLinksVisibility() const
{
   // Get visibility of links between objects

   return fGUI->GetLinksVisibility();
}

//________________________________________________________________________
void TStructViewer::Prepare()
{
   // Create top node and find all member nodes
   if (fTopNode) {
      Reset();
   }

   ULong_t size = 0;
   if (TClass * cl = fPointer->IsA()) {
      size = cl->Size();
   }

   if(size == 0) {
      size = sizeof(fPointer);
   }

   fTopNode = new TStructNode(fPointer->GetName(), fPointer->ClassName(), fPointer, NULL, size, kClass);
   AddNode(fTopNode, size);
   CountMembers(fPointer->IsA(), fTopNode, fPointer);
}

//________________________________________________________________________
void TStructViewer::Reset()
{
   // Deleting nodes, maps and array

   TList* lst;
   TIter it(&fLevelArray);
   while ((lst = (TList*) it() )) {
      lst->SetOwner();
      lst->Clear();
   }

   // deleting maps and array
   fLevelMembersCount.Clear();
   fLevelSize.Clear();
   fPointers.Clear();
   fLevelArray.Clear();
   fColors.SetOwner();
   fColors.Clear();

   fTopNode = NULL;
}

//________________________________________________________________________
void TStructViewer::SetColor(TString name, Int_t color)
{
   // Sets color for the class "name" to color "color"

   TIter it(&fColors);
   TStructNodeProperty* prop;
   while ((prop = (TStructNodeProperty*) it() )) {
      if (name == prop->GetName()) {
         prop->SetColor(TColor::GetColor(color));
         fGUI->Update();

         return;
      }
   }

   // add color
   prop = new TStructNodeProperty(name.Data(), color);
   fColors.Add(prop);
   fColors.Sort();
}

//________________________________________________________________________
void TStructViewer::SetLinksVisibility(Bool_t val)
{
   // ISets links visibility

   fGUI->SetLinksVisibility(val);
}

//________________________________________________________________________
void TStructViewer::SetPointer(TObject* ptr)
{
   // Set main pointer

   if (ptr) {
      fPointer = ptr;
      Prepare();
      fGUI->SetNodePtr(fTopNode);
   }
}

//________________________________________________________________________
TColor TStructViewer::GetColor(const char* typeName)
{
   // Returns color associated with type "typeName"

   TIter it(&fColors);
   TStructNodeProperty* prop;
   while((prop = (TStructNodeProperty*) it())) {
      if (!strcmp(prop->GetName(), typeName)) {
         return prop->GetColor();
      }
   }

   return TColor();
}
<commit_msg>Fix coding conventions.<commit_after>// @(#)root/gviz3d:$Id$
// Author: Tomasz Sosnicki   18/09/09

/************************************************************************
* Copyright (C) 1995-2009, Rene Brun and Fons Rademakers.               *
* All rights reserved.                                                  *
*                                                                       *
* For the licensing terms see $ROOTSYS/LICENSE.                         *
* For the list of contributors see $ROOTSYS/README/CREDITS.             *
*************************************************************************/

#include "TStructViewer.h"
#include "TStructNodeProperty.h"
#include "TStructViewerGUI.h"
#include "TStructNode.h"

#include <TDataMember.h>
#include <TVirtualCollectionProxy.h>

ClassImp(TStructViewer);

//________________________________________________________________________
//////////////////////////////////////////////////////////////////////////
//
// TStructViewer viewer represents class, struct or other type as an object in 3D space.
// At the top of the scene we can see objects which is our pointer. Under it we see
// pointers and collection elements. Collection must inherit from TCollection
// or be STL collecion.
//
// We can change the number of visible levels or objects on the scene with the  GUI or
// methods. The size of geometry objects is proportional to the memory taken by this object
// or to the number of members inside this object.
//
// An easy way to find some class in the viewer is to change the color of the type.
// We can connect for example a TF2 class with red color or connect all classes
// inheriting from TF2 by adding plus to name. For example typename "TF2+" tells us
// that all classes inheriting from TF2 will be red.
//
// Navigation in viewer is very simple like in usual GLViewer. When you put the mouse over
// some object you can see some information about it (e.g. name, size, actual level).
// When you double click this object, it becames top object on scene.
// Undo and redo operation are supported.
//
//
//////////////////////////////////////////////////////////////////////////

//________________________________________________________________________
TStructViewer::TStructViewer(TObject* ptr)
{
   // Default constructor. An argument "ptr" is a main pointer to TObject, which should be shown in the viewer

   fTopNode = NULL;

   // add default color
   fColors.Add(new TStructNodeProperty("+", 17));

   fPointer = ptr;
   Prepare();

   // creating GUI
   fGUI = new TStructViewerGUI(this, fTopNode, &fColors);
}

//________________________________________________________________________
TStructViewer::~TStructViewer()
{
   // Destructor. Clean all object after closing the viewer

   Reset();
}

//________________________________________________________________________
void TStructViewer::AddNode(TStructNode* node, ULong_t size)
{
   // Find list with nodes on specified level and add node to this list and increment list of sizes and list of members

   TList* list = (TList*)fLevelArray[node->GetLevel()];
   // if list doesn't exist -> create one
   if(!list) {
      fLevelArray[node->GetLevel()] = list = new TList();
   }
   list->Add(node);

   // increase number of members on this level
   fLevelMembersCount(node->GetLevel())++;
   // increase size of this level
   fLevelSize(node->GetLevel()) += size;
}

//________________________________________________________________________
void TStructViewer::CountMembers(TClass* cl, TStructNode* parent, void* pointer)
{
   // Count allocated memory, increase member counters, find child nodes

   if(!cl) {
      return;
   }

   if (cl->InheritsFrom("TClass")) {
      return;
   }

   //////////////////////////////////////////////////////////////////////////
   // DATA MEMBERS
   //////////////////////////////////////////////////////////////////////////
   // Set up list of RealData so TClass doesn't create a new object itself
   cl->BuildRealData(parent->GetPointer());
   TIter it(cl->GetListOfDataMembers());
   TDataMember* dm;
   while ((dm = (TDataMember*) it() ))
   {
      // increase counters in parent node
      parent->SetAllMembersCount(parent->GetAllMembersCount() + 1);
      parent->SetMembersCount(parent->GetMembersCount() + 1);

      if (dm->Property() & kIsStatic) {
         continue;
      }

      ENodeType type;
      if(dm->GetDataType()) {   // pointer to basic type
         type = kBasic;
      } else if (dm->IsSTLContainer() == TDataMember::kVector) {
         type = kSTLCollection;

//             it works only for pointer in std object (not pointer)
//             TClass* stlClass = TClass::GetClass(dm->GetTypeName());
//             if (!stlClass) {
//                continue;
//             }
//
//             TVirtualCollectionProxy* proxy = stlClass->GetCollectionProxy();
//             if (!proxy) {
//                continue;
//             }
//             void* ptr = (void*)((ULong_t)pointer + dm->GetOffset());
//             TVirtualCollectionProxy::TPushPop helper(proxy, ptr);
//
//             UInt_t count = proxy->Size();
//             parent->SetMembersCount(parent->GetMembersCount() + count);
//
//             if(!proxy->HasPointers() || proxy->GetType()) { // only objects or pointers to basic type
//                parent->SetTotalSize(parent->GetTotalSize() + count * proxy->Sizeof());
//                parent->SetAllMembersCount(parent->GetAllMembersCount() + count);
//             } else {
//                void* element;
//                for (UInt_t i = 0; i < count ; i++) {
//                   element = *(void**)proxy->At(i);
//
//                   if (!element) {
//                      continue;
//                   }
//
//                   // get size of element
//                   ULong_t size = 0;
//                   TClass* clProxy = proxy->GetValueClass();
//                   const char * name = "name";
//                   if (clProxy) {
//                      if (clProxy->InheritsFrom("TNamed")) {
//                         name = ((TNamed*) element)->GetName();
//                      } else {
//                         name = clProxy->GetName();
//                      }
//
//                      size = clProxy->Size();
//
//                   }
//
//                   // if there is no dictionary
//                   if (size == 0) {
//                      size = proxy->Sizeof();
//                   }
//
//                   // create node
//                   TStructNode* node = new TStructNode(name, name, element, parent, size, kClass);
//                   // add addition information
//                   AddNode(node, size);
//                   // increase parents counter
//                   parent->SetMembersCount(parent->GetMembersCount() + 1);
//
//                   //CountMembers(clProxy, node);
//
//                   parent->SetTotalSize(parent->GetTotalSize() + node->GetTotalSize());
//                   parent->SetAllMembersCount(parent->GetAllMembersCount() + node->GetAllMembersCount());
//                }
//             }
      } else {
         type = kClass;
      }

      if(dm->IsaPointer()) {
         TString trueTypeName = dm->GetTrueTypeName();

         // skip if pointer to pointer
         if(trueTypeName.CountChar('*') > 1) {
            continue;
         }

         if (!pointer) {
            continue;
         }

         void** pptr = (void**)((ULong_t)pointer + dm->GetOffset());
         void* ptr = *pptr;

         if (!ptr) {
            continue;
         }

         if(fPointers.GetValue((ULong_t)ptr)) {
            continue;
         } else {
            fPointers.Add((ULong_t)ptr, (ULong_t)ptr);
         }

         ULong_t size = 0;
         if (TClass* cl2 = TClass::GetClass(dm->GetTypeName())) {
            size = cl2->Size();
         }

         if(size == 0) {
            size = dm->GetUnitSize();
         }

         // creating TStructNode
         TStructNode* node = new TStructNode(dm->GetName(), dm->GetTypeName(), ptr, parent, size, type);
         AddNode(node, size);

         CountMembers(TClass::GetClass(dm->GetTypeName()), node, ptr);

         // total size = size of parent + size of nodes daughters
         parent->SetTotalSize(parent->GetTotalSize() + node->GetTotalSize() - size);
         // all members of node = all nodes of parent + nodes of daughter - 1 because node is added twice
         parent->SetAllMembersCount(parent->GetAllMembersCount() + node->GetAllMembersCount() - 1);
      } else {
         void* ptr = (void*)((ULong_t)pointer + dm->GetOffset());

         if (!ptr) {
            continue;
         }
         CountMembers(TClass::GetClass(dm->GetTypeName()), parent, ptr);
      }
   }

   //////////////////////////////////////////////////////////////////////////
   // COLLECTION
   //////////////////////////////////////////////////////////////////////////
   // if our parent node is collection
   if(cl->InheritsFrom("TCollection")) {
      // we change type of node to collection
      parent->SetNodeType(kCollection);

      // return if invalid pointer to collection
      if (!pointer) {
         return;
      }

      TIter it2((TCollection*)pointer);
      TObject* item;
      // loop through all elements in collection
      while((item = it2())) {
         // get size of element
         ULong_t size = 0;
         if (TClass* cl3 = item->IsA()){
            size = cl3->Size();
         }

         // if there is no dictionary
         if (size == 0) {
            size = sizeof(item);
         }

         // create node
         TStructNode* node = new TStructNode(item->GetName(), item->ClassName(), item, parent, size, kClass);
         // add addition information
         AddNode(node, size);
         // increase parents counter
         parent->SetMembersCount(parent->GetMembersCount() + 1);

         CountMembers(item->IsA(), node, item);

         parent->SetTotalSize(parent->GetTotalSize() + node->GetTotalSize());
         parent->SetAllMembersCount(parent->GetAllMembersCount() + node->GetAllMembersCount());
      }
   }
}

//________________________________________________________________________
void TStructViewer::Draw(Option_t *option)
{
   // Draw object if there is valid pointer
   TString opt(option);
   if(opt == "count") {

   } else if (opt == "size") {

   }

   if (fTopNode) {
      fGUI->SetNodePtr(fTopNode);
   } else {

   }
}

//________________________________________________________________________
TCanvas* TStructViewer::GetCanvas()
{
   // Returns canvas used to keep TGeoVolumes

   return fGUI->GetCanvas();
}

//________________________________________________________________________
TGMainFrame* TStructViewer::GetFrame()
{
   // Returns pointer to main window

   return fGUI;
}
//________________________________________________________________________
TObject* TStructViewer::GetPointer() const
{
   // Return main pointer

   return fPointer;
}

//________________________________________________________________________
TExMap TStructViewer::GetLevelMembersCount() const
{
   // Returns TExMap with pairs <level number, number of objects>

   return fLevelMembersCount;
}

//________________________________________________________________________
TExMap TStructViewer::GetLevelSize() const
{
   // Returns TExMap with pairs <level number, size of level in bytes>

   return fLevelSize;
}

//________________________________________________________________________
Bool_t TStructViewer::GetLinksVisibility() const
{
   // Get visibility of links between objects

   return fGUI->GetLinksVisibility();
}

//________________________________________________________________________
void TStructViewer::Prepare()
{
   // Create top node and find all member nodes
   if (fTopNode) {
      Reset();
   }

   ULong_t size = 0;
   if (TClass * cl = fPointer->IsA()) {
      size = cl->Size();
   }

   if(size == 0) {
      size = sizeof(fPointer);
   }

   fTopNode = new TStructNode(fPointer->GetName(), fPointer->ClassName(), fPointer, NULL, size, kClass);
   AddNode(fTopNode, size);
   CountMembers(fPointer->IsA(), fTopNode, fPointer);
}

//________________________________________________________________________
void TStructViewer::Reset()
{
   // Deleting nodes, maps and array

   TList* lst;
   TIter it(&fLevelArray);
   while ((lst = (TList*) it() )) {
      lst->SetOwner();
      lst->Clear();
   }

   // deleting maps and array
   fLevelMembersCount.Clear();
   fLevelSize.Clear();
   fPointers.Clear();
   fLevelArray.Clear();
   fColors.SetOwner();
   fColors.Clear();

   fTopNode = NULL;
}

//________________________________________________________________________
void TStructViewer::SetColor(TString name, Int_t color)
{
   // Sets color for the class "name" to color "color"

   TIter it(&fColors);
   TStructNodeProperty* prop;
   while ((prop = (TStructNodeProperty*) it() )) {
      if (name == prop->GetName()) {
         prop->SetColor(TColor::GetColor(color));
         fGUI->Update();

         return;
      }
   }

   // add color
   prop = new TStructNodeProperty(name.Data(), color);
   fColors.Add(prop);
   fColors.Sort();
}

//________________________________________________________________________
void TStructViewer::SetLinksVisibility(Bool_t val)
{
   // ISets links visibility

   fGUI->SetLinksVisibility(val);
}

//________________________________________________________________________
void TStructViewer::SetPointer(TObject* ptr)
{
   // Set main pointer

   if (ptr) {
      fPointer = ptr;
      Prepare();
      fGUI->SetNodePtr(fTopNode);
   }
}

//________________________________________________________________________
TColor TStructViewer::GetColor(const char* typeName)
{
   // Returns color associated with type "typeName"

   TIter it(&fColors);
   TStructNodeProperty* prop;
   while((prop = (TStructNodeProperty*) it())) {
      if (!strcmp(prop->GetName(), typeName)) {
         return prop->GetColor();
      }
   }

   return TColor();
}
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    TestGradientAndVorticity.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.

=========================================================================*/
/*----------------------------------------------------------------------------
 Copyright (c) Sandia Corporation
 See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
----------------------------------------------------------------------------*/

#include "vtkCell.h"
#include "vtkCellData.h"
#include "vtkDoubleArray.h"
#include "vtkGradientFilter.h"
#include "vtkPointData.h"
#include "vtkSmartPointer.h"
#include "vtkStdString.h"
#include "vtkStructuredGrid.h"
#include "vtkStructuredGridReader.h"
#include "vtkUnstructuredGrid.h"
#include "vtkUnstructuredGridReader.h"

#include <vtkstd/vector>

#define VTK_CREATE(type, var) \
  vtkSmartPointer<type> var = vtkSmartPointer<type>::New()

namespace
{
  double Tolerance = 0.00001;
}

//-----------------------------------------------------------------------------
void CreateCellData(vtkDataSet* Grid, int NumberOfComponents, int Offset,
                    const char* ArrayName)
{
  vtkIdType NumberOfCells = Grid->GetNumberOfCells();
  VTK_CREATE(vtkDoubleArray, Array);
  Array->SetNumberOfComponents(NumberOfComponents);
  Array->SetNumberOfTuples(NumberOfCells);
  vtkstd::vector<double> TupleValues(NumberOfComponents);
  double Point[3], ParametricCenter[3], weights[100];
  for(vtkIdType i=0;i<NumberOfCells;i++)
    {
    vtkCell* Cell = Grid->GetCell(i);
    Cell->GetParametricCenter(ParametricCenter);
    int subId = 0;
    Cell->EvaluateLocation(subId, ParametricCenter, Point, weights);
    for(int j=0;j<NumberOfComponents;j++)
      {// +offset makes the curl/vorticity nonzero
      TupleValues[j] = Point[(j+Offset)%3];
      }
    Array->SetTupleValue(i, &TupleValues[0]);
    }
  Array->SetName(ArrayName);
  Grid->GetCellData()->AddArray(Array);
}

//-----------------------------------------------------------------------------
void CreatePointData(vtkDataSet* Grid, int NumberOfComponents, int Offset,
                     const char* ArrayName)
{
  vtkIdType NumberOfPoints = Grid->GetNumberOfPoints();
  VTK_CREATE(vtkDoubleArray, Array);
  Array->SetNumberOfComponents(NumberOfComponents);
  Array->SetNumberOfTuples(NumberOfPoints);
  vtkstd::vector<double> TupleValues(NumberOfComponents);
  double Point[3];
  for(vtkIdType i=0;i<NumberOfPoints;i++)
    {
    Grid->GetPoint(i, Point);
    for(int j=0;j<NumberOfComponents;j++)
      {// +offset makes the curl/vorticity nonzero
      TupleValues[j] = Point[(j+Offset)%3];
      }
    Array->SetTupleValue(i, &TupleValues[0]);
    }
  Array->SetName(ArrayName);
  Grid->GetPointData()->AddArray(Array);
}

//-----------------------------------------------------------------------------
int IsGradientCorrect(vtkDoubleArray* Gradients, int Offset)
{
  int NumberOfComponents = Gradients->GetNumberOfComponents();
  for(vtkIdType i=0;i<Gradients->GetNumberOfTuples();i++)
    {
    double* Values = Gradients->GetTuple(i);
    for(int OrigComp=0;OrigComp<NumberOfComponents/3;OrigComp++)
      {
      for(int GradDir=0;GradDir<3;GradDir++)
        {
        if((OrigComp-GradDir+Offset)%3 == 0)
          {
          if(fabs(Values[OrigComp*3+GradDir]-1.) > Tolerance)
            {
            vtkGenericWarningMacro("Gradient value should be one but is "
                                   << Values[OrigComp*3+GradDir]);
            return 0;
            }
          }
        else if(fabs(Values[OrigComp*3+GradDir]) > Tolerance)
          {
          vtkGenericWarningMacro("Gradient value should be zero but is "
                                 << Values[OrigComp*3+GradDir]);
          return 0;
          }
        }
      }
    }
  return 1;
}

//-----------------------------------------------------------------------------
// we assume that the gradients are correct and so we can compute the "real"
// vorticity from it
int IsVorticityCorrect(vtkDoubleArray* Gradients, vtkDoubleArray* Vorticity)
{
  if(Gradients->GetNumberOfComponents() != 9 ||
     Vorticity->GetNumberOfComponents() != 3)
    {
    vtkGenericWarningMacro("Bad number of components.");
    return 0;
    }
  for(vtkIdType i=0;i<Gradients->GetNumberOfTuples();i++)
    {
    double* g = Gradients->GetTuple(i);
    double* v = Vorticity->GetTuple(i);
    if(v[0] != g[7]-g[5])
      {
      vtkGenericWarningMacro("Bad vorticity[0] value.");
      return 0;
      }
    else if(v[1] != g[2]-g[6])
      {
      vtkGenericWarningMacro("Bad vorticity[1] value.");
      return 0;
      }
    else if(v[2] != g[3]-g[1])
      {
      vtkGenericWarningMacro("Bad vorticity[2] value.");
      return 0;
      }
    }

  return 1;
}

//-----------------------------------------------------------------------------
int PerformTest(vtkDataSet* Grid)
{
  // Cleaning out the existing field data so that I can replace it with
  // an analytic function that I know the gradient of
  Grid->GetPointData()->Initialize();
  Grid->GetCellData()->Initialize();
  const char FieldName[] = "LinearField";
  int Offset = 1;
  int NumberOfComponents = 3;
  CreateCellData(Grid, NumberOfComponents, Offset, FieldName);
  CreatePointData(Grid, NumberOfComponents, Offset, FieldName);

  VTK_CREATE(vtkGradientFilter, CellGradients);
  CellGradients->SetInput(Grid);
  CellGradients->SetInputScalars(
    vtkDataObject::FIELD_ASSOCIATION_CELLS, FieldName);
  const char ResultName[] = "Result";
  CellGradients->SetResultArrayName(ResultName);

  VTK_CREATE(vtkGradientFilter, PointGradients);
  PointGradients->SetInput(Grid);
  PointGradients->SetInputScalars(
    vtkDataObject::FIELD_ASSOCIATION_POINTS, FieldName);
  PointGradients->SetResultArrayName(ResultName);

  CellGradients->Update();
  PointGradients->Update();

  vtkDoubleArray* GradCellArray = vtkDoubleArray::SafeDownCast(
    vtkDataSet::SafeDownCast(
      CellGradients->GetOutput())->GetCellData()->GetArray(ResultName));

  if(!Grid->IsA("vtkUnstructuredGrid"))
    {
    // ignore cell gradients if this is an unstructured grid
    // because the accuracy is so lousy
    if(!IsGradientCorrect(GradCellArray, Offset))
      {
      return 1;
      }
    }

  vtkDoubleArray* GradPointArray = vtkDoubleArray::SafeDownCast(
    vtkDataSet::SafeDownCast(
      PointGradients->GetOutput())->GetPointData()->GetArray(ResultName));

  if(!IsGradientCorrect(GradPointArray, Offset))
    {
    return 1;
    }

  if(NumberOfComponents == 3)
    {
    // now check on the vorticity calculations
    VTK_CREATE(vtkGradientFilter, CellVorticity);
    CellVorticity->SetInput(Grid);
    CellVorticity->SetInputScalars(
      vtkDataObject::FIELD_ASSOCIATION_CELLS, FieldName);
    CellVorticity->SetResultArrayName(ResultName);
    CellVorticity->SetComputeVorticity(1);
    CellVorticity->Update();

    VTK_CREATE(vtkGradientFilter, PointVorticity);
    PointVorticity->SetInput(Grid);
    PointVorticity->SetInputScalars(
      vtkDataObject::FIELD_ASSOCIATION_POINTS, FieldName);
    PointVorticity->SetResultArrayName(ResultName);
    PointVorticity->SetComputeVorticity(1);
    PointVorticity->Update();

    // cell stuff
    vtkDoubleArray* VorticityCellArray = vtkDoubleArray::SafeDownCast(
      vtkDataSet::SafeDownCast(
        CellVorticity->GetOutput())->GetCellData()->GetArray(ResultName));

    if(!IsVorticityCorrect(GradCellArray, VorticityCellArray))
      {
      return 1;
      }

    // point stuff
    vtkDoubleArray* VorticityPointArray = vtkDoubleArray::SafeDownCast(
      vtkDataSet::SafeDownCast(
        PointVorticity->GetOutput())->GetPointData()->GetArray(ResultName));

    if(!IsVorticityCorrect(GradPointArray, VorticityPointArray))
      {
      return 1;
      }
    }

  return 0;
}

//-----------------------------------------------------------------------------
int TestGradientAndVorticity(int argc, char *argv[])
{
  int i;
  // Need to get the data root.
  const char *data_root = NULL;
  for (i = 0; i < argc-1; i++)
    {
    if (strcmp("-D", argv[i]) == 0)
      {
      data_root = argv[i+1];
      break;
      }
    }
  if (!data_root)
    {
    vtkGenericWarningMacro(
      "Need to specify the directory to VTK_DATA_ROOT with -D <dir>.");
    return 1;
    }

  vtkStdString filename;
  filename = data_root;
  filename += "/Data/SampleStructGrid.vtk";
  VTK_CREATE(vtkStructuredGridReader, StructuredGridReader);
  StructuredGridReader->SetFileName(filename.c_str());
  StructuredGridReader->Update();
  vtkDataSet* Grid = vtkDataSet::SafeDownCast(
    StructuredGridReader->GetOutput());

  if(PerformTest(Grid))
    {
    return 1;
    }

  // convert the structured grid to an unstructured grid
  VTK_CREATE(vtkUnstructuredGrid, UG);
  UG->SetPoints(vtkStructuredGrid::SafeDownCast(Grid)->GetPoints());
  UG->Allocate(Grid->GetNumberOfCells());
  for(vtkIdType id=0;id<Grid->GetNumberOfCells();id++)
    {
    vtkCell* Cell = Grid->GetCell(id);
    UG->InsertNextCell(Cell->GetCellType(), Cell->GetPointIds());
    }

  return PerformTest(UG);
}
<commit_msg>STYLE: Added better output for errors.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    TestGradientAndVorticity.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.

=========================================================================*/
/*----------------------------------------------------------------------------
 Copyright (c) Sandia Corporation
 See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
----------------------------------------------------------------------------*/

#include "vtkCell.h"
#include "vtkCellData.h"
#include "vtkDoubleArray.h"
#include "vtkGradientFilter.h"
#include "vtkPointData.h"
#include "vtkSmartPointer.h"
#include "vtkStdString.h"
#include "vtkStructuredGrid.h"
#include "vtkStructuredGridReader.h"
#include "vtkUnstructuredGrid.h"
#include "vtkUnstructuredGridReader.h"

#include <vtkstd/vector>

#define VTK_CREATE(type, var) \
  vtkSmartPointer<type> var = vtkSmartPointer<type>::New()

namespace
{
  double Tolerance = 0.00001;
}

//-----------------------------------------------------------------------------
void CreateCellData(vtkDataSet* Grid, int NumberOfComponents, int Offset,
                    const char* ArrayName)
{
  vtkIdType NumberOfCells = Grid->GetNumberOfCells();
  VTK_CREATE(vtkDoubleArray, Array);
  Array->SetNumberOfComponents(NumberOfComponents);
  Array->SetNumberOfTuples(NumberOfCells);
  vtkstd::vector<double> TupleValues(NumberOfComponents);
  double Point[3], ParametricCenter[3], weights[100];
  for(vtkIdType i=0;i<NumberOfCells;i++)
    {
    vtkCell* Cell = Grid->GetCell(i);
    Cell->GetParametricCenter(ParametricCenter);
    int subId = 0;
    Cell->EvaluateLocation(subId, ParametricCenter, Point, weights);
    for(int j=0;j<NumberOfComponents;j++)
      {// +offset makes the curl/vorticity nonzero
      TupleValues[j] = Point[(j+Offset)%3];
      }
    Array->SetTupleValue(i, &TupleValues[0]);
    }
  Array->SetName(ArrayName);
  Grid->GetCellData()->AddArray(Array);
}

//-----------------------------------------------------------------------------
void CreatePointData(vtkDataSet* Grid, int NumberOfComponents, int Offset,
                     const char* ArrayName)
{
  vtkIdType NumberOfPoints = Grid->GetNumberOfPoints();
  VTK_CREATE(vtkDoubleArray, Array);
  Array->SetNumberOfComponents(NumberOfComponents);
  Array->SetNumberOfTuples(NumberOfPoints);
  vtkstd::vector<double> TupleValues(NumberOfComponents);
  double Point[3];
  for(vtkIdType i=0;i<NumberOfPoints;i++)
    {
    Grid->GetPoint(i, Point);
    for(int j=0;j<NumberOfComponents;j++)
      {// +offset makes the curl/vorticity nonzero
      TupleValues[j] = Point[(j+Offset)%3];
      }
    Array->SetTupleValue(i, &TupleValues[0]);
    }
  Array->SetName(ArrayName);
  Grid->GetPointData()->AddArray(Array);
}

//-----------------------------------------------------------------------------
int IsGradientCorrect(vtkDoubleArray* Gradients, int Offset)
{
  int NumberOfComponents = Gradients->GetNumberOfComponents();
  for(vtkIdType i=0;i<Gradients->GetNumberOfTuples();i++)
    {
    double* Values = Gradients->GetTuple(i);
    for(int OrigComp=0;OrigComp<NumberOfComponents/3;OrigComp++)
      {
      for(int GradDir=0;GradDir<3;GradDir++)
        {
        if((OrigComp-GradDir+Offset)%3 == 0)
          {
          if(fabs(Values[OrigComp*3+GradDir]-1.) > Tolerance)
            {
            vtkGenericWarningMacro("Gradient value should be one but is "
                                   << Values[OrigComp*3+GradDir]);
            return 0;
            }
          }
        else if(fabs(Values[OrigComp*3+GradDir]) > Tolerance)
          {
          vtkGenericWarningMacro("Gradient value should be zero but is "
                                 << Values[OrigComp*3+GradDir]);
          return 0;
          }
        }
      }
    }
  return 1;
}

//-----------------------------------------------------------------------------
// we assume that the gradients are correct and so we can compute the "real"
// vorticity from it
int IsVorticityCorrect(vtkDoubleArray* Gradients, vtkDoubleArray* Vorticity)
{
  if(Gradients->GetNumberOfComponents() != 9 ||
     Vorticity->GetNumberOfComponents() != 3)
    {
    vtkGenericWarningMacro("Bad number of components.");
    return 0;
    }
  for(vtkIdType i=0;i<Gradients->GetNumberOfTuples();i++)
    {
    double* g = Gradients->GetTuple(i);
    double* v = Vorticity->GetTuple(i);
    if(v[0] != g[7]-g[5])
      {
      vtkGenericWarningMacro("Bad vorticity[0] value " << v[0] << " "
                             << g[7]-g[5]);
      return 0;
      }
    else if(v[1] != g[2]-g[6])
      {
      vtkGenericWarningMacro("Bad vorticity[1] value " << v[0] << " "
                             << g[7]-g[5]);
      return 0;
      }
    else if(v[2] != g[3]-g[1])
      {
      vtkGenericWarningMacro("Bad vorticity[2] value " << v[0] << " "
                             << g[7]-g[5]);
      return 0;
      }
    }

  return 1;
}

//-----------------------------------------------------------------------------
int PerformTest(vtkDataSet* Grid)
{
  // Cleaning out the existing field data so that I can replace it with
  // an analytic function that I know the gradient of
  Grid->GetPointData()->Initialize();
  Grid->GetCellData()->Initialize();
  const char FieldName[] = "LinearField";
  int Offset = 1;
  int NumberOfComponents = 3;
  CreateCellData(Grid, NumberOfComponents, Offset, FieldName);
  CreatePointData(Grid, NumberOfComponents, Offset, FieldName);

  VTK_CREATE(vtkGradientFilter, CellGradients);
  CellGradients->SetInput(Grid);
  CellGradients->SetInputScalars(
    vtkDataObject::FIELD_ASSOCIATION_CELLS, FieldName);
  const char ResultName[] = "Result";
  CellGradients->SetResultArrayName(ResultName);

  VTK_CREATE(vtkGradientFilter, PointGradients);
  PointGradients->SetInput(Grid);
  PointGradients->SetInputScalars(
    vtkDataObject::FIELD_ASSOCIATION_POINTS, FieldName);
  PointGradients->SetResultArrayName(ResultName);

  CellGradients->Update();
  PointGradients->Update();

  vtkDoubleArray* GradCellArray = vtkDoubleArray::SafeDownCast(
    vtkDataSet::SafeDownCast(
      CellGradients->GetOutput())->GetCellData()->GetArray(ResultName));

  if(!Grid->IsA("vtkUnstructuredGrid"))
    {
    // ignore cell gradients if this is an unstructured grid
    // because the accuracy is so lousy
    if(!IsGradientCorrect(GradCellArray, Offset))
      {
      return 1;
      }
    }

  vtkDoubleArray* GradPointArray = vtkDoubleArray::SafeDownCast(
    vtkDataSet::SafeDownCast(
      PointGradients->GetOutput())->GetPointData()->GetArray(ResultName));

  if(!IsGradientCorrect(GradPointArray, Offset))
    {
    return 1;
    }

  if(NumberOfComponents == 3)
    {
    // now check on the vorticity calculations
    VTK_CREATE(vtkGradientFilter, CellVorticity);
    CellVorticity->SetInput(Grid);
    CellVorticity->SetInputScalars(
      vtkDataObject::FIELD_ASSOCIATION_CELLS, FieldName);
    CellVorticity->SetResultArrayName(ResultName);
    CellVorticity->SetComputeVorticity(1);
    CellVorticity->Update();

    VTK_CREATE(vtkGradientFilter, PointVorticity);
    PointVorticity->SetInput(Grid);
    PointVorticity->SetInputScalars(
      vtkDataObject::FIELD_ASSOCIATION_POINTS, FieldName);
    PointVorticity->SetResultArrayName(ResultName);
    PointVorticity->SetComputeVorticity(1);
    PointVorticity->Update();

    // cell stuff
    vtkDoubleArray* VorticityCellArray = vtkDoubleArray::SafeDownCast(
      vtkDataSet::SafeDownCast(
        CellVorticity->GetOutput())->GetCellData()->GetArray(ResultName));

    if(!IsVorticityCorrect(GradCellArray, VorticityCellArray))
      {
      return 1;
      }

    // point stuff
    vtkDoubleArray* VorticityPointArray = vtkDoubleArray::SafeDownCast(
      vtkDataSet::SafeDownCast(
        PointVorticity->GetOutput())->GetPointData()->GetArray(ResultName));

    if(!IsVorticityCorrect(GradPointArray, VorticityPointArray))
      {
      return 1;
      }
    }

  return 0;
}

//-----------------------------------------------------------------------------
int TestGradientAndVorticity(int argc, char *argv[])
{
  int i;
  // Need to get the data root.
  const char *data_root = NULL;
  for (i = 0; i < argc-1; i++)
    {
    if (strcmp("-D", argv[i]) == 0)
      {
      data_root = argv[i+1];
      break;
      }
    }
  if (!data_root)
    {
    vtkGenericWarningMacro(
      "Need to specify the directory to VTK_DATA_ROOT with -D <dir>.");
    return 1;
    }

  vtkStdString filename;
  filename = data_root;
  filename += "/Data/SampleStructGrid.vtk";
  VTK_CREATE(vtkStructuredGridReader, StructuredGridReader);
  StructuredGridReader->SetFileName(filename.c_str());
  StructuredGridReader->Update();
  vtkDataSet* Grid = vtkDataSet::SafeDownCast(
    StructuredGridReader->GetOutput());

  if(PerformTest(Grid))
    {
    return 1;
    }

  // convert the structured grid to an unstructured grid
  VTK_CREATE(vtkUnstructuredGrid, UG);
  UG->SetPoints(vtkStructuredGrid::SafeDownCast(Grid)->GetPoints());
  UG->Allocate(Grid->GetNumberOfCells());
  for(vtkIdType id=0;id<Grid->GetNumberOfCells();id++)
    {
    vtkCell* Cell = Grid->GetCell(id);
    UG->InsertNextCell(Cell->GetCellType(), Cell->GetPointIds());
    }

  return PerformTest(UG);
}
<|endoftext|>


<commit_before>/**
 * @file      mips1_syscall.cpp
 * @author    Sandro Rigo
 *            Marcus Bartholomeu
 *
 *            The ArchC Team
 *            http://www.archc.org/
 *
 *            Computer Systems Laboratory (LSC)
 *            IC-UNICAMP
 *            http://www.lsc.ic.unicamp.br/
 *
 * @version   1.0
 * @date      Mon, 19 Jun 2006 15:50:52 -0300
 *
 * @brief     The ArchC MIPS-I functional model.
 *
 * @attention Copyright (C) 2002-2006 --- The ArchC Team
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#include "mips1_syscall.H"
#include "ac_utils.H"

// 'using namespace' statement to allow access to all
// mips1-specific datatypes
using namespace mips1_parms;

void mips1_syscall::get_buffer(int argn, unsigned char* buf, unsigned int size)
{
  unsigned int addr = RB[4+argn];

  for (unsigned int i = 0; i<size; i++, addr++) {
    buf[i] = DM.read_byte(addr);
  }
}

void mips1_syscall::set_buffer(int argn, unsigned char* buf, unsigned int size)
{
  unsigned int addr = RB[4+argn];

//  for (unsigned int i = 0; i<size; i++, addr++) {
//    DM.write_byte(addr, buf[i]);
  for (unsigned int i = 0; i<size; i+=4, addr+=4) {
    DM.write(addr, convert_endian(4, *(unsigned int *) &buf[i], false));
  }
}

void mips1_syscall::set_buffer_noinvert(int argn, unsigned char* buf, unsigned int size)
{
  unsigned int addr = RB[4+argn];

  for (unsigned int i = 0; i<size; i+=4, addr+=4) {
    DM.write(addr, *(unsigned int *) &buf[i]);
  }
}

int mips1_syscall::get_int(int argn)
{
  return RB[4+argn];
}

void mips1_syscall::set_int(int argn, int val)
{
  RB[2+argn] = val;
}

void mips1_syscall::return_from_syscall()
{
  ac_pc = RB[31];
  npc = ac_pc + 4;
}

void mips1_syscall::set_prog_args(int argc, char **argv)
{
  int i, j, base;

  unsigned int ac_argv[30];
  char ac_argstr[512];

  base = AC_RAM_END - 512;
  for (i=0, j=0; i<argc; i++) {
    int len = strlen(argv[i]) + 1;
    ac_argv[i] = base + j;
    memcpy(&ac_argstr[j], argv[i], len);
    j += len;
  }

  //Ajust %sp and write argument string
  RB[29] = AC_RAM_END-512;
  set_buffer(25, (unsigned char*) ac_argstr, 512);   //$25 = $29(sp) - 4 (set_buffer adds 4)

  //Ajust %sp and write string pointers
  RB[29] = AC_RAM_END-512-120;
  set_buffer_noinvert(25, (unsigned char*) ac_argv, 120);

  //Set %sp
  RB[29] = AC_RAM_END-512-128;

  //Set %o0 to the argument count
  RB[4] = argc;

  //Set %o1 to the string pointers
  RB[5] = AC_RAM_END-512-120;
}
<commit_msg>adicionado pilha.<commit_after>/**
 * @file      mips1_syscall.cpp
 * @author    Sandro Rigo
 *            Marcus Bartholomeu
 *
 *            The ArchC Team
 *            http://www.archc.org/
 *
 *            Computer Systems Laboratory (LSC)
 *            IC-UNICAMP
 *            http://www.lsc.ic.unicamp.br/
 *
 * @version   1.0
 * @date      Mon, 19 Jun 2006 15:50:52 -0300
 *
 * @brief     The ArchC MIPS-I functional model.
 *
 * @attention Copyright (C) 2002-2006 --- The ArchC Team
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#include "mips1_syscall.H"
#include "ac_utils.H"

// 'using namespace' statement to allow access to all
// mips1-specific datatypes
using namespace mips1_parms;

void mips1_syscall::get_buffer(int argn, unsigned char* buf, unsigned int size)
{
  unsigned int addr = RB[4+argn];

  for (unsigned int i = 0; i<size; i++, addr++) {
    buf[i] = DM.read_byte(addr);
  }
}

void mips1_syscall::set_buffer(int argn, unsigned char* buf, unsigned int size)
{
  unsigned int addr = RB[4+argn];

//  for (unsigned int i = 0; i<size; i++, addr++) {
//    DM.write_byte(addr, buf[i]);
  for (unsigned int i = 0; i<size; i+=4, addr+=4) {
    DM.write(addr, convert_endian(4, *(unsigned int *) &buf[i], false));
  }
}

void mips1_syscall::set_buffer_noinvert(int argn, unsigned char* buf, unsigned int size)
{
  unsigned int addr = RB[4+argn];

  for (unsigned int i = 0; i<size; i+=4, addr+=4) {
    DM.write(addr, *(unsigned int *) &buf[i]);
  }
}

int mips1_syscall::get_int(int argn)
{
  return RB[4+argn];
}

void mips1_syscall::set_int(int argn, int val)
{
  RB[2+argn] = val;
}

void mips1_syscall::return_from_syscall()
{
  ac_pc = RB[31];
  npc = ac_pc + 4;
}

static unsigned int sp = AC_RAM_END;

void mips1_syscall::set_prog_args(int argc, char **argv)
{
  int i, j, base;

  unsigned int ac_argv[30];
  char ac_argstr[512];

  base = sp - 512;
  for (i=0, j=0; i<argc; i++) {
    int len = strlen(argv[i]) + 1;
    ac_argv[i] = base + j;
    memcpy(&ac_argstr[j], argv[i], len);
    j += len;
  }

  //Ajust %sp and write argument string
  RB[29] = sp-512;
  set_buffer(25, (unsigned char*) ac_argstr, 512);   //$25 = $29(sp) - 4 (set_buffer adds 4)

  //Ajust %sp and write string pointers
  RB[29] = sp-512-120;
  set_buffer_noinvert(25, (unsigned char*) ac_argv, 120);

  //Set %sp
  RB[29] = sp-512-128;

  //Set %o0 to the argument count
  RB[4] = argc;

  //Set %o1 to the string pointers
  RB[5] = sp-512-120;

  sp -= 64*1024;
}
<|endoftext|>