<commit_before>// Copyright 2013-2015 Stanford University
//
// 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 <array>

#include "src/cost/latency.h"

using namespace std;

namespace {

array<stoke::Cost, 3976> latencies_ {{
#include "src/cost/tables/haswell_latency.h"
  }
};

} // namespace

namespace stoke {

LatencyCost::result_type LatencyCost::operator()(const Cfg& cfg, Cost max) {
  Cost latency = 0;

  const auto& code = cfg.get_code();
  for (auto b = ++cfg.reachable_begin(), be = cfg.reachable_end(); b != be; ++b) {
    if (cfg.is_exit(*b)) {
      continue;
    }

    Cost block_latency = 0;
    const auto first = cfg.get_index(Cfg::loc_type(*b, 0));
    for (size_t i = first, ie = first + cfg.num_instrs(*b); i < ie; ++i) {
      // Record latency for non nop instructions
      if (!code[i].is_nop()) {
        block_latency += latencies_[code[i].get_opcode()];
      }
    }

    // Increment latency by block latency scaled by nesting penalty
    // The call to pow() is expensive, so we hide it behind a faster check
    const auto nd = cfg.nesting_depth(*b);
    if (nd > 1) {
      latency += block_latency * pow(nesting_penalty_, cfg.nesting_depth(*b));
    } else {
      latency += block_latency;
    }

    if(latency >= max) {
      return result_type(true, max);
    }
  }

  return result_type(true, latency);
}

} //namespace stoke

<commit_msg>Closes #540<commit_after>// Copyright 2013-2015 Stanford University
//
// 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 <array>

#include "src/cost/latency.h"
#include "src/ext/x64asm/include/x64asm.h"

using namespace std;

namespace {

array<stoke::Cost, X64ASM_NUM_OPCODES> latencies_ {{
#include "src/cost/tables/haswell_latency.h"
  }
};

} // namespace

namespace stoke {

LatencyCost::result_type LatencyCost::operator()(const Cfg& cfg, Cost max) {
  Cost latency = 0;

  const auto& code = cfg.get_code();
  for (auto b = ++cfg.reachable_begin(), be = cfg.reachable_end(); b != be; ++b) {
    if (cfg.is_exit(*b)) {
      continue;
    }

    Cost block_latency = 0;
    const auto first = cfg.get_index(Cfg::loc_type(*b, 0));
    for (size_t i = first, ie = first + cfg.num_instrs(*b); i < ie; ++i) {
      // Record latency for non nop instructions
      if (!code[i].is_nop()) {
        block_latency += latencies_[code[i].get_opcode()];
      }
    }

    // Increment latency by block latency scaled by nesting penalty
    // The call to pow() is expensive, so we hide it behind a faster check
    const auto nd = cfg.nesting_depth(*b);
    if (nd > 1) {
      latency += block_latency * pow(nesting_penalty_, cfg.nesting_depth(*b));
    } else {
      latency += block_latency;
    }

    if(latency >= max) {
      return result_type(true, max);
    }
  }

  return result_type(true, latency);
}

} //namespace stoke

<|endoftext|>


<commit_before>// $Id$

//**************************************************************************
//* This file is property of and copyright by the ALICE HLT Project        *
//* ALICE Experiment at CERN, All rights reserved.                         *
//*                                                                        *
//* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
//*                  for The ALICE HLT Project.                            *
//*                                                                        *
//* 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.                  *
//**************************************************************************

//  @file   AliHLTITSAgent.cxx
//  @author Matthias Richter
//  @date   25.08.2008
//  @brief  Agent of the libAliHLTITS library
//  @note

#include <cassert>
#include "AliHLTITSAgent.h"
#include "AliHLTConfiguration.h"
#include "AliHLTOUT.h"
#include "AliHLTDAQ.h"

// header files of library components
#include "AliHLTITSCompressRawDataSDDComponent.h"
#include "AliHLTITSSSDQARecPointsComponent.h"
#include "AliHLTITSQAComponent.h"
#include "AliHLTITSClusterFinderComponent.h"
#include "AliHLTITSClusterHistoComponent.h"
#include "AliHLTITSTrackerComponent.h"
#include "AliHLTITSVertexerSPDComponent.h"
#include "AliHLTITSDigitPublisherComponent.h"

// header file of the module preprocessor
// none at the moment

/** global instance for agent registration */
AliHLTITSAgent gAliHLTITSAgent;

/** ROOT macro for the implementation of ROOT specific class methods */
ClassImp(AliHLTITSAgent)

AliHLTITSAgent::AliHLTITSAgent()
  :
  AliHLTModuleAgent("ITS"),
  fRawDataHandler(NULL)
{
  // see header file for class documentation
  // or
  // refer to README to build package
  // or
  // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
}

AliHLTITSAgent::~AliHLTITSAgent()
{
  // see header file for class documentation
}

int AliHLTITSAgent::CreateConfigurations(AliHLTConfigurationHandler* handler,
					 AliRawReader* rawReader,
					 AliRunLoader* runloader) const
{
  // see header file for class documentation
  int iResult=0;
  if (!handler) return -EINVAL;

  ///////////////////////////////////////////////////////////////////////////////////////////////////
  ///////////////////////////////////////////////////////////////////////////////////////////////////
  //
  // ITS tracking is currently only working on raw data
  // to run on digits, a digit publisher needs to be implemented

  TString trackerInput="";
  TString vertexerSPDInput="";
  if (rawReader || !runloader) {
    // AliSimulation: use the AliRawReaderPublisher if the raw reader is available
    // Alireconstruction: indicated by runloader==NULL, run always on raw data

    ///////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // define the ITS cluster finder configurations
    //

    TString spdCF;
    TString ssdCF;
    TString sddCF;

    iResult=CreateCFConfigurations(handler, AliHLTDAQ::DetectorID("ITSSPD"), spdCF);
    handler->CreateConfiguration("ITS-SPD-CF","BlockFilter",spdCF.Data(),"");

    iResult=CreateCFConfigurations(handler, AliHLTDAQ::DetectorID("ITSSDD"), sddCF);
    handler->CreateConfiguration("ITS-SDD-CF","BlockFilter",sddCF.Data(),"");

    iResult=CreateCFConfigurations(handler, AliHLTDAQ::DetectorID("ITSSSD"), ssdCF);
    handler->CreateConfiguration("ITS-SSD-CF","BlockFilter",ssdCF.Data(),"");

    ///////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // define the SPD vertexer Z input
    //
    vertexerSPDInput="ITS-SPD-CF";

    ///////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // define the ITS tracker input
    //
    trackerInput="ITS-SPD-CF ITS-SDD-CF ITS-SSD-CF";
  }
  else if (runloader && !rawReader) {
    // indicates AliSimulation with no RawReader available -> run on digits

    ///////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // define the Digit Publisher and ITS cluster finder configuration
    //
    handler->CreateConfiguration("DigitPublisher","AliLoaderPublisher",NULL,"-loader ITSLoader -datatype 'ALITREED' 'ITS '");
    handler->CreateConfiguration("DigitClusterFinder","ITSClusterFinderDigits","DigitPublisher","");

    ///////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // define the SPD vertexer Z input.
    //
    // Can not run on Digit ClusterFinder. Wrong inputtype. And wrong input data.
    // If this is fixed in the VertexerSPD it needs to implement the data type
    // handling for the ITS digits and ignore the input from the SDD and SSD
    //vertexerSPDInput="DigitClusterFinder";

    ///////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // define the ITS tracker input
    //
    // Currently there is a seg fault in the TTree access from the DigitClusterFinder
    // needs first to be investigated
    //trackerInput="DigitClusterFinder";
  }

  ///////////////////////////////////////////////////////////////////////////////////////////////////
  //
  // define the SPD vertexer Z configuration
  //
  if (!vertexerSPDInput.IsNull()) {
    handler->CreateConfiguration("ITS-SPD-vertexer","ITSVertexerSPD", vertexerSPDInput, "");
  }

  ///////////////////////////////////////////////////////////////////////////////////////////////////
  //
  // define the ITS tracker configuration
  //
  if (!trackerInput.IsNull()) {
    if (handler->FindConfiguration("TPC-globalmerger")) {
      // add the TPC tracking if available
      trackerInput+=" TPC-globalmerger";
    }
    handler->CreateConfiguration("ITS-tracker","ITSTracker",trackerInput.Data(),"");
  }

  return 0;
}

const char* AliHLTITSAgent::GetReconstructionChains(AliRawReader* /*rawReader*/,
						       AliRunLoader* runloader) const
{
  // see header file for class documentation
  if (runloader) {
    // reconstruction chains for AliRoot simulation
    // Note: run loader is only available while running embedded into
    // AliRoot simulation

    // the chain is just defined and can be used as input for subsequent
    // components
    //return "ITS-tracker";
  }

  return "";
}

const char* AliHLTITSAgent::GetRequiredComponentLibraries() const
{
  // see header file for class documentation
  return "libAliHLTUtil.so libAliHLTRCU.so libAliHLTTPC.so";
}

int AliHLTITSAgent::RegisterComponents(AliHLTComponentHandler* pHandler) const
{
  // see header file for class documentation
  assert(pHandler);
  if (!pHandler) return -EINVAL;
  pHandler->AddComponent(new AliHLTITSCompressRawDataSDDComponent);
  pHandler->AddComponent(new AliHLTITSSSDQARecPointsComponent);
  pHandler->AddComponent(new AliHLTITSQAComponent);
  pHandler->AddComponent(new AliHLTITSClusterFinderComponent(AliHLTITSClusterFinderComponent::kClusterFinderSPD));
  pHandler->AddComponent(new AliHLTITSClusterFinderComponent(AliHLTITSClusterFinderComponent::kClusterFinderSDD));
  pHandler->AddComponent(new AliHLTITSClusterFinderComponent(AliHLTITSClusterFinderComponent::kClusterFinderSSD));
  pHandler->AddComponent(new AliHLTITSClusterFinderComponent(AliHLTITSClusterFinderComponent::kClusterFinderDigits));
  pHandler->AddComponent(new AliHLTITSClusterHistoComponent);
  pHandler->AddComponent(new AliHLTITSTrackerComponent);
  pHandler->AddComponent(new AliHLTITSVertexerSPDComponent);
  pHandler->AddComponent(new AliHLTITSDigitPublisherComponent);

  return 0;
}

AliHLTModulePreprocessor* AliHLTITSAgent::GetPreprocessor()
{
  // see header file for class documentation
  return NULL;
}

int AliHLTITSAgent::GetHandlerDescription(AliHLTComponentDataType dt,
					     AliHLTUInt32_t spec,
					     AliHLTOUTHandlerDesc& desc) const
{
  // see header file for class documentation

  // Handlers for ITS raw data. Even though there are 3 detectors
  // everything is handled in one module library and one HLTOUT handler.
  // This assumes that the data blocks are sent with data type
  // {DDL_RAW :ISDD} and the bit set in the specification corresponding.
  // to detector DDL id.
  // An HLTOUT handler is implemented to extract the equipment id from
  // the specification.
  // Note: Future versions of the framework will provide a default handler
  // class with that functionality.
  if (dt==(kAliHLTDataTypeDDLRaw|kAliHLTDataOriginITSSDD)) {
      desc=AliHLTOUTHandlerDesc(kRawReader, dt, GetModuleId());
      HLTInfo("module %s handles data block type %s specification %d (0x%x)",
	      GetModuleId(), AliHLTComponent::DataType2Text(dt).c_str(), spec, spec);
      return 1;
  }
  return 0;
}

AliHLTOUTHandler* AliHLTITSAgent::GetOutputHandler(AliHLTComponentDataType dt,
						   AliHLTUInt32_t /*spec*/)
{
  // see header file for class documentation
  if (dt==(kAliHLTDataTypeDDLRaw|kAliHLTDataOriginITSSDD)) {
    // use the default handler
    if (!fRawDataHandler) {
      fRawDataHandler=new AliHLTOUTSDDRawDataHandler;
    }
    return fRawDataHandler;
  }
  return NULL;
}

int AliHLTITSAgent::DeleteOutputHandler(AliHLTOUTHandler* pInstance)
{
  // see header file for class documentation
  if (pInstance==NULL) return -EINVAL;

  if (pInstance==fRawDataHandler) {
    delete fRawDataHandler;
    fRawDataHandler=NULL;
    return 0;
  }

  delete pInstance;
  return 0;
}

int AliHLTITSAgent::AliHLTOUTSDDRawDataHandler::ProcessData(AliHLTOUT* pData)
{
  // see header file for class documentation
  if (!pData) return -EINVAL;
  static int errorCount=0;
  const int maxErrorCount=10;
  AliHLTComponentDataType dt=kAliHLTVoidDataType;
  AliHLTUInt32_t spec=kAliHLTVoidDataSpec;
  int iResult=pData->GetDataBlockDescription(dt, spec);
  if (iResult>=0) {
    if (dt==(kAliHLTDataTypeDDLRaw|kAliHLTDataOriginITSSDD)) {
      int ddlOffset=256;//AliDAQ::DdlIDOffset("ITSSDD");
      int numberOfDDLs=24;//AliDAQ::NumberOfDdls("ITSSDD");
      int ddlNo=0;
      for (;ddlNo<32 && ddlNo<numberOfDDLs; ddlNo++) {
	if (spec&(0x1<<ddlNo)) break;
      }
      if (ddlNo>=32 || ddlNo>=numberOfDDLs) {
	HLTError("invalid specification 0x%08x: can not extract DDL id for data block %s", spec, AliHLTComponent::DataType2Text(dt).c_str());
	iResult=-ENODEV;
      } else if (spec^(0x1<<ddlNo)) {
	iResult=-EEXIST;
	HLTError("multiple links set in specification 0x%08x: can not extract DDL id for data block %s", spec, AliHLTComponent::DataType2Text(dt).c_str());
      } else {
	iResult=ddlOffset+ddlNo;
      }
    } else {
      if (errorCount++<10) {
	HLTError("wrong data type: expecting %s, got %s; %s",
		 AliHLTComponent::DataType2Text(kAliHLTDataTypeDDLRaw|kAliHLTDataOriginITSSDD).c_str(),
		 AliHLTComponent::DataType2Text(dt).c_str(),
		   errorCount==maxErrorCount?"suppressing further error messages":"");
      }
      iResult=-EFAULT;
    }
  }
  return iResult;
}

int AliHLTITSAgent::CreateCFConfigurations(AliHLTConfigurationHandler* pHandler, int detectorId, TString& output) const
{
  // see header file for class documentation
  if (!pHandler) return -EINVAL;

  ///////////////////////////////////////////////////////////////////////////////////////////////////
  //
  // define the ITS cluster finder components
  //

  //The spec starts from 0x1 in SPD, SDD and SSD. So 0x1 is ddl 0 for SPD, 0x10 is ddl 1, and so on
  //in SDD 0x1 is ddl 256, 0x10 is ddl 257, and so on. This means that the spec has to be set to 0x1
  //before the loops over the clusterfinder

  TString idString=AliHLTDAQ::DetectorName(detectorId);
  if (idString.CompareTo("ITSSPD") &&
      idString.CompareTo("ITSSDD") &&
      idString.CompareTo("ITSSSD")) {
    HLTError("invalid detector id %d does not describe any ITS detector", detectorId);
    return -ENOENT;
  }

  int minddl=AliHLTDAQ::DdlIDOffset(detectorId);
  int maxddl=minddl+AliHLTDAQ::NumberOfDdls(detectorId)-1;
  int spec=0x1;
  int ddlno=0;

  bool bOneCFperDDL=false;
  TString origin=idString; origin.ReplaceAll("ITS", "I");
  TString cfBase=idString; cfBase+="_CF";
  TString componentId=idString; componentId.ReplaceAll("ITS", "ITSClusterFinder");
  TString cfinput, cf;
  for(ddlno=minddl;ddlno<=maxddl;ddlno++){
    TString arg, publisher;

    // the HLT origin defines are 4 chars: ISPD, ISSD, ISDD respectively
    arg.Form("-minid %d -datatype 'DDL_RAW ' '%s' -dataspec 0x%08x",ddlno, origin.Data(), spec);
    if (CheckFilter(kHLTLogDebug)) arg+=" -verbose";
    publisher.Form("ITS-DP_%d", ddlno);
    pHandler->CreateConfiguration(publisher.Data(), "AliRawReaderPublisher", NULL , arg.Data());

    if (cfinput.Length()>0) cfinput+=" ";
    cfinput+=publisher;

    if (bOneCFperDDL) {
    cf.Form("%s_%d",cfBase.Data(), ddlno);
    pHandler->CreateConfiguration(cf.Data(), componentId.Data(), publisher.Data(), "");

    if (output.Length()>0) output+=" ";
    output+=cf;
    }

    spec=spec<<1;
  }

  if (!bOneCFperDDL) {
    cf.Form("%s",cfBase.Data());
    pHandler->CreateConfiguration(cf.Data(), componentId.Data(), cfinput.Data(), "");

    if (output.Length()>0) output+=" ";
    output+=cf;
  }

  return 0;
}
<commit_msg>enable HLT ITS tracking from digits<commit_after>// $Id$

//**************************************************************************
//* This file is property of and copyright by the ALICE HLT Project        *
//* ALICE Experiment at CERN, All rights reserved.                         *
//*                                                                        *
//* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
//*                  for The ALICE HLT Project.                            *
//*                                                                        *
//* 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.                  *
//**************************************************************************

//  @file   AliHLTITSAgent.cxx
//  @author Matthias Richter
//  @date   25.08.2008
//  @brief  Agent of the libAliHLTITS library
//  @note

#include <cassert>
#include "AliHLTITSAgent.h"
#include "AliHLTConfiguration.h"
#include "AliHLTOUT.h"
#include "AliHLTDAQ.h"

// header files of library components
#include "AliHLTITSCompressRawDataSDDComponent.h"
#include "AliHLTITSSSDQARecPointsComponent.h"
#include "AliHLTITSQAComponent.h"
#include "AliHLTITSClusterFinderComponent.h"
#include "AliHLTITSClusterHistoComponent.h"
#include "AliHLTITSTrackerComponent.h"
#include "AliHLTITSVertexerSPDComponent.h"
#include "AliHLTITSDigitPublisherComponent.h"

// header file of the module preprocessor
// none at the moment

/** global instance for agent registration */
AliHLTITSAgent gAliHLTITSAgent;

/** ROOT macro for the implementation of ROOT specific class methods */
ClassImp(AliHLTITSAgent)

AliHLTITSAgent::AliHLTITSAgent()
  :
  AliHLTModuleAgent("ITS"),
  fRawDataHandler(NULL)
{
  // see header file for class documentation
  // or
  // refer to README to build package
  // or
  // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
}

AliHLTITSAgent::~AliHLTITSAgent()
{
  // see header file for class documentation
}

int AliHLTITSAgent::CreateConfigurations(AliHLTConfigurationHandler* handler,
					 AliRawReader* rawReader,
					 AliRunLoader* runloader) const
{
  // see header file for class documentation
  int iResult=0;
  if (!handler) return -EINVAL;

  ///////////////////////////////////////////////////////////////////////////////////////////////////
  ///////////////////////////////////////////////////////////////////////////////////////////////////
  //
  // ITS tracking is currently only working on raw data
  // to run on digits, a digit publisher needs to be implemented

  TString trackerInput="";
  TString vertexerSPDInput="";
  if (rawReader || !runloader) {
    // AliSimulation: use the AliRawReaderPublisher if the raw reader is available
    // Alireconstruction: indicated by runloader==NULL, run always on raw data

    ///////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // define the ITS cluster finder configurations
    //

    TString spdCF;
    TString ssdCF;
    TString sddCF;

    iResult=CreateCFConfigurations(handler, AliHLTDAQ::DetectorID("ITSSPD"), spdCF);
    handler->CreateConfiguration("ITS-SPD-CF","BlockFilter",spdCF.Data(),"");

    iResult=CreateCFConfigurations(handler, AliHLTDAQ::DetectorID("ITSSDD"), sddCF);
    handler->CreateConfiguration("ITS-SDD-CF","BlockFilter",sddCF.Data(),"");

    iResult=CreateCFConfigurations(handler, AliHLTDAQ::DetectorID("ITSSSD"), ssdCF);
    handler->CreateConfiguration("ITS-SSD-CF","BlockFilter",ssdCF.Data(),"");

    ///////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // define the SPD vertexer Z input
    //
    vertexerSPDInput="ITS-SPD-CF";

    ///////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // define the ITS tracker input
    //
    trackerInput="ITS-SPD-CF ITS-SDD-CF ITS-SSD-CF";
  }
  else if (runloader && !rawReader) {
    // indicates AliSimulation with no RawReader available -> run on digits

    ///////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // define the Digit Publisher and ITS cluster finder configuration
    //
    handler->CreateConfiguration("DigitPublisher","AliLoaderPublisher",NULL,"-loader ITSLoader -datatype 'ALITREED' 'ITS '");
    handler->CreateConfiguration("DigitClusterFinder","ITSClusterFinderDigits","DigitPublisher","");

    ///////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // define the SPD vertexer Z input.
    //
    // Can not run on Digit ClusterFinder. Wrong inputtype. And wrong input data.
    // If this is fixed in the VertexerSPD it needs to implement the data type
    // handling for the ITS digits and ignore the input from the SDD and SSD
    //vertexerSPDInput="DigitClusterFinder";

    ///////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // define the ITS tracker input
    //
    // Currently there is a seg fault in the TTree access from the DigitClusterFinder
    // needs first to be investigated
    trackerInput="DigitClusterFinder";
  }

  ///////////////////////////////////////////////////////////////////////////////////////////////////
  //
  // define the SPD vertexer Z configuration
  //
  if (!vertexerSPDInput.IsNull()) {
    handler->CreateConfiguration("ITS-SPD-vertexer","ITSVertexerSPD", vertexerSPDInput, "");
  }

  ///////////////////////////////////////////////////////////////////////////////////////////////////
  //
  // define the ITS tracker configuration
  //
  if (!trackerInput.IsNull()) {
    if (handler->FindConfiguration("TPC-globalmerger")) {
      // add the TPC tracking if available
      trackerInput+=" TPC-globalmerger";
    }
    handler->CreateConfiguration("ITS-tracker","ITSTracker",trackerInput.Data(),"");
  }

  return 0;
}

const char* AliHLTITSAgent::GetReconstructionChains(AliRawReader* /*rawReader*/,
						       AliRunLoader* runloader) const
{
  // see header file for class documentation
  if (runloader) {
    // reconstruction chains for AliRoot simulation
    // Note: run loader is only available while running embedded into
    // AliRoot simulation

    // the chain is just defined and can be used as input for subsequent
    // components
    //return "ITS-tracker";
  }

  return "";
}

const char* AliHLTITSAgent::GetRequiredComponentLibraries() const
{
  // see header file for class documentation
  return "libAliHLTUtil.so libAliHLTRCU.so libAliHLTTPC.so";
}

int AliHLTITSAgent::RegisterComponents(AliHLTComponentHandler* pHandler) const
{
  // see header file for class documentation
  assert(pHandler);
  if (!pHandler) return -EINVAL;
  pHandler->AddComponent(new AliHLTITSCompressRawDataSDDComponent);
  pHandler->AddComponent(new AliHLTITSSSDQARecPointsComponent);
  pHandler->AddComponent(new AliHLTITSQAComponent);
  pHandler->AddComponent(new AliHLTITSClusterFinderComponent(AliHLTITSClusterFinderComponent::kClusterFinderSPD));
  pHandler->AddComponent(new AliHLTITSClusterFinderComponent(AliHLTITSClusterFinderComponent::kClusterFinderSDD));
  pHandler->AddComponent(new AliHLTITSClusterFinderComponent(AliHLTITSClusterFinderComponent::kClusterFinderSSD));
  pHandler->AddComponent(new AliHLTITSClusterFinderComponent(AliHLTITSClusterFinderComponent::kClusterFinderDigits));
  pHandler->AddComponent(new AliHLTITSClusterHistoComponent);
  pHandler->AddComponent(new AliHLTITSTrackerComponent);
  pHandler->AddComponent(new AliHLTITSVertexerSPDComponent);
  pHandler->AddComponent(new AliHLTITSDigitPublisherComponent);

  return 0;
}

AliHLTModulePreprocessor* AliHLTITSAgent::GetPreprocessor()
{
  // see header file for class documentation
  return NULL;
}

int AliHLTITSAgent::GetHandlerDescription(AliHLTComponentDataType dt,
					     AliHLTUInt32_t spec,
					     AliHLTOUTHandlerDesc& desc) const
{
  // see header file for class documentation

  // Handlers for ITS raw data. Even though there are 3 detectors
  // everything is handled in one module library and one HLTOUT handler.
  // This assumes that the data blocks are sent with data type
  // {DDL_RAW :ISDD} and the bit set in the specification corresponding.
  // to detector DDL id.
  // An HLTOUT handler is implemented to extract the equipment id from
  // the specification.
  // Note: Future versions of the framework will provide a default handler
  // class with that functionality.
  if (dt==(kAliHLTDataTypeDDLRaw|kAliHLTDataOriginITSSDD)) {
      desc=AliHLTOUTHandlerDesc(kRawReader, dt, GetModuleId());
      HLTInfo("module %s handles data block type %s specification %d (0x%x)",
	      GetModuleId(), AliHLTComponent::DataType2Text(dt).c_str(), spec, spec);
      return 1;
  }
  return 0;
}

AliHLTOUTHandler* AliHLTITSAgent::GetOutputHandler(AliHLTComponentDataType dt,
						   AliHLTUInt32_t /*spec*/)
{
  // see header file for class documentation
  if (dt==(kAliHLTDataTypeDDLRaw|kAliHLTDataOriginITSSDD)) {
    // use the default handler
    if (!fRawDataHandler) {
      fRawDataHandler=new AliHLTOUTSDDRawDataHandler;
    }
    return fRawDataHandler;
  }
  return NULL;
}

int AliHLTITSAgent::DeleteOutputHandler(AliHLTOUTHandler* pInstance)
{
  // see header file for class documentation
  if (pInstance==NULL) return -EINVAL;

  if (pInstance==fRawDataHandler) {
    delete fRawDataHandler;
    fRawDataHandler=NULL;
    return 0;
  }

  delete pInstance;
  return 0;
}

int AliHLTITSAgent::AliHLTOUTSDDRawDataHandler::ProcessData(AliHLTOUT* pData)
{
  // see header file for class documentation
  if (!pData) return -EINVAL;
  static int errorCount=0;
  const int maxErrorCount=10;
  AliHLTComponentDataType dt=kAliHLTVoidDataType;
  AliHLTUInt32_t spec=kAliHLTVoidDataSpec;
  int iResult=pData->GetDataBlockDescription(dt, spec);
  if (iResult>=0) {
    if (dt==(kAliHLTDataTypeDDLRaw|kAliHLTDataOriginITSSDD)) {
      int ddlOffset=256;//AliDAQ::DdlIDOffset("ITSSDD");
      int numberOfDDLs=24;//AliDAQ::NumberOfDdls("ITSSDD");
      int ddlNo=0;
      for (;ddlNo<32 && ddlNo<numberOfDDLs; ddlNo++) {
	if (spec&(0x1<<ddlNo)) break;
      }
      if (ddlNo>=32 || ddlNo>=numberOfDDLs) {
	HLTError("invalid specification 0x%08x: can not extract DDL id for data block %s", spec, AliHLTComponent::DataType2Text(dt).c_str());
	iResult=-ENODEV;
      } else if (spec^(0x1<<ddlNo)) {
	iResult=-EEXIST;
	HLTError("multiple links set in specification 0x%08x: can not extract DDL id for data block %s", spec, AliHLTComponent::DataType2Text(dt).c_str());
      } else {
	iResult=ddlOffset+ddlNo;
      }
    } else {
      if (errorCount++<10) {
	HLTError("wrong data type: expecting %s, got %s; %s",
		 AliHLTComponent::DataType2Text(kAliHLTDataTypeDDLRaw|kAliHLTDataOriginITSSDD).c_str(),
		 AliHLTComponent::DataType2Text(dt).c_str(),
		   errorCount==maxErrorCount?"suppressing further error messages":"");
      }
      iResult=-EFAULT;
    }
  }
  return iResult;
}

int AliHLTITSAgent::CreateCFConfigurations(AliHLTConfigurationHandler* pHandler, int detectorId, TString& output) const
{
  // see header file for class documentation
  if (!pHandler) return -EINVAL;

  ///////////////////////////////////////////////////////////////////////////////////////////////////
  //
  // define the ITS cluster finder components
  //

  //The spec starts from 0x1 in SPD, SDD and SSD. So 0x1 is ddl 0 for SPD, 0x10 is ddl 1, and so on
  //in SDD 0x1 is ddl 256, 0x10 is ddl 257, and so on. This means that the spec has to be set to 0x1
  //before the loops over the clusterfinder

  TString idString=AliHLTDAQ::DetectorName(detectorId);
  if (idString.CompareTo("ITSSPD") &&
      idString.CompareTo("ITSSDD") &&
      idString.CompareTo("ITSSSD")) {
    HLTError("invalid detector id %d does not describe any ITS detector", detectorId);
    return -ENOENT;
  }

  int minddl=AliHLTDAQ::DdlIDOffset(detectorId);
  int maxddl=minddl+AliHLTDAQ::NumberOfDdls(detectorId)-1;
  int spec=0x1;
  int ddlno=0;

  bool bOneCFperDDL=false;
  TString origin=idString; origin.ReplaceAll("ITS", "I");
  TString cfBase=idString; cfBase+="_CF";
  TString componentId=idString; componentId.ReplaceAll("ITS", "ITSClusterFinder");
  TString cfinput, cf;
  for(ddlno=minddl;ddlno<=maxddl;ddlno++){
    TString arg, publisher;

    // the HLT origin defines are 4 chars: ISPD, ISSD, ISDD respectively
    arg.Form("-minid %d -datatype 'DDL_RAW ' '%s' -dataspec 0x%08x",ddlno, origin.Data(), spec);
    if (CheckFilter(kHLTLogDebug)) arg+=" -verbose";
    publisher.Form("ITS-DP_%d", ddlno);
    pHandler->CreateConfiguration(publisher.Data(), "AliRawReaderPublisher", NULL , arg.Data());

    if (cfinput.Length()>0) cfinput+=" ";
    cfinput+=publisher;

    if (bOneCFperDDL) {
    cf.Form("%s_%d",cfBase.Data(), ddlno);
    pHandler->CreateConfiguration(cf.Data(), componentId.Data(), publisher.Data(), "");

    if (output.Length()>0) output+=" ";
    output+=cf;
    }

    spec=spec<<1;
  }

  if (!bOneCFperDDL) {
    cf.Form("%s",cfBase.Data());
    pHandler->CreateConfiguration(cf.Data(), componentId.Data(), cfinput.Data(), "");

    if (output.Length()>0) output+=" ";
    output+=cf;
  }

  return 0;
}
<|endoftext|>


<commit_before>/*
* MIT License
*
* Copyright (c) 2009-2021 Jingwood, unvell.com. All right reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* 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. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

#include "stdafx.h"
#include "Text.h"

D2DLIB_API void DrawString(HANDLE ctx, LPCWSTR text, D2D1_COLOR_F color,
													 LPCWSTR fontName, FLOAT fontSize, D2D1_RECT_F* rect,
													 DWRITE_TEXT_ALIGNMENT halign, DWRITE_PARAGRAPH_ALIGNMENT valign)
{
	RetrieveContext(ctx);

	ID2D1SolidColorBrush* brush = NULL;
	IDWriteTextFormat* textFormat = NULL;

	HRESULT hr = context->writeFactory->CreateTextFormat(fontName,
		NULL,
		DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL,
		fontSize,
		L"", //locale
		&textFormat);

	if (SUCCEEDED(hr) && textFormat != NULL)
	{
		textFormat->SetTextAlignment(halign);
		textFormat->SetParagraphAlignment(valign);

		// Create a solid color brush.
		hr = (context->renderTarget)->CreateSolidColorBrush(color, &brush);

		if (SUCCEEDED(hr) && brush != NULL) {
			context->renderTarget->DrawText(text, wcslen(text), textFormat, rect, brush);
		}
	}

	SafeRelease(&brush);
	SafeRelease(&textFormat);
}

D2DLIB_API HANDLE CreateTextLayout(HANDLE ctx, LPCWSTR text, LPCWSTR fontName, FLOAT fontSize, D2D1_SIZE_F* size) {
	RetrieveContext(ctx);

	IDWriteTextFormat* textFormat = NULL;

	HRESULT hr = context->writeFactory->CreateTextFormat(fontName,
		NULL,
		DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL,
		fontSize,
		L"", //locale
		&textFormat);

	if (SUCCEEDED(hr) && textFormat != NULL)
	{
		IDWriteTextLayout* textLayout;

		hr = context->writeFactory->CreateTextLayout(
			text,      // The string to be laid out and formatted.
			wcslen(text),  // The length of the string.
			textFormat,  // The text format to apply to the string (contains font information, etc).
			size->width,         // The width of the layout box.
			size->height,        // The height of the layout box.
			&textLayout  // The IDWriteTextLayout interface pointer.
		);

		if (SUCCEEDED(hr) && textLayout != NULL) {
			return (HANDLE)textLayout;
		}
	}

	SafeRelease(&textFormat);

	return NULL;
}

D2DLIB_API void MeasureText(HANDLE ctx, LPCWSTR text, LPCWSTR fontName, FLOAT fontSize, D2D1_SIZE_F* size) {
	RetrieveContext(ctx);

	IDWriteTextLayout* textLayout = (IDWriteTextLayout*)CreateTextLayout(ctx, text, fontName, fontSize, size);

	if (textLayout != NULL) {
		DWRITE_TEXT_METRICS tm;
		textLayout->GetMetrics(&tm);

		size->width = tm.width;
		size->height = tm.height;
	}

	SafeRelease(&textLayout);
}

void DrawGlyphRun(HANDLE ctx, D2D1_POINT_2F baselineOrigin,
			const DWRITE_GLYPH_RUN *glyphRun, D2D1_COLOR_F color,
			DWRITE_MEASURING_MODE measuringMode)
{
	D2DContext* context = reinterpret_cast<D2DContext*>(ctx);

}

//void DrawTextLayout(HANDLE ctx, D2D1_POINT_2F origin,
//  [in]  IDWriteTextLayout *textLayout,
//  [in]  ID2D1Brush *defaultForegroundBrush,
//  D2D1_DRAW_TEXT_OPTIONS options = D2D1_DRAW_TEXT_OPTIONS_NONE
//)
//{
//}<commit_msg>Fix memory leak<commit_after>/*
* MIT License
*
* Copyright (c) 2009-2021 Jingwood, unvell.com. All right reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* 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. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

#include "stdafx.h"
#include "Text.h"

D2DLIB_API void DrawString(HANDLE ctx, LPCWSTR text, D2D1_COLOR_F color,
													 LPCWSTR fontName, FLOAT fontSize, D2D1_RECT_F* rect,
													 DWRITE_TEXT_ALIGNMENT halign, DWRITE_PARAGRAPH_ALIGNMENT valign)
{
	RetrieveContext(ctx);

	ID2D1SolidColorBrush* brush = NULL;
	IDWriteTextFormat* textFormat = NULL;

	HRESULT hr = context->writeFactory->CreateTextFormat(fontName,
		NULL,
		DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL,
		fontSize,
		L"", //locale
		&textFormat);

	if (SUCCEEDED(hr) && textFormat != NULL)
	{
		textFormat->SetTextAlignment(halign);
		textFormat->SetParagraphAlignment(valign);

		// Create a solid color brush.
		hr = (context->renderTarget)->CreateSolidColorBrush(color, &brush);

		if (SUCCEEDED(hr) && brush != NULL) {
			context->renderTarget->DrawText(text, wcslen(text), textFormat, rect, brush);
		}
	}

	SafeRelease(&brush);
	SafeRelease(&textFormat);
}

D2DLIB_API HANDLE CreateTextLayout(HANDLE ctx, LPCWSTR text, LPCWSTR fontName, FLOAT fontSize, D2D1_SIZE_F* size) {
	RetrieveContext(ctx);

	IDWriteTextFormat* textFormat = NULL;

	HRESULT hr = context->writeFactory->CreateTextFormat(fontName,
		NULL,
		DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL,
		fontSize,
		L"", //locale
		&textFormat);

	if (SUCCEEDED(hr) && textFormat != NULL)
	{
		IDWriteTextLayout* textLayout;

		hr = context->writeFactory->CreateTextLayout(
			text,      // The string to be laid out and formatted.
			wcslen(text),  // The length of the string.
			textFormat,  // The text format to apply to the string (contains font information, etc).
			size->width,         // The width of the layout box.
			size->height,        // The height of the layout box.
			&textLayout  // The IDWriteTextLayout interface pointer.
		);

		if (SUCCEEDED(hr) && textLayout != NULL) {
			SafeRelease(&textFormat);
			return (HANDLE)textLayout;
		}
	}

	SafeRelease(&textFormat);

	return NULL;
}

D2DLIB_API void MeasureText(HANDLE ctx, LPCWSTR text, LPCWSTR fontName, FLOAT fontSize, D2D1_SIZE_F* size) {
	RetrieveContext(ctx);

	IDWriteTextLayout* textLayout = (IDWriteTextLayout*)CreateTextLayout(ctx, text, fontName, fontSize, size);

	if (textLayout != NULL) {
		DWRITE_TEXT_METRICS tm;
		textLayout->GetMetrics(&tm);

		size->width = tm.width;
		size->height = tm.height;
	}

	SafeRelease(&textLayout);
}

void DrawGlyphRun(HANDLE ctx, D2D1_POINT_2F baselineOrigin,
			const DWRITE_GLYPH_RUN *glyphRun, D2D1_COLOR_F color,
			DWRITE_MEASURING_MODE measuringMode)
{
	D2DContext* context = reinterpret_cast<D2DContext*>(ctx);

}

//void DrawTextLayout(HANDLE ctx, D2D1_POINT_2F origin,
//  [in]  IDWriteTextLayout *textLayout,
//  [in]  ID2D1Brush *defaultForegroundBrush,
//  D2D1_DRAW_TEXT_OPTIONS options = D2D1_DRAW_TEXT_OPTIONS_NONE
//)
//{
//}<|endoftext|>


<commit_before>/*
 * Copyright © 2013 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * 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.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

/**
 * \file brw_vec4_tes.cpp
 *
 * Tessellaton evaluation shader specific code derived from the vec4_visitor class.
 */

#include "brw_vec4_tes.h"
#include "brw_cfg.h"

namespace brw {

vec4_tes_visitor::vec4_tes_visitor(const struct brw_compiler *compiler,
                                  void *log_data,
                                  const struct brw_tes_prog_key *key,
                                  struct brw_tes_prog_data *prog_data,
                                  const nir_shader *shader,
                                  void *mem_ctx,
                                  int shader_time_index)
   : vec4_visitor(compiler, log_data, &key->tex, &prog_data->base,
                  shader, mem_ctx, false, shader_time_index)
{
}

dst_reg *
vec4_tes_visitor::make_reg_for_system_value(int location)
{
   return NULL;
}

void
vec4_tes_visitor::nir_setup_system_value_intrinsic(nir_intrinsic_instr *instr)
{
   switch (instr->intrinsic) {
   case nir_intrinsic_load_tess_level_outer:
   case nir_intrinsic_load_tess_level_inner:
      break;
   default:
      vec4_visitor::nir_setup_system_value_intrinsic(instr);
   }
}

void
vec4_tes_visitor::setup_payload()
{
   int reg = 0;

   /* The payload always contains important data in r0 and r1, which contains
    * the URB handles that are passed on to the URB write at the end
    * of the thread.
    */
   reg += 2;

   reg = setup_uniforms(reg);

   foreach_block_and_inst(block, vec4_instruction, inst, cfg) {
      for (int i = 0; i < 3; i++) {
         if (inst->src[i].file != ATTR)
            continue;

         struct brw_reg grf =
            brw_vec4_grf(reg + inst->src[i].nr / 2, 4 * (inst->src[i].nr % 2));
         grf = stride(grf, 0, 4, 1);
         grf.swizzle = inst->src[i].swizzle;
         grf.type = inst->src[i].type;
         grf.abs = inst->src[i].abs;
         grf.negate = inst->src[i].negate;

         inst->src[i] = grf;
      }
   }

   reg += 8 * prog_data->urb_read_length;

   this->first_non_payload_grf = reg;
}

void
vec4_tes_visitor::emit_prolog()
{
   input_read_header = src_reg(this, glsl_type::uvec4_type);
   emit(TES_OPCODE_CREATE_INPUT_READ_HEADER, dst_reg(input_read_header));

   this->current_annotation = NULL;
}

void
vec4_tes_visitor::emit_urb_write_header(int mrf)
{
   /* No need to do anything for DS; an implied write to this MRF will be
    * performed by VS_OPCODE_URB_WRITE.
    */
   (void) mrf;
}

vec4_instruction *
vec4_tes_visitor::emit_urb_write_opcode(bool complete)
{
   /* For DS, the URB writes end the thread. */
   if (complete) {
      if (INTEL_DEBUG & DEBUG_SHADER_TIME)
         emit_shader_time_end();
   }

   vec4_instruction *inst = emit(VS_OPCODE_URB_WRITE);
   inst->urb_write_flags = complete ?
      BRW_URB_WRITE_EOT_COMPLETE : BRW_URB_WRITE_NO_FLAGS;

   return inst;
}

void
vec4_tes_visitor::nir_emit_intrinsic(nir_intrinsic_instr *instr)
{
   const struct brw_tes_prog_data *tes_prog_data =
      (const struct brw_tes_prog_data *) prog_data;

   switch (instr->intrinsic) {
   case nir_intrinsic_load_tess_coord:
      /* gl_TessCoord is part of the payload in g1 channels 0-2 and 4-6. */
      emit(MOV(get_nir_dest(instr->dest, BRW_REGISTER_TYPE_F),
               src_reg(brw_vec8_grf(1, 0))));
      break;
   case nir_intrinsic_load_tess_level_outer:
      if (tes_prog_data->domain == BRW_TESS_DOMAIN_ISOLINE) {
         emit(MOV(get_nir_dest(instr->dest, BRW_REGISTER_TYPE_F),
                  swizzle(src_reg(ATTR, 1, glsl_type::vec4_type),
                          BRW_SWIZZLE_ZWZW)));
      } else {
         emit(MOV(get_nir_dest(instr->dest, BRW_REGISTER_TYPE_F),
                  swizzle(src_reg(ATTR, 1, glsl_type::vec4_type),
                          BRW_SWIZZLE_WZYX)));
      }
      break;
   case nir_intrinsic_load_tess_level_inner:
      if (tes_prog_data->domain == BRW_TESS_DOMAIN_QUAD) {
         emit(MOV(get_nir_dest(instr->dest, BRW_REGISTER_TYPE_F),
                  swizzle(src_reg(ATTR, 0, glsl_type::vec4_type),
                          BRW_SWIZZLE_WZYX)));
      } else {
         emit(MOV(get_nir_dest(instr->dest, BRW_REGISTER_TYPE_F),
                  src_reg(ATTR, 1, glsl_type::float_type)));
      }
      break;
   case nir_intrinsic_load_primitive_id:
      emit(TES_OPCODE_GET_PRIMITIVE_ID,
           get_nir_dest(instr->dest, BRW_REGISTER_TYPE_UD));
      break;

   case nir_intrinsic_load_input:
   case nir_intrinsic_load_per_vertex_input: {
      src_reg indirect_offset = get_indirect_offset(instr);
      unsigned imm_offset = instr->const_index[0];
      src_reg header = input_read_header;
      bool is_64bit = nir_dest_bit_size(instr->dest) == 64;
      unsigned first_component = nir_intrinsic_component(instr);
      if (is_64bit)
         first_component /= 2;

      if (indirect_offset.file != BAD_FILE) {
         header = src_reg(this, glsl_type::uvec4_type);
         emit(TES_OPCODE_ADD_INDIRECT_URB_OFFSET, dst_reg(header),
              input_read_header, indirect_offset);
      } else {
         /* Arbitrarily only push up to 24 vec4 slots worth of data,
          * which is 12 registers (since each holds 2 vec4 slots).
          */
         const unsigned max_push_slots = 24;
         if (imm_offset < max_push_slots) {
            const glsl_type *src_glsl_type =
               is_64bit ? glsl_type::dvec4_type : glsl_type::ivec4_type;
            src_reg src = src_reg(ATTR, imm_offset, src_glsl_type);
            src.swizzle = BRW_SWZ_COMP_INPUT(first_component);

            const brw_reg_type dst_reg_type =
               is_64bit ? BRW_REGISTER_TYPE_DF : BRW_REGISTER_TYPE_D;
            emit(MOV(get_nir_dest(instr->dest, dst_reg_type), src));

            prog_data->urb_read_length =
               MAX2(prog_data->urb_read_length,
                    DIV_ROUND_UP(imm_offset + (is_64bit ? 2 : 1), 2));
            break;
         }
      }

      if (!is_64bit) {
         dst_reg temp(this, glsl_type::ivec4_type);
         vec4_instruction *read =
            emit(VEC4_OPCODE_URB_READ, temp, src_reg(header));
         read->offset = imm_offset;
         read->urb_write_flags = BRW_URB_WRITE_PER_SLOT_OFFSET;

         src_reg src = src_reg(temp);
         src.swizzle = BRW_SWZ_COMP_INPUT(first_component);

         /* Copy to target.  We might end up with some funky writemasks landing
          * in here, but we really don't want them in the above pseudo-ops.
          */
         dst_reg dst = get_nir_dest(instr->dest, BRW_REGISTER_TYPE_D);
         dst.writemask = brw_writemask_for_size(instr->num_components);
         emit(MOV(dst, src));
      } else {
         /* For 64-bit we need to load twice as many 32-bit components, and for
          * dvec3/4 we need to emit 2 URB Read messages
          */
         dst_reg temp(this, glsl_type::dvec4_type);
         dst_reg temp_d = retype(temp, BRW_REGISTER_TYPE_D);

         vec4_instruction *read =
            emit(VEC4_OPCODE_URB_READ, temp_d, src_reg(header));
         read->offset = imm_offset;
         read->urb_write_flags = BRW_URB_WRITE_PER_SLOT_OFFSET;

         if (instr->num_components > 2) {
            read = emit(VEC4_OPCODE_URB_READ, byte_offset(temp_d, REG_SIZE),
                        src_reg(header));
            read->offset = imm_offset + 1;
            read->urb_write_flags = BRW_URB_WRITE_PER_SLOT_OFFSET;
         }

         src_reg temp_as_src = src_reg(temp);
         temp_as_src.swizzle = BRW_SWZ_COMP_INPUT(first_component);

         dst_reg shuffled(this, glsl_type::dvec4_type);
         shuffle_64bit_data(shuffled, temp_as_src, false);

         dst_reg dst = get_nir_dest(instr->dest, BRW_REGISTER_TYPE_DF);
         dst.writemask = brw_writemask_for_size(instr->num_components);
         emit(MOV(dst, src_reg(shuffled)));
      }
      break;
   }
   default:
      vec4_visitor::nir_emit_intrinsic(instr);
   }
}

void
vec4_tes_visitor::emit_thread_end()
{
   /* For DS, we always end the thread by emitting a single vertex.
    * emit_urb_write_opcode() will take care of setting the eot flag on the
    * SEND instruction.
    */
   emit_vertex();
}

} /* namespace brw */
<commit_msg>i965/vec4/tes: fix setup_payload() for 64bit data types<commit_after>/*
 * Copyright © 2013 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * 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.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

/**
 * \file brw_vec4_tes.cpp
 *
 * Tessellaton evaluation shader specific code derived from the vec4_visitor class.
 */

#include "brw_vec4_tes.h"
#include "brw_cfg.h"

namespace brw {

vec4_tes_visitor::vec4_tes_visitor(const struct brw_compiler *compiler,
                                  void *log_data,
                                  const struct brw_tes_prog_key *key,
                                  struct brw_tes_prog_data *prog_data,
                                  const nir_shader *shader,
                                  void *mem_ctx,
                                  int shader_time_index)
   : vec4_visitor(compiler, log_data, &key->tex, &prog_data->base,
                  shader, mem_ctx, false, shader_time_index)
{
}

dst_reg *
vec4_tes_visitor::make_reg_for_system_value(int location)
{
   return NULL;
}

void
vec4_tes_visitor::nir_setup_system_value_intrinsic(nir_intrinsic_instr *instr)
{
   switch (instr->intrinsic) {
   case nir_intrinsic_load_tess_level_outer:
   case nir_intrinsic_load_tess_level_inner:
      break;
   default:
      vec4_visitor::nir_setup_system_value_intrinsic(instr);
   }
}

void
vec4_tes_visitor::setup_payload()
{
   int reg = 0;

   /* The payload always contains important data in r0 and r1, which contains
    * the URB handles that are passed on to the URB write at the end
    * of the thread.
    */
   reg += 2;

   reg = setup_uniforms(reg);

   foreach_block_and_inst(block, vec4_instruction, inst, cfg) {
      for (int i = 0; i < 3; i++) {
         if (inst->src[i].file != ATTR)
            continue;

         bool is_64bit = type_sz(inst->src[i].type) == 8;

         struct brw_reg grf =
            brw_vec4_grf(reg + inst->src[i].nr / 2, 4 * (inst->src[i].nr % 2));
         grf = stride(grf, 0, is_64bit ? 2 : 4, 1);
         grf.swizzle = inst->src[i].swizzle;
         grf.type = inst->src[i].type;
         grf.abs = inst->src[i].abs;
         grf.negate = inst->src[i].negate;

         /* For 64-bit attributes we can end up with components XY in the
          * second half of a register and components ZW in the first half
          * of the next. Fix it up here.
          */
         if (is_64bit && grf.subnr > 0) {
            /* We can't do swizzles that mix XY and ZW channels in this case.
             * Such cases should have been handled by the scalarization pass.
             */
            assert((brw_mask_for_swizzle(grf.swizzle) & 0x3) ^
                   (brw_mask_for_swizzle(grf.swizzle) & 0xc));
            if (brw_mask_for_swizzle(grf.swizzle) & 0xc) {
               grf.subnr = 0;
               grf.nr++;
               grf.swizzle -= BRW_SWIZZLE_ZZZZ;
            }
         }

         inst->src[i] = grf;
      }
   }

   reg += 8 * prog_data->urb_read_length;

   this->first_non_payload_grf = reg;
}

void
vec4_tes_visitor::emit_prolog()
{
   input_read_header = src_reg(this, glsl_type::uvec4_type);
   emit(TES_OPCODE_CREATE_INPUT_READ_HEADER, dst_reg(input_read_header));

   this->current_annotation = NULL;
}

void
vec4_tes_visitor::emit_urb_write_header(int mrf)
{
   /* No need to do anything for DS; an implied write to this MRF will be
    * performed by VS_OPCODE_URB_WRITE.
    */
   (void) mrf;
}

vec4_instruction *
vec4_tes_visitor::emit_urb_write_opcode(bool complete)
{
   /* For DS, the URB writes end the thread. */
   if (complete) {
      if (INTEL_DEBUG & DEBUG_SHADER_TIME)
         emit_shader_time_end();
   }

   vec4_instruction *inst = emit(VS_OPCODE_URB_WRITE);
   inst->urb_write_flags = complete ?
      BRW_URB_WRITE_EOT_COMPLETE : BRW_URB_WRITE_NO_FLAGS;

   return inst;
}

void
vec4_tes_visitor::nir_emit_intrinsic(nir_intrinsic_instr *instr)
{
   const struct brw_tes_prog_data *tes_prog_data =
      (const struct brw_tes_prog_data *) prog_data;

   switch (instr->intrinsic) {
   case nir_intrinsic_load_tess_coord:
      /* gl_TessCoord is part of the payload in g1 channels 0-2 and 4-6. */
      emit(MOV(get_nir_dest(instr->dest, BRW_REGISTER_TYPE_F),
               src_reg(brw_vec8_grf(1, 0))));
      break;
   case nir_intrinsic_load_tess_level_outer:
      if (tes_prog_data->domain == BRW_TESS_DOMAIN_ISOLINE) {
         emit(MOV(get_nir_dest(instr->dest, BRW_REGISTER_TYPE_F),
                  swizzle(src_reg(ATTR, 1, glsl_type::vec4_type),
                          BRW_SWIZZLE_ZWZW)));
      } else {
         emit(MOV(get_nir_dest(instr->dest, BRW_REGISTER_TYPE_F),
                  swizzle(src_reg(ATTR, 1, glsl_type::vec4_type),
                          BRW_SWIZZLE_WZYX)));
      }
      break;
   case nir_intrinsic_load_tess_level_inner:
      if (tes_prog_data->domain == BRW_TESS_DOMAIN_QUAD) {
         emit(MOV(get_nir_dest(instr->dest, BRW_REGISTER_TYPE_F),
                  swizzle(src_reg(ATTR, 0, glsl_type::vec4_type),
                          BRW_SWIZZLE_WZYX)));
      } else {
         emit(MOV(get_nir_dest(instr->dest, BRW_REGISTER_TYPE_F),
                  src_reg(ATTR, 1, glsl_type::float_type)));
      }
      break;
   case nir_intrinsic_load_primitive_id:
      emit(TES_OPCODE_GET_PRIMITIVE_ID,
           get_nir_dest(instr->dest, BRW_REGISTER_TYPE_UD));
      break;

   case nir_intrinsic_load_input:
   case nir_intrinsic_load_per_vertex_input: {
      src_reg indirect_offset = get_indirect_offset(instr);
      unsigned imm_offset = instr->const_index[0];
      src_reg header = input_read_header;
      bool is_64bit = nir_dest_bit_size(instr->dest) == 64;
      unsigned first_component = nir_intrinsic_component(instr);
      if (is_64bit)
         first_component /= 2;

      if (indirect_offset.file != BAD_FILE) {
         header = src_reg(this, glsl_type::uvec4_type);
         emit(TES_OPCODE_ADD_INDIRECT_URB_OFFSET, dst_reg(header),
              input_read_header, indirect_offset);
      } else {
         /* Arbitrarily only push up to 24 vec4 slots worth of data,
          * which is 12 registers (since each holds 2 vec4 slots).
          */
         const unsigned max_push_slots = 24;
         if (imm_offset < max_push_slots) {
            const glsl_type *src_glsl_type =
               is_64bit ? glsl_type::dvec4_type : glsl_type::ivec4_type;
            src_reg src = src_reg(ATTR, imm_offset, src_glsl_type);
            src.swizzle = BRW_SWZ_COMP_INPUT(first_component);

            const brw_reg_type dst_reg_type =
               is_64bit ? BRW_REGISTER_TYPE_DF : BRW_REGISTER_TYPE_D;
            emit(MOV(get_nir_dest(instr->dest, dst_reg_type), src));

            prog_data->urb_read_length =
               MAX2(prog_data->urb_read_length,
                    DIV_ROUND_UP(imm_offset + (is_64bit ? 2 : 1), 2));
            break;
         }
      }

      if (!is_64bit) {
         dst_reg temp(this, glsl_type::ivec4_type);
         vec4_instruction *read =
            emit(VEC4_OPCODE_URB_READ, temp, src_reg(header));
         read->offset = imm_offset;
         read->urb_write_flags = BRW_URB_WRITE_PER_SLOT_OFFSET;

         src_reg src = src_reg(temp);
         src.swizzle = BRW_SWZ_COMP_INPUT(first_component);

         /* Copy to target.  We might end up with some funky writemasks landing
          * in here, but we really don't want them in the above pseudo-ops.
          */
         dst_reg dst = get_nir_dest(instr->dest, BRW_REGISTER_TYPE_D);
         dst.writemask = brw_writemask_for_size(instr->num_components);
         emit(MOV(dst, src));
      } else {
         /* For 64-bit we need to load twice as many 32-bit components, and for
          * dvec3/4 we need to emit 2 URB Read messages
          */
         dst_reg temp(this, glsl_type::dvec4_type);
         dst_reg temp_d = retype(temp, BRW_REGISTER_TYPE_D);

         vec4_instruction *read =
            emit(VEC4_OPCODE_URB_READ, temp_d, src_reg(header));
         read->offset = imm_offset;
         read->urb_write_flags = BRW_URB_WRITE_PER_SLOT_OFFSET;

         if (instr->num_components > 2) {
            read = emit(VEC4_OPCODE_URB_READ, byte_offset(temp_d, REG_SIZE),
                        src_reg(header));
            read->offset = imm_offset + 1;
            read->urb_write_flags = BRW_URB_WRITE_PER_SLOT_OFFSET;
         }

         src_reg temp_as_src = src_reg(temp);
         temp_as_src.swizzle = BRW_SWZ_COMP_INPUT(first_component);

         dst_reg shuffled(this, glsl_type::dvec4_type);
         shuffle_64bit_data(shuffled, temp_as_src, false);

         dst_reg dst = get_nir_dest(instr->dest, BRW_REGISTER_TYPE_DF);
         dst.writemask = brw_writemask_for_size(instr->num_components);
         emit(MOV(dst, src_reg(shuffled)));
      }
      break;
   }
   default:
      vec4_visitor::nir_emit_intrinsic(instr);
   }
}

void
vec4_tes_visitor::emit_thread_end()
{
   /* For DS, we always end the thread by emitting a single vertex.
    * emit_urb_write_opcode() will take care of setting the eot flag on the
    * SEND instruction.
    */
   emit_vertex();
}

} /* namespace brw */
<|endoftext|>


<commit_before><commit_msg>278 - Chess.v2.cpp<commit_after><|endoftext|>


<commit_before>#include "StdAfx.h"
#include "Camera.h"
#include <iostream>
/*
    RawSpeed - RAW file decoder.

    Copyright (C) 2009 Klaus Post

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library 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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

    http://www.klauspost.com
*/

namespace RawSpeed {

Camera::Camera(xmlDocPtr doc, xmlNodePtr cur) {
  xmlChar *key;
  key = xmlGetProp(cur, (const xmlChar *)"make");
  if (!key)
    ThrowCME("Camera XML Parser: \"make\" attribute not found.");
  make = string((const char*)key);
  xmlFree(key);

  key = xmlGetProp(cur, (const xmlChar *)"model");
  if (!key)
    ThrowCME("Camera XML Parser: \"model\" attribute not found.");
  model = string((const char*)key);
  xmlFree(key);

  supported = true;
  key = xmlGetProp(cur, (const xmlChar *)"supported");
  if (key) {
    string s = string((const char*)key);
    if (s.compare("no") == 0)
      supported = false;
    xmlFree(key);
  }

  key = xmlGetProp(cur, (const xmlChar *)"mode");
  if (key) {
    mode = string((const char*)key);
    xmlFree(key);
  } else {
    mode = string("");
  }

  key = xmlGetProp(cur, (const xmlChar *)"decoder_version");
  if (key) {
    decoderVersion = getAttributeAsInt(cur, cur->name, "decoder_version");
    xmlFree(key);
  } else {
    decoderVersion = 0;
  }

  cur = cur->xmlChildrenNode;
  while (cur != NULL) {
    parseCameraChild(doc, cur);
    cur = cur->next;
  }
}

Camera::Camera( const Camera* camera, uint32 alias_num)
{
  if (alias_num >= camera->aliases.size())
    ThrowCME("Camera: Internal error, alias number out of range specified.");

  make = camera->make;
  model = camera->aliases[alias_num];
  mode = camera->mode;
  cfa = camera->cfa;
  supported = camera->supported;
  cropSize = camera->cropSize;
  cropPos = camera->cropPos;
  decoderVersion = camera->decoderVersion;
  for (uint32 i = 0; i < camera->blackAreas.size(); i++) {
    blackAreas.push_back(camera->blackAreas[i]);
  }
  for (uint32 i = 0; i < camera->sensorInfo.size(); i++) {
    sensorInfo.push_back(camera->sensorInfo[i]);
  }
  map<string,string>::const_iterator mi = camera->hints.begin();
  for (; mi != camera->hints.end(); ++mi) {
    hints.insert(make_pair((*mi).first, (*mi).second));
  }
}

Camera::~Camera(void) {
}

void Camera::parseCameraChild(xmlDocPtr doc, xmlNodePtr cur) {
  if (!xmlStrcmp(cur->name, (const xmlChar *) "CFA")) {
    if (2 != getAttributeAsInt(cur, cur->name, "width"))
      ThrowCME("Unsupported CFA size in camera %s %s", make.c_str(), model.c_str());
    if (2 != getAttributeAsInt(cur, cur->name, "height"))
      ThrowCME("Unsupported CFA size in camera %s %s", make.c_str(), model.c_str());

    cur = cur->xmlChildrenNode;
    while (cur != NULL) {
      parseCFA(doc, cur);
      cur = cur->next;
    }

    return;
  }

  if (!xmlStrcmp(cur->name, (const xmlChar *) "Crop")) {
    cropPos.x = getAttributeAsInt(cur, cur->name, "x");
    cropPos.y = getAttributeAsInt(cur, cur->name, "y");

    if (cropPos.x < 0)
      ThrowCME("Negative X axis crop specified in camera %s %s", make.c_str(), model.c_str());
    if (cropPos.y < 0)
      ThrowCME("Negative Y axis crop specified in camera %s %s", make.c_str(), model.c_str());

    cropSize.x = getAttributeAsInt(cur, cur->name, "width");
    cropSize.y = getAttributeAsInt(cur, cur->name, "height");
    return;
  }

  if (!xmlStrcmp(cur->name, (const xmlChar *) "Sensor")) {
    parseSensorInfo(doc, cur);
    return;
  }

  if (!xmlStrcmp(cur->name, (const xmlChar *) "BlackAreas")) {
    cur = cur->xmlChildrenNode;
    while (cur != NULL) {
      parseBlackAreas(doc, cur);
      cur = cur->next;
    }
    return;
  }

  if (!xmlStrcmp(cur->name, (const xmlChar *) "Aliases")) {
    cur = cur->xmlChildrenNode;
    while (cur != NULL) {
      parseAlias(doc, cur);
      cur = cur->next;
    }
    return;
  }

  if (!xmlStrcmp(cur->name, (const xmlChar *) "Hints")) {
    cur = cur->xmlChildrenNode;
    while (cur != NULL) {
      parseHint(doc, cur);
      cur = cur->next;
    }
    return;
  }
}

void Camera::parseCFA(xmlDocPtr doc, xmlNodePtr cur) {
  xmlChar *key;
  if (!xmlStrcmp(cur->name, (const xmlChar *) "Color")) {
    int x = getAttributeAsInt(cur, cur->name, "x");
    if (x < 0 || x > 1) {
      ThrowCME("Invalid x coordinate in CFA array of in camera %s %s", make.c_str(), model.c_str());
    }

    int y = getAttributeAsInt(cur, cur->name, "y");
    if (y < 0 || y > 1) {
      ThrowCME("Invalid y coordinate in CFA array of in camera %s %s", make.c_str(), model.c_str());
    }

    key = xmlNodeListGetString(doc, cur->children, 1);
    if (!xmlStrcmp(key, (const xmlChar *) "GREEN"))
      cfa.setColorAt(iPoint2D(x, y), CFA_GREEN);
    else if (!xmlStrcmp(key, (const xmlChar *) "RED"))
      cfa.setColorAt(iPoint2D(x, y), CFA_RED);
    else if (!xmlStrcmp(key, (const xmlChar *) "BLUE"))
      cfa.setColorAt(iPoint2D(x, y), CFA_BLUE);

    xmlFree(key);
  }
}

void Camera::parseBlackAreas(xmlDocPtr doc, xmlNodePtr cur) {
  if (!xmlStrcmp(cur->name, (const xmlChar *) "Vertical")) {

    int x = getAttributeAsInt(cur, cur->name, "x");
    if (x < 0) {
      ThrowCME("Invalid x coordinate in vertical BlackArea of in camera %s %s", make.c_str(), model.c_str());
    }

    int w = getAttributeAsInt(cur, cur->name, "width");
    if (w < 0) {
      ThrowCME("Invalid width in vertical BlackArea of in camera %s %s", make.c_str(), model.c_str());
    }

    blackAreas.push_back(BlackArea(x, w, true));

  } else if (!xmlStrcmp(cur->name, (const xmlChar *) "Horizontal")) {

    int y = getAttributeAsInt(cur, cur->name, "y");
    if (y < 0) {
      ThrowCME("Invalid y coordinate in horizontal BlackArea of in camera %s %s", make.c_str(), model.c_str());
    }

    int h = getAttributeAsInt(cur, cur->name, "height");
    if (h < 0) {
      ThrowCME("Invalid width in horizontal BlackArea of in camera %s %s", make.c_str(), model.c_str());
    }

    blackAreas.push_back(BlackArea(y, h, false));

  }
}

int Camera::StringToInt(const xmlChar *in, const xmlChar *tag, const char* attribute) {
  int i;

#if defined(__unix__) || defined(__APPLE__) || defined(__MINGW32__)
  if (EOF == sscanf((const char*)in, "%d", &i))
#else
  if (EOF == sscanf_s((const char*)in, "%d", &i))
#endif
    ThrowCME("Error parsing attribute %s in tag %s, in camera %s %s.", attribute, tag, make.c_str(), model.c_str());

  return i;
}

vector<int> Camera::MultipleStringToInt(const xmlChar *in, const xmlChar *tag, const char* attribute) {
  int i;
  vector<int> ret;
  vector<string> v = split_string(string((const char*)in), ' ');

  for (uint32 j = 0; j < v.size(); j++) {
#if defined(__unix__) || defined(__APPLE__) || defined(__MINGW32__)
    if (EOF == sscanf(v[j].c_str(), "%d", &i))
#else
    if (EOF == sscanf_s(v[j].c_str(), "%d", &i))
#endif
      ThrowCME("Error parsing attribute %s in tag %s, in camera %s %s.", attribute, tag, make.c_str(), model.c_str());
    ret.push_back(i);
  }
  return ret;
}

int Camera::getAttributeAsInt(xmlNodePtr cur , const xmlChar *tag, const char* attribute) {
  xmlChar *key = xmlGetProp(cur, (const xmlChar *)attribute);

  if (!key)
    ThrowCME("Could not find attribute %s in tag %s, in camera %s %s.", attribute, tag, make.c_str(), model.c_str());

  try {
    int i = StringToInt(key, tag, attribute);
    xmlFree(key);
    return i;
  } catch (CameraMetadataException &e) {
    xmlFree(key);
    throw e;
  }

 /* Never actually reachable */
  return 0;
}

void Camera::parseAlias( xmlDocPtr doc, xmlNodePtr cur )
{
  if (!xmlStrcmp(cur->name, (const xmlChar *) "Alias")) {
    cur = cur->xmlChildrenNode;
    while (NULL != cur) {
      if (cur && !xmlStrcmp(cur->name, (const xmlChar *) "text"))
        aliases.push_back(string((const char*)cur->content));
      cur = cur->next;
    }
  }
}

void Camera::parseHint( xmlDocPtr doc, xmlNodePtr cur )
{
  if (!xmlStrcmp(cur->name, (const xmlChar *) "Hint")) {
    xmlChar *key;
    string hint_name, hint_value;
    key = xmlGetProp(cur, (const xmlChar *)"name");
    if (key) {
      hint_name = string((const char*)key);
      xmlFree(key);
    }
    else
      ThrowCME("CameraMetadata: Could not find name for hint for %s %s camera.", make.c_str(), model.c_str());

    key = xmlGetProp(cur, (const xmlChar *)"value");
    if (key) {
      hint_value = string((const char*)key);
      xmlFree(key);
    }
    else
      ThrowCME("CameraMetadata: Could not find value for hint %s for %s %s camera.", hint_name.c_str(), make.c_str(), model.c_str());

    hints.insert(make_pair(hint_name, hint_value));
  }
}

void Camera::parseSensorInfo( xmlDocPtr doc, xmlNodePtr cur )
{
  int min_iso = 0;
  int max_iso = 0;
  int black = getAttributeAsInt(cur, cur->name, "black");
  int white = getAttributeAsInt(cur, cur->name, "white");

  xmlChar *key = xmlGetProp(cur, (const xmlChar *)"iso_min");
  if (key) {
    min_iso = StringToInt(key, cur->name, "iso_min");
    xmlFree(key);
  }

  key = xmlGetProp(cur, (const xmlChar *)"iso_max");
  if (key) {
    max_iso = StringToInt(key, cur->name, "iso_max");
    xmlFree(key);
  }
  key = xmlGetProp(cur, (const xmlChar *)"iso_list");
  if (key) {
    vector<int> values = MultipleStringToInt(key, cur->name, "iso_list");
    xmlFree(key);
    if (!values.empty()) {
      for (uint32 i = 0; i < values.size(); i++) {
        sensorInfo.push_back(CameraSensorInfo(black, white, values[i], values[i]));
      }
    }
  } else {
    sensorInfo.push_back(CameraSensorInfo(black, white, min_iso, max_iso));
  }

}

const CameraSensorInfo* Camera::getSensorInfo( int iso )
{
  /* If only one, just return that */
  if (sensorInfo.size() == 1)
    return &sensorInfo[0];

  vector<CameraSensorInfo*> candidates;
  vector<CameraSensorInfo>::iterator i = sensorInfo.begin();
  do
  {
    if (i->isIsoWithin(iso))
      candidates.push_back(&(*i));
  } while (++i != sensorInfo.end());

  if (candidates.size() == 1)
    return candidates[0];

  vector<CameraSensorInfo*>::iterator j = candidates.begin();
  do
  {
    if (!(*j)->isDefault())
      return *j;
  } while (++j != candidates.end());
  /* Several defaults??? Just return first */
  return candidates[0];
}

} // namespace RawSpeed
<commit_msg>Just mark camera as unsupported if CFA size isn't 2x2.<commit_after>#include "StdAfx.h"
#include "Camera.h"
#include <iostream>
/*
    RawSpeed - RAW file decoder.

    Copyright (C) 2009 Klaus Post

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library 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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

    http://www.klauspost.com
*/

namespace RawSpeed {

Camera::Camera(xmlDocPtr doc, xmlNodePtr cur) {
  xmlChar *key;
  key = xmlGetProp(cur, (const xmlChar *)"make");
  if (!key)
    ThrowCME("Camera XML Parser: \"make\" attribute not found.");
  make = string((const char*)key);
  xmlFree(key);

  key = xmlGetProp(cur, (const xmlChar *)"model");
  if (!key)
    ThrowCME("Camera XML Parser: \"model\" attribute not found.");
  model = string((const char*)key);
  xmlFree(key);

  supported = true;
  key = xmlGetProp(cur, (const xmlChar *)"supported");
  if (key) {
    string s = string((const char*)key);
    if (s.compare("no") == 0)
      supported = false;
    xmlFree(key);
  }

  key = xmlGetProp(cur, (const xmlChar *)"mode");
  if (key) {
    mode = string((const char*)key);
    xmlFree(key);
  } else {
    mode = string("");
  }

  key = xmlGetProp(cur, (const xmlChar *)"decoder_version");
  if (key) {
    decoderVersion = getAttributeAsInt(cur, cur->name, "decoder_version");
    xmlFree(key);
  } else {
    decoderVersion = 0;
  }

  cur = cur->xmlChildrenNode;
  while (cur != NULL) {
    parseCameraChild(doc, cur);
    cur = cur->next;
  }
}

Camera::Camera( const Camera* camera, uint32 alias_num)
{
  if (alias_num >= camera->aliases.size())
    ThrowCME("Camera: Internal error, alias number out of range specified.");

  make = camera->make;
  model = camera->aliases[alias_num];
  mode = camera->mode;
  cfa = camera->cfa;
  supported = camera->supported;
  cropSize = camera->cropSize;
  cropPos = camera->cropPos;
  decoderVersion = camera->decoderVersion;
  for (uint32 i = 0; i < camera->blackAreas.size(); i++) {
    blackAreas.push_back(camera->blackAreas[i]);
  }
  for (uint32 i = 0; i < camera->sensorInfo.size(); i++) {
    sensorInfo.push_back(camera->sensorInfo[i]);
  }
  map<string,string>::const_iterator mi = camera->hints.begin();
  for (; mi != camera->hints.end(); ++mi) {
    hints.insert(make_pair((*mi).first, (*mi).second));
  }
}

Camera::~Camera(void) {
}

void Camera::parseCameraChild(xmlDocPtr doc, xmlNodePtr cur) {

  if (!xmlStrcmp(cur->name, (const xmlChar *) "CFA")) {
    if (2 != getAttributeAsInt(cur, cur->name, "width") || 2 != getAttributeAsInt(cur, cur->name, "height")) {
      supported = FALSE;
    } else {
      cur = cur->xmlChildrenNode;
      while (cur != NULL) {
        parseCFA(doc, cur);
        cur = cur->next;
      }
    }
    return;
  }
  if (!xmlStrcmp(cur->name, (const xmlChar *) "Crop")) {
    cropPos.x = getAttributeAsInt(cur, cur->name, "x");
    cropPos.y = getAttributeAsInt(cur, cur->name, "y");

    if (cropPos.x < 0)
      ThrowCME("Negative X axis crop specified in camera %s %s", make.c_str(), model.c_str());
    if (cropPos.y < 0)
      ThrowCME("Negative Y axis crop specified in camera %s %s", make.c_str(), model.c_str());

    cropSize.x = getAttributeAsInt(cur, cur->name, "width");
    cropSize.y = getAttributeAsInt(cur, cur->name, "height");
    return;
  }

  if (!xmlStrcmp(cur->name, (const xmlChar *) "Sensor")) {
    parseSensorInfo(doc, cur);
    return;
  }

  if (!xmlStrcmp(cur->name, (const xmlChar *) "BlackAreas")) {
    cur = cur->xmlChildrenNode;
    while (cur != NULL) {
      parseBlackAreas(doc, cur);
      cur = cur->next;
    }
    return;
  }

  if (!xmlStrcmp(cur->name, (const xmlChar *) "Aliases")) {
    cur = cur->xmlChildrenNode;
    while (cur != NULL) {
      parseAlias(doc, cur);
      cur = cur->next;
    }
    return;
  }

  if (!xmlStrcmp(cur->name, (const xmlChar *) "Hints")) {
    cur = cur->xmlChildrenNode;
    while (cur != NULL) {
      parseHint(doc, cur);
      cur = cur->next;
    }
    return;
  }
}

void Camera::parseCFA(xmlDocPtr doc, xmlNodePtr cur) {
  xmlChar *key;
  if (!xmlStrcmp(cur->name, (const xmlChar *) "Color")) {
    int x = getAttributeAsInt(cur, cur->name, "x");
    if (x < 0 || x > 1) {
      ThrowCME("Invalid x coordinate in CFA array of in camera %s %s", make.c_str(), model.c_str());
    }

    int y = getAttributeAsInt(cur, cur->name, "y");
    if (y < 0 || y > 1) {
      ThrowCME("Invalid y coordinate in CFA array of in camera %s %s", make.c_str(), model.c_str());
    }

    key = xmlNodeListGetString(doc, cur->children, 1);
    if (!xmlStrcmp(key, (const xmlChar *) "GREEN"))
      cfa.setColorAt(iPoint2D(x, y), CFA_GREEN);
    else if (!xmlStrcmp(key, (const xmlChar *) "RED"))
      cfa.setColorAt(iPoint2D(x, y), CFA_RED);
    else if (!xmlStrcmp(key, (const xmlChar *) "BLUE"))
      cfa.setColorAt(iPoint2D(x, y), CFA_BLUE);

    xmlFree(key);
  }
}

void Camera::parseBlackAreas(xmlDocPtr doc, xmlNodePtr cur) {
  if (!xmlStrcmp(cur->name, (const xmlChar *) "Vertical")) {

    int x = getAttributeAsInt(cur, cur->name, "x");
    if (x < 0) {
      ThrowCME("Invalid x coordinate in vertical BlackArea of in camera %s %s", make.c_str(), model.c_str());
    }

    int w = getAttributeAsInt(cur, cur->name, "width");
    if (w < 0) {
      ThrowCME("Invalid width in vertical BlackArea of in camera %s %s", make.c_str(), model.c_str());
    }

    blackAreas.push_back(BlackArea(x, w, true));

  } else if (!xmlStrcmp(cur->name, (const xmlChar *) "Horizontal")) {

    int y = getAttributeAsInt(cur, cur->name, "y");
    if (y < 0) {
      ThrowCME("Invalid y coordinate in horizontal BlackArea of in camera %s %s", make.c_str(), model.c_str());
    }

    int h = getAttributeAsInt(cur, cur->name, "height");
    if (h < 0) {
      ThrowCME("Invalid width in horizontal BlackArea of in camera %s %s", make.c_str(), model.c_str());
    }

    blackAreas.push_back(BlackArea(y, h, false));

  }
}

int Camera::StringToInt(const xmlChar *in, const xmlChar *tag, const char* attribute) {
  int i;

#if defined(__unix__) || defined(__APPLE__) || defined(__MINGW32__)
  if (EOF == sscanf((const char*)in, "%d", &i))
#else
  if (EOF == sscanf_s((const char*)in, "%d", &i))
#endif
    ThrowCME("Error parsing attribute %s in tag %s, in camera %s %s.", attribute, tag, make.c_str(), model.c_str());

  return i;
}

vector<int> Camera::MultipleStringToInt(const xmlChar *in, const xmlChar *tag, const char* attribute) {
  int i;
  vector<int> ret;
  vector<string> v = split_string(string((const char*)in), ' ');

  for (uint32 j = 0; j < v.size(); j++) {
#if defined(__unix__) || defined(__APPLE__) || defined(__MINGW32__)
    if (EOF == sscanf(v[j].c_str(), "%d", &i))
#else
    if (EOF == sscanf_s(v[j].c_str(), "%d", &i))
#endif
      ThrowCME("Error parsing attribute %s in tag %s, in camera %s %s.", attribute, tag, make.c_str(), model.c_str());
    ret.push_back(i);
  }
  return ret;
}

int Camera::getAttributeAsInt(xmlNodePtr cur , const xmlChar *tag, const char* attribute) {
  xmlChar *key = xmlGetProp(cur, (const xmlChar *)attribute);

  if (!key)
    ThrowCME("Could not find attribute %s in tag %s, in camera %s %s.", attribute, tag, make.c_str(), model.c_str());

  try {
    int i = StringToInt(key, tag, attribute);
    xmlFree(key);
    return i;
  } catch (CameraMetadataException &e) {
    xmlFree(key);
    throw e;
  }

 /* Never actually reachable */
  return 0;
}

void Camera::parseAlias( xmlDocPtr doc, xmlNodePtr cur )
{
  if (!xmlStrcmp(cur->name, (const xmlChar *) "Alias")) {
    cur = cur->xmlChildrenNode;
    while (NULL != cur) {
      if (cur && !xmlStrcmp(cur->name, (const xmlChar *) "text"))
        aliases.push_back(string((const char*)cur->content));
      cur = cur->next;
    }
  }
}

void Camera::parseHint( xmlDocPtr doc, xmlNodePtr cur )
{
  if (!xmlStrcmp(cur->name, (const xmlChar *) "Hint")) {
    xmlChar *key;
    string hint_name, hint_value;
    key = xmlGetProp(cur, (const xmlChar *)"name");
    if (key) {
      hint_name = string((const char*)key);
      xmlFree(key);
    }
    else
      ThrowCME("CameraMetadata: Could not find name for hint for %s %s camera.", make.c_str(), model.c_str());

    key = xmlGetProp(cur, (const xmlChar *)"value");
    if (key) {
      hint_value = string((const char*)key);
      xmlFree(key);
    }
    else
      ThrowCME("CameraMetadata: Could not find value for hint %s for %s %s camera.", hint_name.c_str(), make.c_str(), model.c_str());

    hints.insert(make_pair(hint_name, hint_value));
  }
}

void Camera::parseSensorInfo( xmlDocPtr doc, xmlNodePtr cur )
{
  int min_iso = 0;
  int max_iso = 0;
  int black = getAttributeAsInt(cur, cur->name, "black");
  int white = getAttributeAsInt(cur, cur->name, "white");

  xmlChar *key = xmlGetProp(cur, (const xmlChar *)"iso_min");
  if (key) {
    min_iso = StringToInt(key, cur->name, "iso_min");
    xmlFree(key);
  }

  key = xmlGetProp(cur, (const xmlChar *)"iso_max");
  if (key) {
    max_iso = StringToInt(key, cur->name, "iso_max");
    xmlFree(key);
  }
  key = xmlGetProp(cur, (const xmlChar *)"iso_list");
  if (key) {
    vector<int> values = MultipleStringToInt(key, cur->name, "iso_list");
    xmlFree(key);
    if (!values.empty()) {
      for (uint32 i = 0; i < values.size(); i++) {
        sensorInfo.push_back(CameraSensorInfo(black, white, values[i], values[i]));
      }
    }
  } else {
    sensorInfo.push_back(CameraSensorInfo(black, white, min_iso, max_iso));
  }

}

const CameraSensorInfo* Camera::getSensorInfo( int iso )
{
  /* If only one, just return that */
  if (sensorInfo.size() == 1)
    return &sensorInfo[0];

  vector<CameraSensorInfo*> candidates;
  vector<CameraSensorInfo>::iterator i = sensorInfo.begin();
  do
  {
    if (i->isIsoWithin(iso))
      candidates.push_back(&(*i));
  } while (++i != sensorInfo.end());

  if (candidates.size() == 1)
    return candidates[0];

  vector<CameraSensorInfo*>::iterator j = candidates.begin();
  do
  {
    if (!(*j)->isDefault())
      return *j;
  } while (++j != candidates.end());
  /* Several defaults??? Just return first */
  return candidates[0];
}

} // namespace RawSpeed
<|endoftext|>


<commit_before><commit_msg>Move link prefetch field trial to 2% for m7, using 1000 base<commit_after><|endoftext|>


<commit_before>#define WIN32_LEAN_AND_MEAN
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif

#include <assert.h>
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <malloc.h>

#include "../../MemoryModule.h"

typedef int (*addNumberProc)(int, int);

#define DLL_FILE TEXT("..\\SampleDLL\\SampleDLL.dll")

void LoadFromFile(void)
{
    addNumberProc addNumber;
    HRSRC resourceInfo;
    DWORD resourceSize;
    LPVOID resourceData;
    TCHAR buffer[100];

    HINSTANCE handle = LoadLibrary(DLL_FILE);
    if (handle == NULL)
        return;

    addNumber = (addNumberProc)GetProcAddress(handle, "addNumbers");
    _tprintf(_T("From file: %d\n"), addNumber(1, 2));

    resourceInfo = FindResource(handle, MAKEINTRESOURCE(VS_VERSION_INFO), RT_VERSION);
    _tprintf(_T("FindResource returned 0x%p\n"), resourceInfo);

    resourceSize = SizeofResource(handle, resourceInfo);
    resourceData = LoadResource(handle, resourceInfo);
    _tprintf(_T("Resource data: %ld bytes at 0x%p\n"), resourceSize, resourceData);

    LoadString(handle, 1, buffer, sizeof(buffer));
    _tprintf(_T("String1: %s\n"), buffer);

    LoadString(handle, 20, buffer, sizeof(buffer));
    _tprintf(_T("String2: %s\n"), buffer);

    FreeLibrary(handle);
}

void* ReadLibrary(long* pSize) {
    long read;
    void* result;
    FILE* fp;

    fp = _tfopen(DLL_FILE, _T("rb"));
    if (fp == NULL)
    {
        _tprintf(_T("Can't open DLL file \"%s\"."), DLL_FILE);
        return NULL;
    }

    fseek(fp, 0, SEEK_END);
    *pSize = ftell(fp);
    if (*pSize < 0)
    {
        fclose(fp);
        return NULL;
    }

    result = (unsigned char *)malloc(*pSize);
    if (result == NULL)
    {
        return NULL;
    }

    fseek(fp, 0, SEEK_SET);
    read = fread(result, 1, *pSize, fp);
    fclose(fp);
    if (read != static_cast<size_t>(*pSize))
    {
        free(result);
        return NULL;
    }

    return result;
}

void LoadFromMemory(void)
{
    void *data;
    long size;
    HMEMORYMODULE handle;
    addNumberProc addNumber;
    HMEMORYRSRC resourceInfo;
    DWORD resourceSize;
    LPVOID resourceData;
    TCHAR buffer[100];

    data = ReadLibrary(&size);
    if (data == NULL)
    {
        return;
    }

    handle = MemoryLoadLibrary(data, size);
    if (handle == NULL)
    {
        _tprintf(_T("Can't load library from memory.\n"));
        goto exit;
    }

    addNumber = (addNumberProc)MemoryGetProcAddress(handle, "addNumbers");
    _tprintf(_T("From memory: %d\n"), addNumber(1, 2));

    resourceInfo = MemoryFindResource(handle, MAKEINTRESOURCE(VS_VERSION_INFO), RT_VERSION);
    _tprintf(_T("MemoryFindResource returned 0x%p\n"), resourceInfo);

    resourceSize = MemorySizeofResource(handle, resourceInfo);
    resourceData = MemoryLoadResource(handle, resourceInfo);
    _tprintf(_T("Memory resource data: %ld bytes at 0x%p\n"), resourceSize, resourceData);

    MemoryLoadString(handle, 1, buffer, sizeof(buffer));
    _tprintf(_T("String1: %s\n"), buffer);

    MemoryLoadString(handle, 20, buffer, sizeof(buffer));
    _tprintf(_T("String2: %s\n"), buffer);

    MemoryFreeLibrary(handle);

exit:
    free(data);
}

#define MAX_CALLS 20

struct CallList {
    int current_alloc_call, current_free_call;
    CustomAllocFunc alloc_calls[MAX_CALLS];
    CustomFreeFunc free_calls[MAX_CALLS];
};

LPVOID MemoryFailingAlloc(LPVOID address, SIZE_T size, DWORD allocationType, DWORD protect, void* userdata)
{
    UNREFERENCED_PARAMETER(address);
    UNREFERENCED_PARAMETER(size);
    UNREFERENCED_PARAMETER(allocationType);
    UNREFERENCED_PARAMETER(protect);
    UNREFERENCED_PARAMETER(userdata);
    return NULL;
}

LPVOID MemoryMockAlloc(LPVOID address, SIZE_T size, DWORD allocationType, DWORD protect, void* userdata)
{
    CallList* calls = (CallList*)userdata;
    CustomAllocFunc current_func = calls->alloc_calls[calls->current_alloc_call++];
    assert(current_func != NULL);
    return current_func(address, size, allocationType, protect, NULL);
}

BOOL MemoryMockFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType, void* userdata)
{
    CallList* calls = (CallList*)userdata;
    CustomFreeFunc current_func = calls->free_calls[calls->current_free_call++];
    assert(current_func != NULL);
    return current_func(lpAddress, dwSize, dwFreeType, NULL);
}

void InitFuncs(void** funcs, va_list args) {
    for (int i = 0; ; i++) {
        assert(i < MAX_CALLS);
        funcs[i] = va_arg(args, void*);
        if (funcs[i] == NULL) break;
    }
}

void InitAllocFuncs(CallList* calls, ...) {
    va_list args;
    va_start(args, calls);
    InitFuncs((void**)calls->alloc_calls, args);
    va_end(args);
    calls->current_alloc_call = 0;
}

void InitFreeFuncs(CallList* calls, ...) {
    va_list args;
    va_start(args, calls);
    InitFuncs((void**)calls->free_calls, args);
    va_end(args);
    calls->current_free_call = 0;
}

void InitFreeFunc(CallList* calls, CustomFreeFunc freeFunc) {
	for (int i = 0; i < MAX_CALLS; i++) {
		calls->free_calls[i] = freeFunc;
	}
	calls->current_free_call = 0;
}

void TestFailingAllocation(void *data, long size) {
    CallList expected_calls;
    HMEMORYMODULE handle;

    InitAllocFuncs(&expected_calls, MemoryFailingAlloc, MemoryFailingAlloc, NULL);
    InitFreeFuncs(&expected_calls, NULL);

    handle = MemoryLoadLibraryEx(
        data, size, MemoryMockAlloc, MemoryMockFree, MemoryDefaultLoadLibrary,
        MemoryDefaultGetProcAddress, MemoryDefaultFreeLibrary, &expected_calls);

    assert(handle == NULL);
    assert(GetLastError() == ERROR_OUTOFMEMORY);
    assert(expected_calls.current_free_call == 0);

    MemoryFreeLibrary(handle);
    assert(expected_calls.current_free_call == 0);
}

void TestCleanupAfterFailingAllocation(void *data, long size) {
    CallList expected_calls;
    HMEMORYMODULE handle;
    int free_calls_after_loading;

    InitAllocFuncs(&expected_calls,
        MemoryDefaultAlloc,
        MemoryDefaultAlloc,
        MemoryDefaultAlloc,
        MemoryDefaultAlloc,
        MemoryFailingAlloc,
        NULL);
    InitFreeFuncs(&expected_calls, MemoryDefaultFree, NULL);

    handle = MemoryLoadLibraryEx(
        data, size, MemoryMockAlloc, MemoryMockFree, MemoryDefaultLoadLibrary,
        MemoryDefaultGetProcAddress, MemoryDefaultFreeLibrary, &expected_calls);

    free_calls_after_loading = expected_calls.current_free_call;

    MemoryFreeLibrary(handle);
    assert(expected_calls.current_free_call == free_calls_after_loading);
}

void TestFreeAfterDefaultAlloc(void *data, long size) {
    CallList expected_calls;
    HMEMORYMODULE handle;
    int free_calls_after_loading;

	// Note: free might get called internally multiple times
    InitFreeFunc(&expected_calls, MemoryDefaultFree);

    handle = MemoryLoadLibraryEx(
        data, size, MemoryDefaultAlloc, MemoryMockFree, MemoryDefaultLoadLibrary,
        MemoryDefaultGetProcAddress, MemoryDefaultFreeLibrary, &expected_calls);

    assert(handle != NULL);
    free_calls_after_loading = expected_calls.current_free_call;

    MemoryFreeLibrary(handle);
    assert(expected_calls.current_free_call == free_calls_after_loading + 1);
}

void TestCustomAllocAndFree(void)
{
    void *data;
    long size;

    data = ReadLibrary(&size);
    if (data == NULL)
    {
        return;
    }

    _tprintf(_T("Test MemoryLoadLibraryEx after initially failing allocation function\n"));
    TestFailingAllocation(data, size);
    _tprintf(_T("Test cleanup after MemoryLoadLibraryEx with failing allocation function\n"));
    TestCleanupAfterFailingAllocation(data, size);
    _tprintf(_T("Test custom free function after MemoryLoadLibraryEx\n"));
    TestFreeAfterDefaultAlloc(data, size);

    free(data);
}

int main()
{
    LoadFromFile();
    printf("\n\n");
    LoadFromMemory();
    printf("\n\n");
    TestCustomAllocAndFree();
    return 0;
}

<commit_msg>Use "size_t" instead of "long" for sizes.<commit_after>#define WIN32_LEAN_AND_MEAN
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif

#include <assert.h>
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <malloc.h>

#include "../../MemoryModule.h"

typedef int (*addNumberProc)(int, int);

#define DLL_FILE TEXT("..\\SampleDLL\\SampleDLL.dll")

void LoadFromFile(void)
{
    addNumberProc addNumber;
    HRSRC resourceInfo;
    DWORD resourceSize;
    LPVOID resourceData;
    TCHAR buffer[100];

    HINSTANCE handle = LoadLibrary(DLL_FILE);
    if (handle == NULL)
        return;

    addNumber = (addNumberProc)GetProcAddress(handle, "addNumbers");
    _tprintf(_T("From file: %d\n"), addNumber(1, 2));

    resourceInfo = FindResource(handle, MAKEINTRESOURCE(VS_VERSION_INFO), RT_VERSION);
    _tprintf(_T("FindResource returned 0x%p\n"), resourceInfo);

    resourceSize = SizeofResource(handle, resourceInfo);
    resourceData = LoadResource(handle, resourceInfo);
    _tprintf(_T("Resource data: %ld bytes at 0x%p\n"), resourceSize, resourceData);

    LoadString(handle, 1, buffer, sizeof(buffer));
    _tprintf(_T("String1: %s\n"), buffer);

    LoadString(handle, 20, buffer, sizeof(buffer));
    _tprintf(_T("String2: %s\n"), buffer);

    FreeLibrary(handle);
}

void* ReadLibrary(size_t* pSize) {
    size_t read;
    void* result;
    FILE* fp;

    fp = _tfopen(DLL_FILE, _T("rb"));
    if (fp == NULL)
    {
        _tprintf(_T("Can't open DLL file \"%s\"."), DLL_FILE);
        return NULL;
    }

    fseek(fp, 0, SEEK_END);
    *pSize = static_cast<size_t>(ftell(fp));
    if (*pSize == 0)
    {
        fclose(fp);
        return NULL;
    }

    result = (unsigned char *)malloc(*pSize);
    if (result == NULL)
    {
        return NULL;
    }

    fseek(fp, 0, SEEK_SET);
    read = fread(result, 1, *pSize, fp);
    fclose(fp);
    if (read != *pSize)
    {
        free(result);
        return NULL;
    }

    return result;
}

void LoadFromMemory(void)
{
    void *data;
    size_t size;
    HMEMORYMODULE handle;
    addNumberProc addNumber;
    HMEMORYRSRC resourceInfo;
    DWORD resourceSize;
    LPVOID resourceData;
    TCHAR buffer[100];

    data = ReadLibrary(&size);
    if (data == NULL)
    {
        return;
    }

    handle = MemoryLoadLibrary(data, size);
    if (handle == NULL)
    {
        _tprintf(_T("Can't load library from memory.\n"));
        goto exit;
    }

    addNumber = (addNumberProc)MemoryGetProcAddress(handle, "addNumbers");
    _tprintf(_T("From memory: %d\n"), addNumber(1, 2));

    resourceInfo = MemoryFindResource(handle, MAKEINTRESOURCE(VS_VERSION_INFO), RT_VERSION);
    _tprintf(_T("MemoryFindResource returned 0x%p\n"), resourceInfo);

    resourceSize = MemorySizeofResource(handle, resourceInfo);
    resourceData = MemoryLoadResource(handle, resourceInfo);
    _tprintf(_T("Memory resource data: %ld bytes at 0x%p\n"), resourceSize, resourceData);

    MemoryLoadString(handle, 1, buffer, sizeof(buffer));
    _tprintf(_T("String1: %s\n"), buffer);

    MemoryLoadString(handle, 20, buffer, sizeof(buffer));
    _tprintf(_T("String2: %s\n"), buffer);

    MemoryFreeLibrary(handle);

exit:
    free(data);
}

#define MAX_CALLS 20

struct CallList {
    int current_alloc_call, current_free_call;
    CustomAllocFunc alloc_calls[MAX_CALLS];
    CustomFreeFunc free_calls[MAX_CALLS];
};

LPVOID MemoryFailingAlloc(LPVOID address, SIZE_T size, DWORD allocationType, DWORD protect, void* userdata)
{
    UNREFERENCED_PARAMETER(address);
    UNREFERENCED_PARAMETER(size);
    UNREFERENCED_PARAMETER(allocationType);
    UNREFERENCED_PARAMETER(protect);
    UNREFERENCED_PARAMETER(userdata);
    return NULL;
}

LPVOID MemoryMockAlloc(LPVOID address, SIZE_T size, DWORD allocationType, DWORD protect, void* userdata)
{
    CallList* calls = (CallList*)userdata;
    CustomAllocFunc current_func = calls->alloc_calls[calls->current_alloc_call++];
    assert(current_func != NULL);
    return current_func(address, size, allocationType, protect, NULL);
}

BOOL MemoryMockFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType, void* userdata)
{
    CallList* calls = (CallList*)userdata;
    CustomFreeFunc current_func = calls->free_calls[calls->current_free_call++];
    assert(current_func != NULL);
    return current_func(lpAddress, dwSize, dwFreeType, NULL);
}

void InitFuncs(void** funcs, va_list args) {
    for (int i = 0; ; i++) {
        assert(i < MAX_CALLS);
        funcs[i] = va_arg(args, void*);
        if (funcs[i] == NULL) break;
    }
}

void InitAllocFuncs(CallList* calls, ...) {
    va_list args;
    va_start(args, calls);
    InitFuncs((void**)calls->alloc_calls, args);
    va_end(args);
    calls->current_alloc_call = 0;
}

void InitFreeFuncs(CallList* calls, ...) {
    va_list args;
    va_start(args, calls);
    InitFuncs((void**)calls->free_calls, args);
    va_end(args);
    calls->current_free_call = 0;
}

void InitFreeFunc(CallList* calls, CustomFreeFunc freeFunc) {
	for (int i = 0; i < MAX_CALLS; i++) {
		calls->free_calls[i] = freeFunc;
	}
	calls->current_free_call = 0;
}

void TestFailingAllocation(void *data, size_t size) {
    CallList expected_calls;
    HMEMORYMODULE handle;

    InitAllocFuncs(&expected_calls, MemoryFailingAlloc, MemoryFailingAlloc, NULL);
    InitFreeFuncs(&expected_calls, NULL);

    handle = MemoryLoadLibraryEx(
        data, size, MemoryMockAlloc, MemoryMockFree, MemoryDefaultLoadLibrary,
        MemoryDefaultGetProcAddress, MemoryDefaultFreeLibrary, &expected_calls);

    assert(handle == NULL);
    assert(GetLastError() == ERROR_OUTOFMEMORY);
    assert(expected_calls.current_free_call == 0);

    MemoryFreeLibrary(handle);
    assert(expected_calls.current_free_call == 0);
}

void TestCleanupAfterFailingAllocation(void *data, size_t size) {
    CallList expected_calls;
    HMEMORYMODULE handle;
    int free_calls_after_loading;

    InitAllocFuncs(&expected_calls,
        MemoryDefaultAlloc,
        MemoryDefaultAlloc,
        MemoryDefaultAlloc,
        MemoryDefaultAlloc,
        MemoryFailingAlloc,
        NULL);
    InitFreeFuncs(&expected_calls, MemoryDefaultFree, NULL);

    handle = MemoryLoadLibraryEx(
        data, size, MemoryMockAlloc, MemoryMockFree, MemoryDefaultLoadLibrary,
        MemoryDefaultGetProcAddress, MemoryDefaultFreeLibrary, &expected_calls);

    free_calls_after_loading = expected_calls.current_free_call;

    MemoryFreeLibrary(handle);
    assert(expected_calls.current_free_call == free_calls_after_loading);
}

void TestFreeAfterDefaultAlloc(void *data, size_t size) {
    CallList expected_calls;
    HMEMORYMODULE handle;
    int free_calls_after_loading;

	// Note: free might get called internally multiple times
    InitFreeFunc(&expected_calls, MemoryDefaultFree);

    handle = MemoryLoadLibraryEx(
        data, size, MemoryDefaultAlloc, MemoryMockFree, MemoryDefaultLoadLibrary,
        MemoryDefaultGetProcAddress, MemoryDefaultFreeLibrary, &expected_calls);

    assert(handle != NULL);
    free_calls_after_loading = expected_calls.current_free_call;

    MemoryFreeLibrary(handle);
    assert(expected_calls.current_free_call == free_calls_after_loading + 1);
}

void TestCustomAllocAndFree(void)
{
    void *data;
    size_t size;

    data = ReadLibrary(&size);
    if (data == NULL)
    {
        return;
    }

    _tprintf(_T("Test MemoryLoadLibraryEx after initially failing allocation function\n"));
    TestFailingAllocation(data, size);
    _tprintf(_T("Test cleanup after MemoryLoadLibraryEx with failing allocation function\n"));
    TestCleanupAfterFailingAllocation(data, size);
    _tprintf(_T("Test custom free function after MemoryLoadLibraryEx\n"));
    TestFreeAfterDefaultAlloc(data, size);

    free(data);
}

int main()
{
    LoadFromFile();
    printf("\n\n");
    LoadFromMemory();
    printf("\n\n");
    TestCustomAllocAndFree();
    return 0;
}

<|endoftext|>