<commit_before>//===- InlineFunction.cpp - Code to perform function inlining -------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements inlining of a function into a call site, resolving
// parameters and the return value as appropriate.
//
// FIXME: This pass should transform alloca instructions in the called function
// into alloca/dealloca pairs!  Or perhaps it should refuse to inline them!
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Constant.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/Instructions.h"
#include "llvm/Intrinsics.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Transforms/Utils/Local.h"
using namespace llvm;

bool llvm::InlineFunction(CallInst *CI) { return InlineFunction(CallSite(CI)); }
bool llvm::InlineFunction(InvokeInst *II) {return InlineFunction(CallSite(II));}

// InlineFunction - This function inlines the called function into the basic
// block of the caller.  This returns false if it is not possible to inline this
// call.  The program is still in a well defined state if this occurs though.
//
// Note that this only does one level of inlining.  For example, if the
// instruction 'call B' is inlined, and 'B' calls 'C', then the call to 'C' now
// exists in the instruction stream.  Similiarly this will inline a recursive
// function by one level.
//
bool llvm::InlineFunction(CallSite CS) {
  Instruction *TheCall = CS.getInstruction();
  assert(TheCall->getParent() && TheCall->getParent()->getParent() &&
         "Instruction not in function!");

  const Function *CalledFunc = CS.getCalledFunction();
  if (CalledFunc == 0 ||          // Can't inline external function or indirect
      CalledFunc->isExternal() || // call, or call to a vararg function!
      CalledFunc->getFunctionType()->isVarArg()) return false;

  BasicBlock *OrigBB = TheCall->getParent();
  Function *Caller = OrigBB->getParent();

  // Calculate the vector of arguments to pass into the function cloner...
  std::map<const Value*, Value*> ValueMap;
  assert(std::distance(CalledFunc->abegin(), CalledFunc->aend()) ==
         std::distance(CS.arg_begin(), CS.arg_end()) &&
         "No varargs calls can be inlined!");

  CallSite::arg_iterator AI = CS.arg_begin();
  for (Function::const_aiterator I = CalledFunc->abegin(), E=CalledFunc->aend();
       I != E; ++I, ++AI)
    ValueMap[I] = *AI;

  // Get an iterator to the last basic block in the function, which will have
  // the new function inlined after it.
  //
  Function::iterator LastBlock = &Caller->back();

  // Clone the entire body of the callee into the caller.  Make sure to capture
  // all of the return instructions from the cloned function.
  std::vector<ReturnInst*> Returns;
  CloneFunctionInto(Caller, CalledFunc, ValueMap, Returns, ".i");

  // We want to clone the entire callee function into the hole between the
  // "starter" and "ender" blocks.  How we accomplish this depends on whether
  // this is an invoke instruction or a call instruction.

  BasicBlock *InvokeDest = 0;     // Exception handling destination
  std::vector<Value*> InvokeDestPHIValues; // Values for PHI nodes in InvokeDest
  BasicBlock *AfterCallBB;

  if (InvokeInst *II = dyn_cast<InvokeInst>(TheCall)) {
    InvokeDest = II->getExceptionalDest();

    // If there are PHI nodes in the exceptional destination block, we need to
    // keep track of which values came into them from this invoke, then remove
    // the entry for this block.
    for (BasicBlock::iterator I = InvokeDest->begin();
         PHINode *PN = dyn_cast<PHINode>(I); ++I) {
      // Save the value to use for this edge...
      InvokeDestPHIValues.push_back(PN->getIncomingValueForBlock(OrigBB));
    }

    // Add an unconditional branch to make this look like the CallInst case...
    BranchInst *NewBr = new BranchInst(II->getNormalDest(), TheCall);

    // Split the basic block.  This guarantees that no PHI nodes will have to be
    // updated due to new incoming edges, and make the invoke case more
    // symmetric to the call case.
    AfterCallBB = OrigBB->splitBasicBlock(NewBr,
                                          CalledFunc->getName()+".entry");

    // Remove (unlink) the InvokeInst from the function...
    OrigBB->getInstList().remove(TheCall);

  } else {  // It's a call
    // If this is a call instruction, we need to split the basic block that the
    // call lives in.
    //
    AfterCallBB = OrigBB->splitBasicBlock(TheCall,
                                          CalledFunc->getName()+".entry");
    // Remove (unlink) the CallInst from the function...
    AfterCallBB->getInstList().remove(TheCall);
  }

  // If we have a return value generated by this call, convert it into a PHI
  // node that gets values from each of the old RET instructions in the original
  // function.
  //
  if (!TheCall->use_empty()) {
    // We only need to make the PHI if there is more than one return instruction
    if (Returns.size() > 1) {
      // The PHI node should go at the front of the new basic block to merge all
      // possible incoming values.
      //
      PHINode *PHI = new PHINode(CalledFunc->getReturnType(),
                                 TheCall->getName(), AfterCallBB->begin());

      // Anything that used the result of the function call should now use the
      // PHI node as their operand.
      //
      TheCall->replaceAllUsesWith(PHI);

      // Add all of the return instructions as entries in the PHI node.
      for (unsigned i = 0, e = Returns.size(); i != e; ++i) {
        ReturnInst *RI = Returns[i];

        assert(RI->getReturnValue() && "Ret should have value!");
        assert(RI->getReturnValue()->getType() == PHI->getType() &&
               "Ret value not consistent in function!");
        PHI->addIncoming(RI->getReturnValue(), RI->getParent());
      }

    } else if (!Returns.empty()) {
      // Otherwise, if there is exactly one return value, just replace anything
      // using the return value of the call with the computed value.
      TheCall->replaceAllUsesWith(Returns[0]->getReturnValue());
    }
  }

  // Since we are now done with the Call/Invoke, we can delete it.
  delete TheCall;

  // Loop over all of the return instructions, turning them into unconditional
  // branches to the merge point now...
  for (unsigned i = 0, e = Returns.size(); i != e; ++i) {
    ReturnInst *RI = Returns[i];

    // Add a branch to the merge point where the PHI node lives if it exists.
    new BranchInst(AfterCallBB, RI);

    // Delete the return instruction now
    RI->getParent()->getInstList().erase(RI);
  }

  // Change the branch that used to go to AfterCallBB to branch to the first
  // basic block of the inlined function.
  //
  TerminatorInst *Br = OrigBB->getTerminator();
  assert(Br && Br->getOpcode() == Instruction::Br &&
	 "splitBasicBlock broken!");
  Br->setOperand(0, ++LastBlock);

  // If there are any alloca instructions in the block that used to be the entry
  // block for the callee, move them to the entry block of the caller.  First
  // calculate which instruction they should be inserted before.  We insert the
  // instructions at the end of the current alloca list.
  //
  if (isa<AllocaInst>(LastBlock->begin())) {
    BasicBlock::iterator InsertPoint = Caller->begin()->begin();
    while (isa<AllocaInst>(InsertPoint)) ++InsertPoint;

    for (BasicBlock::iterator I = LastBlock->begin(), E = LastBlock->end();
         I != E; )
      if (AllocaInst *AI = dyn_cast<AllocaInst>(I++))
        if (isa<Constant>(AI->getArraySize())) {
          LastBlock->getInstList().remove(AI);
          Caller->front().getInstList().insert(InsertPoint, AI);
        }
  }

  // If we just inlined a call due to an invoke instruction, scan the inlined
  // function checking for function calls that should now be made into invoke
  // instructions, and for unwind's which should be turned into branches.
  if (InvokeDest) {
    for (Function::iterator BB = LastBlock, E = Caller->end(); BB != E; ++BB) {
      for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) {
        // We only need to check for function calls: inlined invoke instructions
        // require no special handling...
        if (CallInst *CI = dyn_cast<CallInst>(I)) {
          // Convert this function call into an invoke instruction...

          // First, split the basic block...
          BasicBlock *Split = BB->splitBasicBlock(CI, CI->getName()+".noexc");

          // Next, create the new invoke instruction, inserting it at the end
          // of the old basic block.
          InvokeInst *II =
            new InvokeInst(CI->getCalledValue(), Split, InvokeDest,
                           std::vector<Value*>(CI->op_begin()+1, CI->op_end()),
                           CI->getName(), BB->getTerminator());

          // Make sure that anything using the call now uses the invoke!
          CI->replaceAllUsesWith(II);

          // Delete the unconditional branch inserted by splitBasicBlock
          BB->getInstList().pop_back();
          Split->getInstList().pop_front();  // Delete the original call

          // Update any PHI nodes in the exceptional block to indicate that
          // there is now a new entry in them.
          unsigned i = 0;
          for (BasicBlock::iterator I = InvokeDest->begin();
               PHINode *PN = dyn_cast<PHINode>(I); ++I, ++i)
            PN->addIncoming(InvokeDestPHIValues[i], BB);

          // This basic block is now complete, start scanning the next one.
          break;
        } else {
          ++I;
        }
      }

      if (UnwindInst *UI = dyn_cast<UnwindInst>(BB->getTerminator())) {
        // An UnwindInst requires special handling when it gets inlined into an
        // invoke site.  Once this happens, we know that the unwind would cause
        // a control transfer to the invoke exception destination, so we can
        // transform it into a direct branch to the exception destination.
        new BranchInst(InvokeDest, UI);

        // Delete the unwind instruction!
        UI->getParent()->getInstList().pop_back();

        // Update any PHI nodes in the exceptional block to indicate that
        // there is now a new entry in them.
        unsigned i = 0;
        for (BasicBlock::iterator I = InvokeDest->begin();
             PHINode *PN = dyn_cast<PHINode>(I); ++I, ++i)
          PN->addIncoming(InvokeDestPHIValues[i], BB);
      }
    }

    // Now that everything is happy, we have one final detail.  The PHI nodes in
    // the exception destination block still have entries due to the original
    // invoke instruction.  Eliminate these entries (which might even delete the
    // PHI node) now.
    for (BasicBlock::iterator I = InvokeDest->begin();
         PHINode *PN = dyn_cast<PHINode>(I); ++I)
      PN->removeIncomingValue(AfterCallBB);
  }
  // Now that the function is correct, make it a little bit nicer.  In
  // particular, move the basic blocks inserted from the end of the function
  // into the space made by splitting the source basic block.
  //
  Caller->getBasicBlockList().splice(AfterCallBB, Caller->getBasicBlockList(),
                                     LastBlock, Caller->end());

  // We should always be able to fold the entry block of the function into the
  // single predecessor of the block...
  assert(cast<BranchInst>(Br)->isUnconditional() && "splitBasicBlock broken!");
  BasicBlock *CalleeEntry = cast<BranchInst>(Br)->getSuccessor(0);
  SimplifyCFG(CalleeEntry);

  // Okay, continue the CFG cleanup.  It's often the case that there is only a
  // single return instruction in the callee function.  If this is the case,
  // then we have an unconditional branch from the return block to the
  // 'AfterCallBB'.  Check for this case, and eliminate the branch is possible.
  SimplifyCFG(AfterCallBB);
  return true;
}
<commit_msg>More refactoring.  Move alloca instructions and handle invoke instructions before we delete the original call site, allowing slight simplifications of code, but nothing exciting.<commit_after>//===- InlineFunction.cpp - Code to perform function inlining -------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements inlining of a function into a call site, resolving
// parameters and the return value as appropriate.
//
// FIXME: This pass should transform alloca instructions in the called function
// into alloca/dealloca pairs!  Or perhaps it should refuse to inline them!
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Constant.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/Instructions.h"
#include "llvm/Intrinsics.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Transforms/Utils/Local.h"
using namespace llvm;

bool llvm::InlineFunction(CallInst *CI) { return InlineFunction(CallSite(CI)); }
bool llvm::InlineFunction(InvokeInst *II) {return InlineFunction(CallSite(II));}

// InlineFunction - This function inlines the called function into the basic
// block of the caller.  This returns false if it is not possible to inline this
// call.  The program is still in a well defined state if this occurs though.
//
// Note that this only does one level of inlining.  For example, if the
// instruction 'call B' is inlined, and 'B' calls 'C', then the call to 'C' now
// exists in the instruction stream.  Similiarly this will inline a recursive
// function by one level.
//
bool llvm::InlineFunction(CallSite CS) {
  Instruction *TheCall = CS.getInstruction();
  assert(TheCall->getParent() && TheCall->getParent()->getParent() &&
         "Instruction not in function!");

  const Function *CalledFunc = CS.getCalledFunction();
  if (CalledFunc == 0 ||          // Can't inline external function or indirect
      CalledFunc->isExternal() || // call, or call to a vararg function!
      CalledFunc->getFunctionType()->isVarArg()) return false;

  BasicBlock *OrigBB = TheCall->getParent();
  Function *Caller = OrigBB->getParent();

  // Get an iterator to the last basic block in the function, which will have
  // the new function inlined after it.
  //
  Function::iterator LastBlock = &Caller->back();

  // Make sure to capture all of the return instructions from the cloned
  // function.
  std::vector<ReturnInst*> Returns;
  { // Scope to destroy ValueMap after cloning.
    // Calculate the vector of arguments to pass into the function cloner...
    std::map<const Value*, Value*> ValueMap;
    assert(std::distance(CalledFunc->abegin(), CalledFunc->aend()) ==
           std::distance(CS.arg_begin(), CS.arg_end()) &&
           "No varargs calls can be inlined!");

    CallSite::arg_iterator AI = CS.arg_begin();
    for (Function::const_aiterator I = CalledFunc->abegin(),
           E = CalledFunc->aend(); I != E; ++I, ++AI)
      ValueMap[I] = *AI;

    // Clone the entire body of the callee into the caller.
    CloneFunctionInto(Caller, CalledFunc, ValueMap, Returns, ".i");
  }

  // Remember the first block that is newly cloned over.
  Function::iterator FirstNewBlock = LastBlock; ++FirstNewBlock;

  // If there are any alloca instructions in the block that used to be the entry
  // block for the callee, move them to the entry block of the caller.  First
  // calculate which instruction they should be inserted before.  We insert the
  // instructions at the end of the current alloca list.
  //
  if (isa<AllocaInst>(FirstNewBlock->begin())) {
    BasicBlock::iterator InsertPoint = Caller->begin()->begin();
    while (isa<AllocaInst>(InsertPoint)) ++InsertPoint;

    for (BasicBlock::iterator I = FirstNewBlock->begin(),
           E = FirstNewBlock->end(); I != E; )
      if (AllocaInst *AI = dyn_cast<AllocaInst>(I++))
        if (isa<Constant>(AI->getArraySize())) {
          FirstNewBlock->getInstList().remove(AI);
          Caller->front().getInstList().insert(InsertPoint, AI);
        }
  }

  // If we are inlining for an invoke instruction, we must make sure to rewrite
  // any inlined 'unwind' instructions into branches to the invoke exception
  // destination, and call instructions into invoke instructions.
  if (InvokeInst *II = dyn_cast<InvokeInst>(TheCall)) {
    BasicBlock *InvokeDest = II->getExceptionalDest();
    std::vector<Value*> InvokeDestPHIValues;

    // If there are PHI nodes in the exceptional destination block, we need to
    // keep track of which values came into them from this invoke, then remove
    // the entry for this block.
    for (BasicBlock::iterator I = InvokeDest->begin();
         PHINode *PN = dyn_cast<PHINode>(I); ++I)
      // Save the value to use for this edge...
      InvokeDestPHIValues.push_back(PN->getIncomingValueForBlock(OrigBB));

    for (Function::iterator BB = FirstNewBlock, E = Caller->end();
         BB != E; ++BB) {
      for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) {
        // We only need to check for function calls: inlined invoke instructions
        // require no special handling...
        if (CallInst *CI = dyn_cast<CallInst>(I)) {
          // Convert this function call into an invoke instruction...

          // First, split the basic block...
          BasicBlock *Split = BB->splitBasicBlock(CI, CI->getName()+".noexc");

          // Next, create the new invoke instruction, inserting it at the end
          // of the old basic block.
          InvokeInst *II =
            new InvokeInst(CI->getCalledValue(), Split, InvokeDest,
                           std::vector<Value*>(CI->op_begin()+1, CI->op_end()),
                           CI->getName(), BB->getTerminator());

          // Make sure that anything using the call now uses the invoke!
          CI->replaceAllUsesWith(II);

          // Delete the unconditional branch inserted by splitBasicBlock
          BB->getInstList().pop_back();
          Split->getInstList().pop_front();  // Delete the original call

          // Update any PHI nodes in the exceptional block to indicate that
          // there is now a new entry in them.
          unsigned i = 0;
          for (BasicBlock::iterator I = InvokeDest->begin();
               PHINode *PN = dyn_cast<PHINode>(I); ++I, ++i)
            PN->addIncoming(InvokeDestPHIValues[i], BB);

          // This basic block is now complete, start scanning the next one.
          break;
        } else {
          ++I;
        }
      }

      if (UnwindInst *UI = dyn_cast<UnwindInst>(BB->getTerminator())) {
        // An UnwindInst requires special handling when it gets inlined into an
        // invoke site.  Once this happens, we know that the unwind would cause
        // a control transfer to the invoke exception destination, so we can
        // transform it into a direct branch to the exception destination.
        new BranchInst(InvokeDest, UI);

        // Delete the unwind instruction!
        UI->getParent()->getInstList().pop_back();

        // Update any PHI nodes in the exceptional block to indicate that
        // there is now a new entry in them.
        unsigned i = 0;
        for (BasicBlock::iterator I = InvokeDest->begin();
             PHINode *PN = dyn_cast<PHINode>(I); ++I, ++i)
          PN->addIncoming(InvokeDestPHIValues[i], BB);
      }
    }

    // Now that everything is happy, we have one final detail.  The PHI nodes in
    // the exception destination block still have entries due to the original
    // invoke instruction.  Eliminate these entries (which might even delete the
    // PHI node) now.
    InvokeDest->removePredecessor(II->getParent());
  }

  // We want to clone the entire callee function into the hole between the
  // "starter" and "ender" blocks.  How we accomplish this depends on whether
  // this is an invoke instruction or a call instruction.
  BasicBlock *AfterCallBB;
  if (InvokeInst *II = dyn_cast<InvokeInst>(TheCall)) {

    // Add an unconditional branch to make this look like the CallInst case...
    BranchInst *NewBr = new BranchInst(II->getNormalDest(), TheCall);

    // Split the basic block.  This guarantees that no PHI nodes will have to be
    // updated due to new incoming edges, and make the invoke case more
    // symmetric to the call case.
    AfterCallBB = OrigBB->splitBasicBlock(NewBr,
                                          CalledFunc->getName()+".entry");

    // Remove (unlink) the InvokeInst from the function...
    OrigBB->getInstList().remove(TheCall);

  } else {  // It's a call
    // If this is a call instruction, we need to split the basic block that the
    // call lives in.
    //
    AfterCallBB = OrigBB->splitBasicBlock(TheCall,
                                          CalledFunc->getName()+".entry");
    // Remove (unlink) the CallInst from the function...
    AfterCallBB->getInstList().remove(TheCall);
  }

  // Handle all of the return instructions that we just cloned in, and eliminate
  // any users of the original call/invoke instruction.
  if (Returns.size() > 1) {
    // The PHI node should go at the front of the new basic block to merge all
    // possible incoming values.
    //
    PHINode *PHI = 0;
    if (!TheCall->use_empty()) {
      PHI = new PHINode(CalledFunc->getReturnType(),
                        TheCall->getName(), AfterCallBB->begin());

      // Anything that used the result of the function call should now use the
      // PHI node as their operand.
      //
      TheCall->replaceAllUsesWith(PHI);
    }

    // Loop over all of the return instructions, turning them into unconditional
    // branches to the merge point now, and adding entries to the PHI node as
    // appropriate.
    for (unsigned i = 0, e = Returns.size(); i != e; ++i) {
      ReturnInst *RI = Returns[i];

      if (PHI) {
        assert(RI->getReturnValue() && "Ret should have value!");
        assert(RI->getReturnValue()->getType() == PHI->getType() &&
               "Ret value not consistent in function!");
        PHI->addIncoming(RI->getReturnValue(), RI->getParent());
      }

      // Add a branch to the merge point where the PHI node lives if it exists.
      new BranchInst(AfterCallBB, RI);

      // Delete the return instruction now
      RI->getParent()->getInstList().erase(RI);
    }

  } else if (!Returns.empty()) {
    // Otherwise, if there is exactly one return value, just replace anything
    // using the return value of the call with the computed value.
    if (!TheCall->use_empty())
      TheCall->replaceAllUsesWith(Returns[0]->getReturnValue());

    // Add a branch to the merge point where the PHI node lives if it exists.
    new BranchInst(AfterCallBB, Returns[0]);

    // Delete the return instruction now
    Returns[0]->getParent()->getInstList().erase(Returns[0]);
  }

  // Since we are now done with the Call/Invoke, we can delete it.
  delete TheCall;

  // Change the branch that used to go to AfterCallBB to branch to the first
  // basic block of the inlined function.
  //
  TerminatorInst *Br = OrigBB->getTerminator();
  assert(Br && Br->getOpcode() == Instruction::Br &&
	 "splitBasicBlock broken!");
  Br->setOperand(0, FirstNewBlock);

  // Now that the function is correct, make it a little bit nicer.  In
  // particular, move the basic blocks inserted from the end of the function
  // into the space made by splitting the source basic block.
  //
  Caller->getBasicBlockList().splice(AfterCallBB, Caller->getBasicBlockList(),
                                     FirstNewBlock, Caller->end());

  // We should always be able to fold the entry block of the function into the
  // single predecessor of the block...
  assert(cast<BranchInst>(Br)->isUnconditional() && "splitBasicBlock broken!");
  BasicBlock *CalleeEntry = cast<BranchInst>(Br)->getSuccessor(0);
  SimplifyCFG(CalleeEntry);

  // Okay, continue the CFG cleanup.  It's often the case that there is only a
  // single return instruction in the callee function.  If this is the case,
  // then we have an unconditional branch from the return block to the
  // 'AfterCallBB'.  Check for this case, and eliminate the branch is possible.
  SimplifyCFG(AfterCallBB);
  return true;
}
<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2008 Renato Araujo Oliveira Filho <renatox@gmail.com>
Copyright (c) 2000-2014 Torus Knot Software Ltd

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 "OgreException.h"
#include "OgreLogManager.h"
#include "OgreStringConverter.h"
#include "OgreRoot.h"

#include "OgreRenderSystem.h"

#include "OgreEGLSupport.h"
#include "OgreEGLWindow.h"
#if OGRE_PLATFORM != OGRE_PLATFORM_EMSCRIPTEN
#include "OgreEGLRenderTexture.h"
#endif

#ifndef EGL_VERSION_1_5
#define EGL_CONTEXT_MAJOR_VERSION EGL_CONTEXT_CLIENT_VERSION
#define EGL_CONTEXT_MINOR_VERSION EGL_NONE
#endif

#include <EGL/eglext.h>

namespace Ogre {

    EGLSupport::EGLSupport(int profile)
        : GLNativeSupport(profile), mGLDisplay(0),
          mNativeDisplay(EGL_DEFAULT_DISPLAY), hasEGL15(false)
    {
    }

    EGLDisplay EGLSupport::getGLDisplay(void)
    {
#if defined(EGL_VERSION_1_5) && OGRE_PLATFORM != OGRE_PLATFORM_ANDROID
        static auto eglQueryDevicesEXT = (PFNEGLQUERYDEVICESEXTPROC)eglGetProcAddress("eglQueryDevicesEXT");
        static auto eglQueryDeviceStringEXT =
            (PFNEGLQUERYDEVICESTRINGEXTPROC)eglGetProcAddress("eglQueryDeviceStringEXT");

        if(eglQueryDevicesEXT && mNativeDisplay == EGL_DEFAULT_DISPLAY)
        {
            int numDevices;
            eglQueryDevicesEXT(0, NULL, &numDevices);
            EGL_CHECK_ERROR
            std::vector<EGLDeviceEXT> devices(numDevices);
            eglQueryDevicesEXT(numDevices, devices.data(), &numDevices);

            EGLAttrib attribs[] = {EGL_NONE};
            for(auto dev : devices)
            {
                EGLDisplay display = eglGetPlatformDisplay(EGL_PLATFORM_DEVICE_EXT, dev, attribs);
                EGL_CHECK_ERROR

                if(display != EGL_NO_DISPLAY && !mGLDisplay)
                {
                    mGLDisplay = display;
                    const char* exts = eglQueryDeviceStringEXT(dev, EGL_EXTENSIONS);
                    LogManager::getSingleton().stream() << "EGL: using default display. Device extensions: " << exts;
                    break;
                }
            }
        }
        else
#endif
        {
            mGLDisplay = eglGetDisplay(mNativeDisplay);
            EGL_CHECK_ERROR
        }

        if(mGLDisplay == EGL_NO_DISPLAY)
        {
            OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Couldn`t get EGLDisplay");
        }

        if (eglInitialize(mGLDisplay, &mEGLMajor, &mEGLMinor) == EGL_FALSE)
        {
            OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
                        "Couldn`t initialize EGLDisplay ",
                        "EGLSupport::getGLDisplay");
        }
        EGL_CHECK_ERROR

        return mGLDisplay;
    }

    EGLConfig* EGLSupport::chooseGLConfig(const EGLint *attribList, EGLint *nElements)
    {
        EGLConfig *configs;

        if (eglChooseConfig(mGLDisplay, attribList, NULL, 0, nElements) == EGL_FALSE)
        {
            OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to choose config");

            *nElements = 0;
            return 0;
        }
        EGL_CHECK_ERROR
        configs = (EGLConfig*) malloc(*nElements * sizeof(EGLConfig));
        if (eglChooseConfig(mGLDisplay, attribList, configs, *nElements, nElements) == EGL_FALSE)
        {
            OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to choose config");

            *nElements = 0;
            free(configs);
            return 0;
        }
        EGL_CHECK_ERROR
        return configs;
    }

    EGLConfig* EGLSupport::getConfigs(EGLint *nElements)
    {
        EGLConfig *configs;

        if (eglGetConfigs(mGLDisplay, NULL, 0, nElements) == EGL_FALSE)
        {
            OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to choose config");

            *nElements = 0;
            return 0;
        }
        EGL_CHECK_ERROR
        configs = (EGLConfig*) malloc(*nElements * sizeof(EGLConfig));
        if (eglGetConfigs(mGLDisplay, configs, *nElements, nElements) == EGL_FALSE)
        {
            OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to choose config");

            *nElements = 0;
            free(configs);
            return 0;
        }
        EGL_CHECK_ERROR
        return configs;
    }

    EGLBoolean EGLSupport::getGLConfigAttrib(EGLConfig glConfig, EGLint attribute, EGLint *value)
    {
        EGLBoolean status;

        status = eglGetConfigAttrib(mGLDisplay, glConfig, attribute, value);
        EGL_CHECK_ERROR
        return status;
    }

    void* EGLSupport::getProcAddress(const char* name) const
    {
        return (void*)eglGetProcAddress(name);
    }

    ::EGLConfig EGLSupport::getGLConfigFromContext(::EGLContext context)
    {
        ::EGLConfig glConfig;
        EGLint id = 0;
        ::EGLConfig *configs;
        EGLint numConfigs;

        if (eglQueryContext(mGLDisplay, context, EGL_CONFIG_ID, &id) == EGL_FALSE)
        {
            OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Fail to get config from context");
            return 0;
        }
        EGL_CHECK_ERROR
        configs = getConfigs(&numConfigs);
        glConfig = configs[id];
        free(configs);
        return glConfig;
    }

    ::EGLConfig EGLSupport::getGLConfigFromDrawable(::EGLSurface drawable,
                                                    unsigned int *w, unsigned int *h)
    {
        ::EGLConfig glConfig;
        EGLint id = 0;
        ::EGLConfig *configs;
        EGLint numConfigs;

        if (eglQuerySurface(mGLDisplay, drawable, EGL_CONFIG_ID, &id) == EGL_FALSE)
        {
            OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Fail to get config from drawable");
            return 0;
        }
        EGL_CHECK_ERROR
        eglQuerySurface(mGLDisplay, drawable, EGL_WIDTH, (EGLint *) w);
        EGL_CHECK_ERROR
        eglQuerySurface(mGLDisplay, drawable, EGL_HEIGHT, (EGLint *) h);
        EGL_CHECK_ERROR
        configs = getConfigs(&numConfigs);
        glConfig = configs[id];
        free(configs);
        return glConfig;
    }

    //------------------------------------------------------------------------
    // A helper class for the implementation of selectFBConfig
    //------------------------------------------------------------------------
    class GLConfigAttribs
    {
        public:
            GLConfigAttribs(const int* attribs)
            {
                fields[EGL_CONFIG_CAVEAT] = EGL_NONE;

                for (int i = 0; attribs[2*i] != EGL_NONE; i++)
                {
                    fields[attribs[2*i]] = attribs[2*i+1];
                }
            }

            void load(EGLSupport* const glSupport, EGLConfig glConfig)
            {
                std::map<int,int>::iterator it;

                for (it = fields.begin(); it != fields.end(); it++)
                {
                    it->second = EGL_NONE;

                    glSupport->getGLConfigAttrib(glConfig, it->first, &it->second);
                }
            }

            bool operator>(GLConfigAttribs& alternative)
            {
                // Caveats are best avoided, but might be needed for anti-aliasing
                if (fields[EGL_CONFIG_CAVEAT] != alternative.fields[EGL_CONFIG_CAVEAT])
                {
                    if (fields[EGL_CONFIG_CAVEAT] == EGL_SLOW_CONFIG)
                    {
                        return false;
                    }

                    if (fields.find(EGL_SAMPLES) != fields.end() &&
                        fields[EGL_SAMPLES] < alternative.fields[EGL_SAMPLES])
                    {
                        return false;
                    }
                }

                std::map<int,int>::iterator it;

                for (it = fields.begin(); it != fields.end(); it++)
                {
                    if (it->first != EGL_CONFIG_CAVEAT &&
                        fields[it->first] > alternative.fields[it->first])
                    {
                        return true;
                    }
                }

                return false;
            }

            std::map<int,int> fields;
    };

    ::EGLConfig EGLSupport::selectGLConfig(const int* minAttribs, const int *maxAttribs)
    {
        EGLConfig *glConfigs;
        EGLConfig glConfig = 0;
        int config, nConfigs = 0;

        glConfigs = chooseGLConfig(minAttribs, &nConfigs);

        if (!nConfigs)
        {
            glConfigs = getConfigs(&nConfigs);
        }

        if (!nConfigs)
        {
            return 0;
        }

        glConfig = glConfigs[0];

        if (maxAttribs)
        {
            GLConfigAttribs maximum(maxAttribs);
            GLConfigAttribs best(maxAttribs);
            GLConfigAttribs candidate(maxAttribs);

            best.load(this, glConfig);

            for (config = 1; config < nConfigs; config++)
            {
                candidate.load(this, glConfigs[config]);

                if (candidate > maximum)
                {
                    continue;
                }

                if (candidate > best)
                {
                    glConfig = glConfigs[config];

                    best.load(this, glConfig);
                }
            }
        }

        free(glConfigs);
        return glConfig;
    }

    void EGLSupport::switchMode(void)
    {
        return switchMode(mOriginalMode.width,
                          mOriginalMode.height, mOriginalMode.refreshRate);
    }

    ::EGLContext EGLSupport::createNewContext(EGLDisplay eglDisplay,
                          ::EGLConfig glconfig,
                                              ::EGLContext shareList) const
    {
        EGLint contextAttrs[] = {
            EGL_CONTEXT_MAJOR_VERSION, 3,
            EGL_CONTEXT_MINOR_VERSION, 2,
            EGL_NONE, EGL_NONE,
            EGL_NONE
        };

        if (!eglBindAPI(mContextProfile == CONTEXT_ES ? EGL_OPENGL_ES_API : EGL_OPENGL_API))
        {
            OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "eglBindAPI failed");
        }

        if(mContextProfile != CONTEXT_ES) {
            contextAttrs[1] = 4;
            contextAttrs[3] = 6;

#ifdef EGL_VERSION_1_5
            contextAttrs[4] = EGL_CONTEXT_OPENGL_PROFILE_MASK;
            contextAttrs[5] = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT;
            if(mContextProfile == CONTEXT_COMPATIBILITY)
            {
                contextAttrs[1] = 3; // MESA 20.2.6 always gives us core if we request 4.x
                contextAttrs[3] = 0;
                contextAttrs[5] = EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT;
            }
#endif
        }

        if(!hasEGL15)
        {
            contextAttrs[2] = EGL_NONE; // skips following attributes
            contextAttrs[3] = 0;
        }

        ::EGLContext context = (::EGLContext)0;

        // find maximal supported context version
        while(!context && (contextAttrs[1] >= 1))
        {
            context = eglCreateContext(eglDisplay, glconfig, shareList, contextAttrs);
            EGL_CHECK_ERROR
            contextAttrs[1] -= contextAttrs[3] == 0; // only decrement if minor == 0

            if(hasEGL15)
                contextAttrs[3] = (contextAttrs[3] - 1 + 7) % 7; // decrement: -1 -> 6
        }

        if (!context)
        {
            OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to create EGL context");
            return 0;
        }

        return context;
    }

    void EGLSupport::start()
    {
        LogManager::getSingleton().logMessage(
            "******************************\n"
            "*** Starting EGL Subsystem ***\n"
            "******************************");
        initialiseExtensions();
    }

    void EGLSupport::stop()
    {
        eglTerminate(mGLDisplay);
        EGL_CHECK_ERROR
    }

    void EGLSupport::initialiseExtensions() {
        assert (mGLDisplay);

        const char* propStr = eglQueryString(mGLDisplay, EGL_VENDOR);
        LogManager::getSingleton().stream() << "EGL_VENDOR = " << propStr;

        propStr = eglQueryString(mGLDisplay, EGL_VERSION);
        LogManager::getSingleton().stream() << "EGL_VERSION = " << propStr;

        hasEGL15 = String(propStr).find("1.5") != String::npos;

        StringStream ext;

        // client extensions
        propStr = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
        if(propStr) // NULL = failure case
            ext << propStr << " ";

        // display extension
        propStr = eglQueryString(mGLDisplay, EGL_EXTENSIONS);
        ext << propStr;

        LogManager::getSingleton().stream() << "EGL_EXTENSIONS = " << ext.str();

        String instr;
        while(ext >> instr)
        {
            extensionList.insert(instr);
        }
    }

    void EGLSupport::setGLDisplay( EGLDisplay val )
    {
        mGLDisplay = val;
    }

    GLPBuffer* EGLSupport::createPBuffer( PixelComponentType format, size_t width, size_t height )
    {
#if OGRE_PLATFORM == OGRE_PLATFORM_EMSCRIPTEN
        return nullptr;
#else
        return new EGLPBuffer(this, format, width, height);
#endif
    }
}
<commit_msg>GLSupport: fix compilation on emscripten<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2008 Renato Araujo Oliveira Filho <renatox@gmail.com>
Copyright (c) 2000-2014 Torus Knot Software Ltd

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 "OgreException.h"
#include "OgreLogManager.h"
#include "OgreStringConverter.h"
#include "OgreRoot.h"

#include "OgreRenderSystem.h"

#include "OgreEGLSupport.h"
#include "OgreEGLWindow.h"
#if OGRE_PLATFORM != OGRE_PLATFORM_EMSCRIPTEN
#include "OgreEGLRenderTexture.h"
#endif

#ifndef EGL_VERSION_1_5
#define EGL_CONTEXT_MAJOR_VERSION EGL_CONTEXT_CLIENT_VERSION
#define EGL_CONTEXT_MINOR_VERSION EGL_NONE
#endif

#include <EGL/eglext.h>

namespace Ogre {

    EGLSupport::EGLSupport(int profile)
        : GLNativeSupport(profile), mGLDisplay(0),
          mNativeDisplay(EGL_DEFAULT_DISPLAY), hasEGL15(false)
    {
    }

    EGLDisplay EGLSupport::getGLDisplay(void)
    {
#if defined(EGL_VERSION_1_5) && OGRE_PLATFORM != OGRE_PLATFORM_ANDROID && OGRE_PLATFORM != OGRE_PLATFORM_EMSCRIPTEN
        static auto eglQueryDevicesEXT = (PFNEGLQUERYDEVICESEXTPROC)eglGetProcAddress("eglQueryDevicesEXT");
        static auto eglQueryDeviceStringEXT =
            (PFNEGLQUERYDEVICESTRINGEXTPROC)eglGetProcAddress("eglQueryDeviceStringEXT");

        if(eglQueryDevicesEXT && mNativeDisplay == EGL_DEFAULT_DISPLAY)
        {
            int numDevices;
            eglQueryDevicesEXT(0, NULL, &numDevices);
            EGL_CHECK_ERROR
            std::vector<EGLDeviceEXT> devices(numDevices);
            eglQueryDevicesEXT(numDevices, devices.data(), &numDevices);

            EGLAttrib attribs[] = {EGL_NONE};
            for(auto dev : devices)
            {
                EGLDisplay display = eglGetPlatformDisplay(EGL_PLATFORM_DEVICE_EXT, dev, attribs);
                EGL_CHECK_ERROR

                if(display != EGL_NO_DISPLAY && !mGLDisplay)
                {
                    mGLDisplay = display;
                    const char* exts = eglQueryDeviceStringEXT(dev, EGL_EXTENSIONS);
                    LogManager::getSingleton().stream() << "EGL: using default display. Device extensions: " << exts;
                    break;
                }
            }
        }
        else
#endif
        {
            mGLDisplay = eglGetDisplay(mNativeDisplay);
            EGL_CHECK_ERROR
        }

        if(mGLDisplay == EGL_NO_DISPLAY)
        {
            OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Couldn`t get EGLDisplay");
        }

        if (eglInitialize(mGLDisplay, &mEGLMajor, &mEGLMinor) == EGL_FALSE)
        {
            OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
                        "Couldn`t initialize EGLDisplay ",
                        "EGLSupport::getGLDisplay");
        }
        EGL_CHECK_ERROR

        return mGLDisplay;
    }

    EGLConfig* EGLSupport::chooseGLConfig(const EGLint *attribList, EGLint *nElements)
    {
        EGLConfig *configs;

        if (eglChooseConfig(mGLDisplay, attribList, NULL, 0, nElements) == EGL_FALSE)
        {
            OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to choose config");

            *nElements = 0;
            return 0;
        }
        EGL_CHECK_ERROR
        configs = (EGLConfig*) malloc(*nElements * sizeof(EGLConfig));
        if (eglChooseConfig(mGLDisplay, attribList, configs, *nElements, nElements) == EGL_FALSE)
        {
            OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to choose config");

            *nElements = 0;
            free(configs);
            return 0;
        }
        EGL_CHECK_ERROR
        return configs;
    }

    EGLConfig* EGLSupport::getConfigs(EGLint *nElements)
    {
        EGLConfig *configs;

        if (eglGetConfigs(mGLDisplay, NULL, 0, nElements) == EGL_FALSE)
        {
            OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to choose config");

            *nElements = 0;
            return 0;
        }
        EGL_CHECK_ERROR
        configs = (EGLConfig*) malloc(*nElements * sizeof(EGLConfig));
        if (eglGetConfigs(mGLDisplay, configs, *nElements, nElements) == EGL_FALSE)
        {
            OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to choose config");

            *nElements = 0;
            free(configs);
            return 0;
        }
        EGL_CHECK_ERROR
        return configs;
    }

    EGLBoolean EGLSupport::getGLConfigAttrib(EGLConfig glConfig, EGLint attribute, EGLint *value)
    {
        EGLBoolean status;

        status = eglGetConfigAttrib(mGLDisplay, glConfig, attribute, value);
        EGL_CHECK_ERROR
        return status;
    }

    void* EGLSupport::getProcAddress(const char* name) const
    {
        return (void*)eglGetProcAddress(name);
    }

    ::EGLConfig EGLSupport::getGLConfigFromContext(::EGLContext context)
    {
        ::EGLConfig glConfig;
        EGLint id = 0;
        ::EGLConfig *configs;
        EGLint numConfigs;

        if (eglQueryContext(mGLDisplay, context, EGL_CONFIG_ID, &id) == EGL_FALSE)
        {
            OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Fail to get config from context");
            return 0;
        }
        EGL_CHECK_ERROR
        configs = getConfigs(&numConfigs);
        glConfig = configs[id];
        free(configs);
        return glConfig;
    }

    ::EGLConfig EGLSupport::getGLConfigFromDrawable(::EGLSurface drawable,
                                                    unsigned int *w, unsigned int *h)
    {
        ::EGLConfig glConfig;
        EGLint id = 0;
        ::EGLConfig *configs;
        EGLint numConfigs;

        if (eglQuerySurface(mGLDisplay, drawable, EGL_CONFIG_ID, &id) == EGL_FALSE)
        {
            OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Fail to get config from drawable");
            return 0;
        }
        EGL_CHECK_ERROR
        eglQuerySurface(mGLDisplay, drawable, EGL_WIDTH, (EGLint *) w);
        EGL_CHECK_ERROR
        eglQuerySurface(mGLDisplay, drawable, EGL_HEIGHT, (EGLint *) h);
        EGL_CHECK_ERROR
        configs = getConfigs(&numConfigs);
        glConfig = configs[id];
        free(configs);
        return glConfig;
    }

    //------------------------------------------------------------------------
    // A helper class for the implementation of selectFBConfig
    //------------------------------------------------------------------------
    class GLConfigAttribs
    {
        public:
            GLConfigAttribs(const int* attribs)
            {
                fields[EGL_CONFIG_CAVEAT] = EGL_NONE;

                for (int i = 0; attribs[2*i] != EGL_NONE; i++)
                {
                    fields[attribs[2*i]] = attribs[2*i+1];
                }
            }

            void load(EGLSupport* const glSupport, EGLConfig glConfig)
            {
                std::map<int,int>::iterator it;

                for (it = fields.begin(); it != fields.end(); it++)
                {
                    it->second = EGL_NONE;

                    glSupport->getGLConfigAttrib(glConfig, it->first, &it->second);
                }
            }

            bool operator>(GLConfigAttribs& alternative)
            {
                // Caveats are best avoided, but might be needed for anti-aliasing
                if (fields[EGL_CONFIG_CAVEAT] != alternative.fields[EGL_CONFIG_CAVEAT])
                {
                    if (fields[EGL_CONFIG_CAVEAT] == EGL_SLOW_CONFIG)
                    {
                        return false;
                    }

                    if (fields.find(EGL_SAMPLES) != fields.end() &&
                        fields[EGL_SAMPLES] < alternative.fields[EGL_SAMPLES])
                    {
                        return false;
                    }
                }

                std::map<int,int>::iterator it;

                for (it = fields.begin(); it != fields.end(); it++)
                {
                    if (it->first != EGL_CONFIG_CAVEAT &&
                        fields[it->first] > alternative.fields[it->first])
                    {
                        return true;
                    }
                }

                return false;
            }

            std::map<int,int> fields;
    };

    ::EGLConfig EGLSupport::selectGLConfig(const int* minAttribs, const int *maxAttribs)
    {
        EGLConfig *glConfigs;
        EGLConfig glConfig = 0;
        int config, nConfigs = 0;

        glConfigs = chooseGLConfig(minAttribs, &nConfigs);

        if (!nConfigs)
        {
            glConfigs = getConfigs(&nConfigs);
        }

        if (!nConfigs)
        {
            return 0;
        }

        glConfig = glConfigs[0];

        if (maxAttribs)
        {
            GLConfigAttribs maximum(maxAttribs);
            GLConfigAttribs best(maxAttribs);
            GLConfigAttribs candidate(maxAttribs);

            best.load(this, glConfig);

            for (config = 1; config < nConfigs; config++)
            {
                candidate.load(this, glConfigs[config]);

                if (candidate > maximum)
                {
                    continue;
                }

                if (candidate > best)
                {
                    glConfig = glConfigs[config];

                    best.load(this, glConfig);
                }
            }
        }

        free(glConfigs);
        return glConfig;
    }

    void EGLSupport::switchMode(void)
    {
        return switchMode(mOriginalMode.width,
                          mOriginalMode.height, mOriginalMode.refreshRate);
    }

    ::EGLContext EGLSupport::createNewContext(EGLDisplay eglDisplay,
                          ::EGLConfig glconfig,
                                              ::EGLContext shareList) const
    {
        EGLint contextAttrs[] = {
            EGL_CONTEXT_MAJOR_VERSION, 3,
            EGL_CONTEXT_MINOR_VERSION, 2,
            EGL_NONE, EGL_NONE,
            EGL_NONE
        };

        if (!eglBindAPI(mContextProfile == CONTEXT_ES ? EGL_OPENGL_ES_API : EGL_OPENGL_API))
        {
            OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "eglBindAPI failed");
        }

        if(mContextProfile != CONTEXT_ES) {
            contextAttrs[1] = 4;
            contextAttrs[3] = 6;

#ifdef EGL_VERSION_1_5
            contextAttrs[4] = EGL_CONTEXT_OPENGL_PROFILE_MASK;
            contextAttrs[5] = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT;
            if(mContextProfile == CONTEXT_COMPATIBILITY)
            {
                contextAttrs[1] = 3; // MESA 20.2.6 always gives us core if we request 4.x
                contextAttrs[3] = 0;
                contextAttrs[5] = EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT;
            }
#endif
        }

        if(!hasEGL15)
        {
            contextAttrs[2] = EGL_NONE; // skips following attributes
            contextAttrs[3] = 0;
        }

        ::EGLContext context = (::EGLContext)0;

        // find maximal supported context version
        while(!context && (contextAttrs[1] >= 1))
        {
            context = eglCreateContext(eglDisplay, glconfig, shareList, contextAttrs);
            EGL_CHECK_ERROR
            contextAttrs[1] -= contextAttrs[3] == 0; // only decrement if minor == 0

            if(hasEGL15)
                contextAttrs[3] = (contextAttrs[3] - 1 + 7) % 7; // decrement: -1 -> 6
        }

        if (!context)
        {
            OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to create EGL context");
            return 0;
        }

        return context;
    }

    void EGLSupport::start()
    {
        LogManager::getSingleton().logMessage(
            "******************************\n"
            "*** Starting EGL Subsystem ***\n"
            "******************************");
        initialiseExtensions();
    }

    void EGLSupport::stop()
    {
        eglTerminate(mGLDisplay);
        EGL_CHECK_ERROR
    }

    void EGLSupport::initialiseExtensions() {
        assert (mGLDisplay);

        const char* propStr = eglQueryString(mGLDisplay, EGL_VENDOR);
        LogManager::getSingleton().stream() << "EGL_VENDOR = " << propStr;

        propStr = eglQueryString(mGLDisplay, EGL_VERSION);
        LogManager::getSingleton().stream() << "EGL_VERSION = " << propStr;

        hasEGL15 = String(propStr).find("1.5") != String::npos;

        StringStream ext;

        // client extensions
        propStr = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
        if(propStr) // NULL = failure case
            ext << propStr << " ";

        // display extension
        propStr = eglQueryString(mGLDisplay, EGL_EXTENSIONS);
        ext << propStr;

        LogManager::getSingleton().stream() << "EGL_EXTENSIONS = " << ext.str();

        String instr;
        while(ext >> instr)
        {
            extensionList.insert(instr);
        }
    }

    void EGLSupport::setGLDisplay( EGLDisplay val )
    {
        mGLDisplay = val;
    }

    GLPBuffer* EGLSupport::createPBuffer( PixelComponentType format, size_t width, size_t height )
    {
#if OGRE_PLATFORM == OGRE_PLATFORM_EMSCRIPTEN
        return nullptr;
#else
        return new EGLPBuffer(this, format, width, height);
#endif
    }
}
<|endoftext|>


<commit_before>/* Copyright 2020 Sergei Bastrakov
 *
 * This file is part of alpaka.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#pragma once

#if defined(ALPAKA_ACC_GPU_CUDA_ENABLED) || defined(ALPAKA_ACC_GPU_HIP_ENABLED)

#include <alpaka/core/BoostPredef.hpp>

#if defined(ALPAKA_ACC_GPU_CUDA_ENABLED) && !BOOST_LANG_CUDA
    #error If ALPAKA_ACC_GPU_CUDA_ENABLED is set, the compiler has to support CUDA!
#endif

#if defined(ALPAKA_ACC_GPU_HIP_ENABLED) && !BOOST_LANG_HIP
    #error If ALPAKA_ACC_GPU_HIP_ENABLED is set, the compiler has to support HIP!
#endif

#include <alpaka/intrinsic/Traits.hpp>

namespace alpaka
{
    namespace intrinsic
    {
        //#############################################################################
        //! The GPU CUDA/HIP intrinsic.
        class IntrinsicUniformCudaHipBuiltIn : public concepts::Implements<ConceptIntrinsic, IntrinsicUniformCudaHipBuiltIn>
        {
        public:
            //-----------------------------------------------------------------------------
            IntrinsicUniformCudaHipBuiltIn() = default;
            //-----------------------------------------------------------------------------
            __device__ IntrinsicUniformCudaHipBuiltIn(IntrinsicUniformCudaHipBuiltIn const &) = delete;
            //-----------------------------------------------------------------------------
            __device__ IntrinsicUniformCudaHipBuiltIn(IntrinsicUniformCudaHipBuiltIn &&) = delete;
            //-----------------------------------------------------------------------------
            __device__ auto operator=(IntrinsicUniformCudaHipBuiltIn const &) -> IntrinsicUniformCudaHipBuiltIn & = delete;
            //-----------------------------------------------------------------------------
            __device__ auto operator=(IntrinsicUniformCudaHipBuiltIn &&) -> IntrinsicUniformCudaHipBuiltIn & = delete;
            //-----------------------------------------------------------------------------
            ~IntrinsicUniformCudaHipBuiltIn() = default;
        };

        namespace traits
        {
            //#############################################################################
            template<>
            struct Popcount<
                IntrinsicUniformCudaHipBuiltIn>
            {
                //-----------------------------------------------------------------------------
                __device__ static auto popcount(
                    intrinsic::IntrinsicUniformCudaHipBuiltIn const & /*intrinsic*/,
                    unsigned int value)
                -> int
                {
#if BOOST_COMP_CLANG
                    return __popc(static_cast<int>(value));
#else
                    return __popc(value);
#endif
                }

                //-----------------------------------------------------------------------------
                __device__ static auto popcount(
                    intrinsic::IntrinsicUniformCudaHipBuiltIn const & /*intrinsic*/,
                    unsigned long long value)
                -> int
                {
#if BOOST_COMP_CLANG
                    return __popcll(static_cast<long long>(value));
#else
                    return __popcll(value);
#endif
                }
            };

            //#############################################################################
            template<>
            struct Ffs<
                IntrinsicUniformCudaHipBuiltIn>
            {
                //-----------------------------------------------------------------------------
                __device__ static auto ffs(
                    intrinsic::IntrinsicUniformCudaHipBuiltIn const & /*intrinsic*/,
                    std::int32_t value)
                -> std::int32_t
                {
                    return __ffs(value);
                }

                //-----------------------------------------------------------------------------
                __device__ static auto ffs(
                    intrinsic::IntrinsicUniformCudaHipBuiltIn const & /*intrinsic*/,
                    std::int64_t value)
                -> std::int32_t
                {
                    return __ffsll(value);
                }
            };
        }
    }
}

#endif
<commit_msg>fix intrinsic `ffs` for HIP (#1049)<commit_after>/* Copyright 2020 Sergei Bastrakov
 *
 * This file is part of alpaka.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#pragma once

#if defined(ALPAKA_ACC_GPU_CUDA_ENABLED) || defined(ALPAKA_ACC_GPU_HIP_ENABLED)

#include <alpaka/core/BoostPredef.hpp>

#if defined(ALPAKA_ACC_GPU_CUDA_ENABLED) && !BOOST_LANG_CUDA
    #error If ALPAKA_ACC_GPU_CUDA_ENABLED is set, the compiler has to support CUDA!
#endif

#if defined(ALPAKA_ACC_GPU_HIP_ENABLED) && !BOOST_LANG_HIP
    #error If ALPAKA_ACC_GPU_HIP_ENABLED is set, the compiler has to support HIP!
#endif

#include <alpaka/intrinsic/Traits.hpp>

namespace alpaka
{
    namespace intrinsic
    {
        //#############################################################################
        //! The GPU CUDA/HIP intrinsic.
        class IntrinsicUniformCudaHipBuiltIn : public concepts::Implements<ConceptIntrinsic, IntrinsicUniformCudaHipBuiltIn>
        {
        public:
            //-----------------------------------------------------------------------------
            IntrinsicUniformCudaHipBuiltIn() = default;
            //-----------------------------------------------------------------------------
            __device__ IntrinsicUniformCudaHipBuiltIn(IntrinsicUniformCudaHipBuiltIn const &) = delete;
            //-----------------------------------------------------------------------------
            __device__ IntrinsicUniformCudaHipBuiltIn(IntrinsicUniformCudaHipBuiltIn &&) = delete;
            //-----------------------------------------------------------------------------
            __device__ auto operator=(IntrinsicUniformCudaHipBuiltIn const &) -> IntrinsicUniformCudaHipBuiltIn & = delete;
            //-----------------------------------------------------------------------------
            __device__ auto operator=(IntrinsicUniformCudaHipBuiltIn &&) -> IntrinsicUniformCudaHipBuiltIn & = delete;
            //-----------------------------------------------------------------------------
            ~IntrinsicUniformCudaHipBuiltIn() = default;
        };

        namespace traits
        {
            //#############################################################################
            template<>
            struct Popcount<
                IntrinsicUniformCudaHipBuiltIn>
            {
                //-----------------------------------------------------------------------------
                __device__ static auto popcount(
                    intrinsic::IntrinsicUniformCudaHipBuiltIn const & /*intrinsic*/,
                    unsigned int value)
                -> int
                {
#if BOOST_COMP_CLANG
                    return __popc(static_cast<int>(value));
#else
                    return __popc(value);
#endif
                }

                //-----------------------------------------------------------------------------
                __device__ static auto popcount(
                    intrinsic::IntrinsicUniformCudaHipBuiltIn const & /*intrinsic*/,
                    unsigned long long value)
                -> int
                {
#if BOOST_COMP_CLANG
                    return __popcll(static_cast<long long>(value));
#else
                    return __popcll(value);
#endif
                }
            };

            //#############################################################################
            template<>
            struct Ffs<
                IntrinsicUniformCudaHipBuiltIn>
            {
                //-----------------------------------------------------------------------------
                __device__ static auto ffs(
                    intrinsic::IntrinsicUniformCudaHipBuiltIn const & /*intrinsic*/,
                    std::int32_t value)
                -> std::int32_t
                {
                    return __ffs(static_cast<int>(value));
                }

                //-----------------------------------------------------------------------------
                __device__ static auto ffs(
                    intrinsic::IntrinsicUniformCudaHipBuiltIn const & /*intrinsic*/,
                    std::int64_t value)
                -> std::int32_t
                {
                    return __ffsll(static_cast<long long>(value));
                }
            };
        }
    }
}

#endif
<|endoftext|>


<commit_before>#ifndef GNR_SWAP_HPP
# define GNR_SWAP_HPP
# pragma once

#include <cstdint>

#include <cstring>

#include <type_traits>

#if defined(_MSC_VER)
# include <stdlib.h>
#endif // _MSC_VER

namespace gnr
{

template <class Dst, class Src>
inline Dst bit_cast(Src const& src) noexcept
{
  Dst dst;

  std::memcpy(&dst, &src, sizeof(dst));

  return dst;
}

template <class Dst, class Src>
inline Dst bit_cast(Src* const src) noexcept
{
  Dst dst;

  std::memcpy(&dst, src, sizeof(dst));

  return dst;
}

#if defined(__GNUC__)

template <typename T>
constexpr inline std::enable_if_t<
  std::is_integral<T>{} &&
  (sizeof(std::int64_t) == sizeof(T)),
  T
>
swap(T const v) noexcept
{
  return __builtin_bswap64(v);
}

template <typename T>
constexpr inline std::enable_if_t<
  std::is_integral<T>{} &&
  (sizeof(std::int32_t) == sizeof(T)),
  T
>
swap(T const v) noexcept
{
  return __builtin_bswap32(v);
}

template <typename T>
constexpr inline std::enable_if_t<
  std::is_integral<T>{} &&
  (sizeof(std::int16_t) == sizeof(T)),
  T
>
swap(T const v) noexcept
{
  return __builtin_bswap16(v);
}

template <typename T>
constexpr inline std::enable_if_t<
  std::is_integral<T>{} &&
  (sizeof(std::int8_t) == sizeof(T)),
  T
>
swap(T const v) noexcept
{
  return v;
}

#elif defined(_MSC_VER)

template <typename T>
constexpr inline std::enable_if_t<
  std::is_integral<T>{} &&
  (sizeof(__int64) == sizeof(T)),
  T
>
swap(T const v) noexcept
{
  return _byteswap_uint64(i);
}

template <typename T>
constexpr inline std::enable_if_t<
  std::is_integral<T>{} &&
  (sizeof(unsigned long) == sizeof(T)),
  T
>
swap(T const v) noexcept
{
  return _byteswap_ulong(v);
}

template <typename T>
constexpr inline std::enable_if_t<
  std::is_integral<T>{} &&
  (sizeof(unsigned short) == sizeof(T)),
  T
>
swap(T const v) noexcept
{
  return _byteswap_ushort(v)
}

template <typename T>
constexpr inline std::enable_if_t<
  std::is_integral<T>{} &&
  (sizeof(std::int8_t) == sizeof(T)),
  T
>
swap(T const v) noexcept
{
  return v;
}

#else

namespace detail
{

template<class T, std::size_t ...I>
constexpr inline T swap_impl(T v, std::index_sequence<I...> const) noexcept
{
  return (
    (
      ((v >> (I * std::numeric_limits<char>::digits)) & std::uint8_t(~0)) <<
      ((sizeof(T) - 1 - I) * std::numeric_limits<char>::digits)
    ) | ...
  );
};

}

template <typename T>
constexpr inline std::enable_if_t<
  std::is_integral<T>{},
  T
>
swap(T const v) noexcept
{
  return detail::swap_impl<T>(v, std::make_index_sequence<sizeof(T)>{});
}

#endif

#if (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) || \
  (defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)) || \
  (defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)) || \
  defined(__ARMEB__) || \
  defined(__THUMBEB__) || \
  defined(__AARCH64EB__) || \
  defined(_MIPSEB) || \
  defined(__MIPSEB) || \
  defined(__MIPSEB__)
template <typename T>
constexpr inline std::enable_if_t<
  std::is_integral<T>{},
  T
>
from_be(T const i) noexcept
{
  return i;
}

template <typename T>
inline std::enable_if_t<
  std::is_integral<T>{},
  T
>
from_le(T const i) noexcept
{
  return swap(i);
}

#elif (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) || \
  (defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)) || \
  (defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)) || \
  defined(__ARMEL__) || \
  defined(__THUMBEL__) || \
  defined(__AARCH64EL__) || \
  defined(_MIPSEL) || \
  defined(__MIPSEL) || \
  defined(__MIPSEL__)

template <typename T>
constexpr inline std::enable_if_t<
  std::is_integral<T>{},
  T
>
from_le(T const i) noexcept
{
  return i;
}

template <typename T>
inline std::enable_if_t<
  std::is_integral<T>{},
  T
>
from_be(T const i) noexcept
{
  return swap(i);
}

#else
#error "I don't know what architecture this is!"
#endif

}

#endif // GNR_SWAP_HPP
<commit_msg>some fixes<commit_after>#ifndef GNR_SWAP_HPP
# define GNR_SWAP_HPP
# pragma once

#include <cstdint>

#include <cstring>

#include <type_traits>

#if defined(_MSC_VER)
# include <stdlib.h>
#endif // _MSC_VER

namespace gnr
{

template <class Dst, class Src>
inline Dst bit_cast(Src const& src) noexcept
{
  Dst dst;

  std::memcpy(&dst, &src, sizeof(dst));

  return dst;
}

template <class Dst, class Src>
inline Dst bit_cast(Src* const src) noexcept
{
  Dst dst;

  std::memcpy(&dst, src, sizeof(dst));

  return dst;
}

#if defined(__GNUC__)

template <typename T>
constexpr std::enable_if_t<
  std::is_integral_v<T> && (sizeof(std::int64_t) == sizeof(T)),
  T
>
swap(T const v) noexcept
{
  return __builtin_bswap64(v);
}

template <typename T>
constexpr std::enable_if_t<
  std::is_integral_v<T> && (sizeof(std::int32_t) == sizeof(T)),
  T
>
swap(T const v) noexcept
{
  return __builtin_bswap32(v);
}

template <typename T>
constexpr std::enable_if_t<
  std::is_integral_v<T> && (sizeof(std::int16_t) == sizeof(T)),
  T
>
swap(T const v) noexcept
{
  return __builtin_bswap16(v);
}

template <typename T>
constexpr std::enable_if_t<
  std::is_integral_v<T> && (sizeof(std::int8_t) == sizeof(T)),
  T
>
swap(T const v) noexcept
{
  return v;
}

#elif defined(_MSC_VER)

template <typename T>
constexpr std::enable_if_t<
  std::is_integral_v<T> && (sizeof(__int64) == sizeof(T)),
  T
>
swap(T const v) noexcept
{
  return _byteswap_uint64(i);
}

template <typename T>
constexpr inline std::enable_if_t<
  std::is_integral_v<T> && (sizeof(unsigned long) == sizeof(T)),
  T
>
swap(T const v) noexcept
{
  return _byteswap_ulong(v);
}

template <typename T>
constexpr inline std::enable_if_t<
  std::is_integral_v<T> && (sizeof(unsigned short) == sizeof(T)),
  T
>
swap(T const v) noexcept
{
  return _byteswap_ushort(v)
}

template <typename T>
constexpr inline std::enable_if_t<
  std::is_integral_v<T> && (sizeof(std::int8_t) == sizeof(T)),
  T
>
swap(T const v) noexcept
{
  return v;
}

#else

namespace detail
{

template<class T, std::size_t ...I>
constexpr T swap_impl(T v, std::index_sequence<I...>) noexcept
{
  return (
    (
      ((v >> (I * std::numeric_limits<char>::digits)) & std::uint8_t(~0)) <<
      ((sizeof(T) - 1 - I) * std::numeric_limits<char>::digits)
    ) | ...
  );
};

}

template <typename T>
constexpr std::enable_if_t<std::is_integral_v<T>, T>
swap(T const v) noexcept
{
  return detail::swap_impl<T>(v, std::make_index_sequence<sizeof(T)>{});
}

#endif

#if (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) || \
  (defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)) || \
  (defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)) || \
  defined(__ARMEB__) || \
  defined(__THUMBEB__) || \
  defined(__AARCH64EB__) || \
  defined(_MIPSEB) || \
  defined(__MIPSEB) || \
  defined(__MIPSEB__)
template <typename T>
constexpr std::enable_if_t<std::is_integral_v<T>, T>
from_be(T const i) noexcept
{
  return i;
}

template <typename T>
inline std::enable_if_t<std::is_integral_v<T>, T>
from_le(T const i) noexcept
{
  return swap(i);
}

#elif (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) || \
  (defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)) || \
  (defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)) || \
  defined(__ARMEL__) || \
  defined(__THUMBEL__) || \
  defined(__AARCH64EL__) || \
  defined(_MIPSEL) || \
  defined(__MIPSEL) || \
  defined(__MIPSEL__)

template <typename T>
constexpr std::enable_if_t<std::is_integral_v<T>, T>
from_le(T const i) noexcept
{
  return i;
}

template <typename T>
inline std::enable_if_t<std::is_integral_v<T>, T>
from_be(T const i) noexcept
{
  return swap(i);
}

#else
#error "I don't know what architecture this is!"
#endif

}

#endif // GNR_SWAP_HPP
<|endoftext|>


<commit_before>// //////////////////////////////////////////////////////////////////////
// Import section
// //////////////////////////////////////////////////////////////////////
// STL
#include <cassert>
#include <sstream>
#if BOOST_VERSION >= 104100
// Boost Property Tree
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp>
#endif // BOOST_VERSION >= 104100
// StdAir
#include <stdair/basic/BasFileMgr.hpp>
#include <stdair/bom/BomINIImport.hpp>
#include <stdair/bom/ConfigHolderStruct.hpp>

#if BOOST_VERSION >= 104100
namespace bpt = boost::property_tree;
#else // BOOST_VERSION >= 104100
namespace bpt {
  typedef char ptree;
}
#endif // BOOST_VERSION >= 104100

namespace stdair {

  // ////////////////////////////////////////////////////////////////////
  void BomINIImport::importINIConfig (ConfigHolderStruct& iConfigHolder,
				      const ConfigINIFile& iConfigINIFile) {

    // Get the config file name.
    const stdair::Filename_T lFilename = iConfigINIFile.name();

    // Check that the file path given as input corresponds to an actual file
    const bool doesExistAndIsReadable =
      stdair::BasFileMgr::doesExistAndIsReadable (lFilename);
    if (doesExistAndIsReadable == false) {
      return;
    }

#if BOOST_VERSION >= 104100

    // Transform the INI file into a BOOST property tree.
    bpt::ptree pt;
    bpt::ini_parser::read_ini(lFilename, pt);
    // Add the property tree to the configuration structure.
    iConfigHolder.add(pt);

#endif // BOOST_VERSION >= 104100
  }

}
<commit_msg>[Dev] Added debug logs about configuration files retrieval.<commit_after>// //////////////////////////////////////////////////////////////////////
// Import section
// //////////////////////////////////////////////////////////////////////
// STL
#include <cassert>
#include <sstream>
#if BOOST_VERSION >= 104100
// Boost Property Tree
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp>
#endif // BOOST_VERSION >= 104100
// StdAir
#include <stdair/basic/BasFileMgr.hpp>
#include <stdair/bom/BomINIImport.hpp>
#include <stdair/bom/ConfigHolderStruct.hpp>
#include <stdair/service/Logger.hpp>

#if BOOST_VERSION >= 104100
namespace bpt = boost::property_tree;
#else // BOOST_VERSION >= 104100
namespace bpt {
  typedef char ptree;
}
#endif // BOOST_VERSION >= 104100

namespace stdair {

  // ////////////////////////////////////////////////////////////////////
  void BomINIImport::importINIConfig (ConfigHolderStruct& iConfigHolder,
				      const ConfigINIFile& iConfigINIFile) {

    // Get the config file name.
    const stdair::Filename_T lFilename = iConfigINIFile.name();

    // Check that the file path given as input corresponds to an actual file
    const bool doesExistAndIsReadable =
      stdair::BasFileMgr::doesExistAndIsReadable (lFilename);
    if (doesExistAndIsReadable == false) {
      STDAIR_LOG_DEBUG ("The config input file '" << lFilename
                       << "' can not be retrieved on the file-system.");
      return;
    }
    STDAIR_LOG_DEBUG ("Load the config input file '" << lFilename
                      << "' content into the configuration holder.");

#if BOOST_VERSION >= 104100

    // Transform the INI file into a BOOST property tree.
    bpt::ptree pt;
    bpt::ini_parser::read_ini(lFilename, pt);
    // Add the property tree to the configuration structure.
    iConfigHolder.add(pt);

#endif // BOOST_VERSION >= 104100
  }

}
<|endoftext|>


<commit_before>

#include "storage/Devices/SwapImpl.h"
#include "storage/Devicegraph.h"
#include "storage/Action.h"
#include "storage/Utils/StorageDefines.h"
#include "storage/Utils/SystemCmd.h"

namespace storage
{

    using namespace std;

    Swap::Impl::Impl(const xmlNode* node)
	: Filesystem::Impl(node)
    {
    }

    void
    Swap::Impl::save(xmlNode* node) const
    {
	Filesystem::Impl::save(node);
    }

    void
    Swap::Impl::add_create_actions(Actiongraph& actiongraph) const
    {
	vector<Action::Base*> actions;

	actions.push_back(new Action::Create(get_sid()));

	if (!get_mountpoints().empty())
	{
	    actions.push_back(new Action::Mount(get_sid(), "swap"));
	    actions.push_back(new Action::AddFstab(get_sid(), "swap"));
	}

	actiongraph.add_chain(actions);
    }

    bool
    Swap::Impl::equal(const Device::Impl& rhs_base) const
    {
	const Impl& rhs = dynamic_cast<const Impl&>(rhs_base);

	if (!Filesystem::Impl::equal(rhs))
	    return false;

	return true;
    }

    void
    Swap::Impl::log_diff(std::ostream& log, const Device::Impl& rhs_base) const
    {
	const Impl& rhs = dynamic_cast<const Impl&>(rhs_base);

	Filesystem::Impl::log_diff(log, rhs);
    }

    void
    Swap::Impl::print(std::ostream& out) const
    {
	Filesystem::Impl::print(out);
    }

    void
    Swap::Impl::do_create() const
    {
	const BlkDevice* blkdevice = get_blkdevice();

	string cmd_line = MKSWAPBIN " -f " + quote(blkdevice->get_name());
	cout << cmd_line << endl;

	SystemCmd cmd(cmd_line);
	if (cmd.retcode() != 0)
	    throw runtime_error("create swap failed");
    }

    void
    Swap::Impl::do_mount(const string& mountpoint) const
    {
	const BlkDevice* blkdevice = get_blkdevice();

	string cmd_line = SWAPONBIN " --fixpgsz " + quote(blkdevice->get_name());
	cout << cmd_line << endl;

	SystemCmd cmd(cmd_line);
	if (cmd.retcode() != 0)
	    throw runtime_error("mount swap failed");
    }

}
<commit_msg>- added include<commit_after>

#include <iostream>

#include "storage/Devices/SwapImpl.h"
#include "storage/Devicegraph.h"
#include "storage/Action.h"
#include "storage/Utils/StorageDefines.h"
#include "storage/Utils/SystemCmd.h"

namespace storage
{

    using namespace std;

    Swap::Impl::Impl(const xmlNode* node)
	: Filesystem::Impl(node)
    {
    }

    void
    Swap::Impl::save(xmlNode* node) const
    {
	Filesystem::Impl::save(node);
    }

    void
    Swap::Impl::add_create_actions(Actiongraph& actiongraph) const
    {
	vector<Action::Base*> actions;

	actions.push_back(new Action::Create(get_sid()));

	if (!get_mountpoints().empty())
	{
	    actions.push_back(new Action::Mount(get_sid(), "swap"));
	    actions.push_back(new Action::AddFstab(get_sid(), "swap"));
	}

	actiongraph.add_chain(actions);
    }

    bool
    Swap::Impl::equal(const Device::Impl& rhs_base) const
    {
	const Impl& rhs = dynamic_cast<const Impl&>(rhs_base);

	if (!Filesystem::Impl::equal(rhs))
	    return false;

	return true;
    }

    void
    Swap::Impl::log_diff(std::ostream& log, const Device::Impl& rhs_base) const
    {
	const Impl& rhs = dynamic_cast<const Impl&>(rhs_base);

	Filesystem::Impl::log_diff(log, rhs);
    }

    void
    Swap::Impl::print(std::ostream& out) const
    {
	Filesystem::Impl::print(out);
    }

    void
    Swap::Impl::do_create() const
    {
	const BlkDevice* blkdevice = get_blkdevice();

	string cmd_line = MKSWAPBIN " -f " + quote(blkdevice->get_name());
	cout << cmd_line << endl;

	SystemCmd cmd(cmd_line);
	if (cmd.retcode() != 0)
	    throw runtime_error("create swap failed");
    }

    void
    Swap::Impl::do_mount(const string& mountpoint) const
    {
	const BlkDevice* blkdevice = get_blkdevice();

	string cmd_line = SWAPONBIN " --fixpgsz " + quote(blkdevice->get_name());
	cout << cmd_line << endl;

	SystemCmd cmd(cmd_line);
	if (cmd.retcode() != 0)
	    throw runtime_error("mount swap failed");
    }

}
<|endoftext|>


<commit_before>#include <iostream>
#include <cassert>
#include <type_traits>
#include <typeinfo>

//Get the total size in bytes of the arguments
template<typename T, typename... Args>
struct SizeOf {
	static const size_t value = sizeof(T) + SizeOf<Args...>::value;
};
template<typename T>
struct SizeOf<T> {
	static const size_t value = sizeof(T);
};
//Get the size in bytes of the arguments with each argument at the desired alignment
template<size_t Align, typename T, typename... Args>
struct AlignedSizeOf {
	static const size_t value = AlignedSizeOf<Align, Args...>::value
		+ (sizeof(T) % Align == 0 ? sizeof(T) : sizeof(T) + Align - sizeof(T) % Align);
};
template<size_t Align, typename T>
struct AlignedSizeOf<Align, T> {
	static const size_t value = sizeof(T) % Align == 0 ? sizeof(T) : sizeof(T) + Align - sizeof(T) % Align;
};

template<int I, typename T, typename... List>
struct TypeAt {
	static_assert(I > -1 && I < sizeof...(List) + 1, "TypeAt index out of bounds");
	using type = typename TypeAt<I-1, List...>::type;
};
template<typename T, typename... List>
struct TypeAt<0, T, List...> {
	using type = T;
};

//Find the offset by the index
template<int I, size_t Align, typename T, typename... List>
struct AlignedOffsetOfIndex {
	static_assert(I > -1 && I < sizeof...(List) + 1, "AlignedOffsetOfIndex index out of bounds");
	static const int64_t value = AlignedOffsetOfIndex<I-1, Align, List...>::value != -1 ?
		AlignedSizeOf<Align, T>::value + AlignedOffsetOfIndex<I-1, Align, List...>::value
		: -1;
};
template<size_t Align, typename T, typename... List>
struct AlignedOffsetOfIndex<0, Align, T, List...> {
	static const int64_t value = 0;
};
template<size_t Align, typename T>
struct AlignedOffsetOfIndex<0, Align, T> {
	static const int64_t value = 0;
};
//If I > 0 and there's only one item left in the list the index is out of bounds
template<int I, size_t Align, typename T>
struct AlignedOffsetOfIndex<I, Align, T> {
	//Should there be a static assert here?
	static const int64_t value = -1;
};

//Would also need indexed offset of to get offset by index instead of by type
template<size_t Align, typename T, typename A, typename... List>
struct AlignedOffsetOf;
template<bool same, size_t Align, typename T, typename A, typename... List>
struct AlignedOffsetOfHelper;
template<size_t Align, typename T, typename A, typename... List>
struct AlignedOffsetOfHelper<true, Align, T, A, List...> {
	static const int64_t value = 0;
};
template<size_t Align, typename T, typename A, typename... List>
struct AlignedOffsetOfHelper<false, Align, T, A, List...> {
	static const int64_t value = AlignedOffsetOf<Align, T, List...>::value != -1 ?
		AlignedSizeOf<Align, T>::value + AlignedOffsetOf<Align, T, List...>::value : -1;
};
template<size_t Align, typename T, typename A>
struct AlignedOffsetOfHelper<true, Align, T, A> {
	static const int64_t value = 0;
};
template<size_t Align, typename T, typename A>
struct AlignedOffsetOfHelper<false, Align, T, A> {
	static const int64_t value = -1;
};
//Get the offset in bytes of some type in the list
template<size_t Align, typename T, typename A, typename... List>
struct AlignedOffsetOf {
	static const int64_t value = AlignedOffsetOfHelper<std::is_same<T, A>::value, Align, T, A, List...>::value;
};

template<typename T, typename A, typename... List>
struct OffsetOf;
template<bool same, typename T, typename A, typename... List>
struct OffsetOfHelper;
template<typename T, typename A, typename... List>
struct OffsetOfHelper<true, T, A, List...> {
	static const int64_t value = 0;
};
template<typename T, typename A, typename... List>
struct OffsetOfHelper<false, T, A, List...> {
	static const int64_t value = OffsetOf<T, List...>::value != -1 ? sizeof(A) + OffsetOf<T, List...>::value : -1;
};
template<typename T, typename A>
struct OffsetOfHelper<true, T, A> {
	static const int64_t value = 0;
};
template<typename T, typename A>
struct OffsetOfHelper<false, T, A> {
	static const int64_t value = -1;
};
//Get the offset in bytes of some type in the list
template<typename T, typename A, typename... List>
struct OffsetOf {
	static const int64_t value = OffsetOfHelper<std::is_same<T, A>::value, T, A, List...>::value;
};

template<typename... Args>
class InterleavedArray {
	size_t sz;
	char *data;

public:
	InterleavedArray(size_t size) : sz(size), data(new char[sz * SizeOf<Args...>::value]){}
	~InterleavedArray(){
		delete[] data;
	}
	template<typename T>
	T& at(size_t i){
		assert(i < sz);
		static_assert(OffsetOf<T, Args...>::value != -1, "Type not in array");
		size_t offset = OffsetOf<T, Args...>::value;
		T *t = static_cast<T*>(static_cast<void*>(data + offset + i * SizeOf<Args...>::value));
		return *t;
	}
	template<size_t I>
	typename TypeAt<I, Args...>::type& at(size_t i){
		assert(i < sz);
		using T = typename TypeAt<I, Args...>::type;
		static_assert(AlignedOffsetOfIndex<I, 1, T, Args...>::value != -1, "Type not in array");
		size_t offset = AlignedOffsetOfIndex<I, 1, T, Args...>::value;
		T *t = static_cast<T*>(static_cast<void*>(data + offset + i * SizeOf<Args...>::value));
		return *t;
	}
	size_t size() const {
		return sz;
	}
};

int main(int argc, char **argv){
	std::cout << "char: " << sizeof(char) << ", size % 4=" << sizeof(char) % 4 << "\n"
		<< "int: " << sizeof(int) << ", size % 4=" << sizeof(int) % 4 << "\n";
	std::cout << "SizeOf<int, float, char>: " << SizeOf<int, float, char>::value << "\n"
		<< "AlignedSizeOf<4, int, float, char>: " << AlignedSizeOf<4, int, float, char>::value << "\n"
		<< "AlignedSizeOf<4, int16_t, int16_t, int16_t>: "
		<< AlignedSizeOf<4, int16_t, int16_t, int16_t>::value << "\n";
	std::cout << "AlignedOffsetOf<4, float, int, char, float>: "
		<< AlignedOffsetOf<4, float, int, char, float>::value << "\n";
	std::cout << "AlignedOffsetOfIndex<1, int16_t, int16_t, int16_t>: "
		<< AlignedOffsetOfIndex<2, 4, int16_t, int16_t, int16_t>::value << "\n";

	using TA = TypeAt<0, float, int, char>::type;
	using TB = TypeAt<1, float, int, char>::type;
	using TC = TypeAt<2, float, int, char>::type;
	static_assert(std::is_same<TA, float>::value && std::is_same<TB, int>::value
		&& std::is_same<TC, char>::value, "TypeAt failure");

	InterleavedArray<int, float, char> array(2);
	array.at<int>(0) = 10;
	array.at<int>(1) = 20;
	array.at<float>(0) = 15.f;
	array.at<float>(1) = 5.f;
	array.at<char>(0) = 'A';
	array.at<char>(1) = 'B';
	for (size_t i = 0; i < array.size(); ++i){
		std::cout << "Data at " << i
			<< ": int=" << array.at<int>(i)
			<< ", float=" << array.at<float>(i)
			<< ", char=" << array.at<char>(i) << "\n";
	}
	std::cout << "Data item 1 @ 0: " << array.at<1>(0) << "\n";
	return 0;
}

<commit_msg>Remove some silly testing<commit_after>#include <iostream>
#include <cassert>
#include <type_traits>
#include <typeinfo>

//Get the total size in bytes of the arguments
template<typename T, typename... Args>
struct SizeOf {
	static const size_t value = sizeof(T) + SizeOf<Args...>::value;
};
template<typename T>
struct SizeOf<T> {
	static const size_t value = sizeof(T);
};
//Get the size in bytes of the arguments with each argument at the desired alignment
template<size_t Align, typename T, typename... Args>
struct AlignedSizeOf {
	static const size_t value = AlignedSizeOf<Align, Args...>::value
		+ (sizeof(T) % Align == 0 ? sizeof(T) : sizeof(T) + Align - sizeof(T) % Align);
};
template<size_t Align, typename T>
struct AlignedSizeOf<Align, T> {
	static const size_t value = sizeof(T) % Align == 0 ? sizeof(T) : sizeof(T) + Align - sizeof(T) % Align;
};

template<int I, typename T, typename... List>
struct TypeAt {
	static_assert(I > -1 && I < sizeof...(List) + 1, "TypeAt index out of bounds");
	using type = typename TypeAt<I-1, List...>::type;
};
template<typename T, typename... List>
struct TypeAt<0, T, List...> {
	using type = T;
};

//Find the offset by the index
template<int I, size_t Align, typename T, typename... List>
struct AlignedOffsetOfIndex {
	static_assert(I > -1 && I < sizeof...(List) + 1, "AlignedOffsetOfIndex index out of bounds");
	static const int64_t value = AlignedOffsetOfIndex<I-1, Align, List...>::value != -1 ?
		AlignedSizeOf<Align, T>::value + AlignedOffsetOfIndex<I-1, Align, List...>::value
		: -1;
};
template<size_t Align, typename T, typename... List>
struct AlignedOffsetOfIndex<0, Align, T, List...> {
	static const int64_t value = 0;
};
template<size_t Align, typename T>
struct AlignedOffsetOfIndex<0, Align, T> {
	static const int64_t value = 0;
};
//If I > 0 and there's only one item left in the list the index is out of bounds
template<int I, size_t Align, typename T>
struct AlignedOffsetOfIndex<I, Align, T> {
	//Should there be a static assert here?
	static const int64_t value = -1;
};

//Would also need indexed offset of to get offset by index instead of by type
template<size_t Align, typename T, typename A, typename... List>
struct AlignedOffsetOf;
template<bool same, size_t Align, typename T, typename A, typename... List>
struct AlignedOffsetOfHelper;
template<size_t Align, typename T, typename A, typename... List>
struct AlignedOffsetOfHelper<true, Align, T, A, List...> {
	static const int64_t value = 0;
};
template<size_t Align, typename T, typename A, typename... List>
struct AlignedOffsetOfHelper<false, Align, T, A, List...> {
	static const int64_t value = AlignedOffsetOf<Align, T, List...>::value != -1 ?
		AlignedSizeOf<Align, T>::value + AlignedOffsetOf<Align, T, List...>::value : -1;
};
template<size_t Align, typename T, typename A>
struct AlignedOffsetOfHelper<true, Align, T, A> {
	static const int64_t value = 0;
};
template<size_t Align, typename T, typename A>
struct AlignedOffsetOfHelper<false, Align, T, A> {
	static const int64_t value = -1;
};
//Get the offset in bytes of some type in the list
template<size_t Align, typename T, typename A, typename... List>
struct AlignedOffsetOf {
	static const int64_t value = AlignedOffsetOfHelper<std::is_same<T, A>::value, Align, T, A, List...>::value;
};

template<typename T, typename A, typename... List>
struct OffsetOf;
template<bool same, typename T, typename A, typename... List>
struct OffsetOfHelper;
template<typename T, typename A, typename... List>
struct OffsetOfHelper<true, T, A, List...> {
	static const int64_t value = 0;
};
template<typename T, typename A, typename... List>
struct OffsetOfHelper<false, T, A, List...> {
	static const int64_t value = OffsetOf<T, List...>::value != -1 ? sizeof(A) + OffsetOf<T, List...>::value : -1;
};
template<typename T, typename A>
struct OffsetOfHelper<true, T, A> {
	static const int64_t value = 0;
};
template<typename T, typename A>
struct OffsetOfHelper<false, T, A> {
	static const int64_t value = -1;
};
//Get the offset in bytes of some type in the list
template<typename T, typename A, typename... List>
struct OffsetOf {
	static const int64_t value = OffsetOfHelper<std::is_same<T, A>::value, T, A, List...>::value;
};

template<typename... Args>
class InterleavedArray {
	size_t sz;
	char *data;

public:
	InterleavedArray(size_t size) : sz(size), data(new char[sz * SizeOf<Args...>::value]){}
	~InterleavedArray(){
		delete[] data;
	}
	template<typename T>
	T& at(size_t i){
		assert(i < sz);
		static_assert(OffsetOf<T, Args...>::value != -1, "Type not in array");
		size_t offset = OffsetOf<T, Args...>::value;
		T *t = static_cast<T*>(static_cast<void*>(data + offset + i * SizeOf<Args...>::value));
		return *t;
	}
	template<size_t I>
	typename TypeAt<I, Args...>::type& at(size_t i){
		assert(i < sz);
		using T = typename TypeAt<I, Args...>::type;
		static_assert(AlignedOffsetOfIndex<I, 1, T, Args...>::value != -1, "Type not in array");
		size_t offset = AlignedOffsetOfIndex<I, 1, T, Args...>::value;
		T *t = static_cast<T*>(static_cast<void*>(data + offset + i * SizeOf<Args...>::value));
		return *t;
	}
	size_t size() const {
		return sz;
	}
};

int main(int argc, char **argv){
	std::cout << "SizeOf<int, float, char>: " << SizeOf<int, float, char>::value << "\n"
		<< "AlignedSizeOf<4, int, float, char>: " << AlignedSizeOf<4, int, float, char>::value << "\n"
		<< "AlignedSizeOf<4, int16_t, int16_t, int16_t>: "
		<< AlignedSizeOf<4, int16_t, int16_t, int16_t>::value << "\n";
	std::cout << "AlignedOffsetOf<4, float, int, char, float>: "
		<< AlignedOffsetOf<4, float, int, char, float>::value << "\n";
	std::cout << "AlignedOffsetOfIndex<1, int16_t, int16_t, int16_t>: "
		<< AlignedOffsetOfIndex<2, 4, int16_t, int16_t, int16_t>::value << "\n";

	using TA = TypeAt<0, float, int, char>::type;
	using TB = TypeAt<1, float, int, char>::type;
	using TC = TypeAt<2, float, int, char>::type;
	static_assert(std::is_same<TA, float>::value && std::is_same<TB, int>::value
		&& std::is_same<TC, char>::value, "TypeAt failure");

	InterleavedArray<int, float, char> array(2);
	array.at<int>(0) = 10;
	array.at<int>(1) = 20;
	array.at<float>(0) = 15.f;
	array.at<float>(1) = 5.f;
	array.at<char>(0) = 'A';
	array.at<char>(1) = 'B';
	for (size_t i = 0; i < array.size(); ++i){
		std::cout << "Data at " << i
			<< ": int=" << array.at<int>(i)
			<< ", float=" << array.at<float>(i)
			<< ", char=" << array.at<char>(i) << "\n";
	}
	std::cout << "Data item 1 @ 0: " << array.at<1>(0) << "\n";
	return 0;
}

<|endoftext|>


<commit_before>#include <stdio.h>

int main() {
    printf("Hello World");
}<commit_msg>test 2<commit_after>#include <stdio.h>

int main() {
    printf("Hello World");
    printf("Joe So Cute");
}<|endoftext|>


<commit_before>#include <clunk/context.h>
#include <clunk/backend/sdl/backend.h>
#include <clunk/source.h>
#include <clunk/wav_file.h>
#include <stdlib.h>
#ifdef _WINDOWS
#	include <Windows.h>
#	define usleep(us) ::Sleep(((us) + 999) / 1000)
#else
#	include <unistd.h>
#endif

#define WINDOW_BITS 9

typedef clunk::mdct_context<WINDOW_BITS, clunk::vorbis_window_func, float> mdct_type;
typedef clunk::fft_context<WINDOW_BITS - 2, float> fft_type;

int main(int argc, char *argv[]) {
	if (argc > 1 && argv[1][0] == 'b' && argv[1][1] == 'm') {
		mdct_type mdct;
		for(int i = 0; i < 1000000; ++i)
			mdct.mdct();
		return 0;
	}
	if (argc > 1 && argv[1][0] == 'b' && argv[1][1] == 'f') {
		fft_type fft;
		for(int i = 0; i < 2000000; ++i)
			fft.fft();
		return 0;
	}
	if (argc > 1 && argv[1][0] == 't') {
		fft_type fft;
		for(int i = 0; i < fft_type::N; ++i) {
			fft.data[i] = std::complex<float>((float)((i / 4) & 1), 0);
		}
		fft.fft();
		for(int i = 0; i < fft_type::N; ++i) {
			printf("%f, %f = %f\n", fft.data[i].real(), fft.data[i].imag(), std::abs(fft.data[i]));
		}
		fft.ifft();

		for(int i = 0; i < fft_type::N; ++i) {
			fft.data[i] -= std::complex<float>((float)((i / 4) & 1), 0);
			printf("%f, %f\n", fft.data[i].real(), fft.data[i].imag());
		}

		return 0;
	}

	clunk::sdl::Backend backend(44100, 2, 1024);
	clunk::Context &context = backend.get_context();

	clunk::Object * o = context.create_object();
	clunk::Sample * s = clunk::WavFile::load(context, "scissors.wav");
	clunk::Sample * h = clunk::WavFile::load(context, "helicopter.wav");

	static const int d = 3, n = 72;
	clunk::DistanceModel dm(clunk::DistanceModel::Exponent, false);
	dm.rolloff_factor = 0.7f;
	context.set_distance_model(dm);

	context.save("test_out.raw");
	backend.start();
/*	o->play("l", new clunk::Source(s, false, clunk::v3f(-d, 0, 0)));
	sleep(1);
	//o->play("c", new clunk::Source(s, false, clunk::v3f(0, 0, 0)));
	//sleep(1);
	o->play("r", new clunk::Source(s, false, clunk::v3f(d, 0, 0)));
	sleep(1);

	o->play("u", new clunk::Source(s, false, clunk::v3f(0, d, 0)));
	sleep(1);

	o->play("b", new clunk::Source(s, false, clunk::v3f(0, 0, d)));
	sleep(1);
*/
	o->play("h", new clunk::Source(h, true));

	for(int i = 0; i <= n; ++i) {
		float a = float(2 * M_PI * i / n);
		clunk::v3f pos(cos(a) * d, sin(a) * d * 2, 1);
		o->set_position(pos);
		printf("%g %g %g\n", pos.x, pos.y, pos.z);
		usleep(100000);
	}

/*	for(int i = 0; i <= n; ++i) {
		float a = M_PI * i / n;
		o->play("s", new clunk::Source(s, false, clunk::v3f(cos(a), -0.25f, sin(a)) * d));
		usleep(500000);
	}
*/	backend.stop();
	return 0;
}
<commit_msg>added mdct feed test mode<commit_after>#include <clunk/context.h>
#include <clunk/backend/sdl/backend.h>
#include <clunk/source.h>
#include <clunk/wav_file.h>
#include <stdlib.h>
#ifdef _WINDOWS
#	include <Windows.h>
#	define usleep(us) ::Sleep(((us) + 999) / 1000)
#else
#	include <unistd.h>
#endif
#include <clunk/ref_mdct_context.h>

#define WINDOW_BITS 9

typedef clunk::mdct_context<WINDOW_BITS, clunk::vorbis_window_func, float> mdct_type;
typedef clunk::fft_context<WINDOW_BITS - 2, float> fft_type;

template<typename mdct_type>
struct mdct_test {
	mdct_type	_mdct;
	float		_input[mdct_type::N];
	float		_overlap[mdct_type::N2];

	mdct_test(): _input(), _overlap() { }
	void dump(int n = mdct_type::N)
	{
		for(int i = 0; i < n; ++i)
			printf("%+1.1g ", _mdct.data[i]);
	}

	void feed()
	{
		//printf("feeding ");
		for(int i = 0; i < mdct_type::N2; ++i)
		{
			float v = (rand() % 11) - 5;
			_input[i] = _input[i + mdct_type::N2];
			_input[i + mdct_type::N2] = v;
			//printf("%+g ", v);
		}
		printf("\ninput: ");
		for(int i = 0; i < mdct_type::N; ++i)
		{
			_mdct.data[i] = _input[i];
		}
		dump();
		//_mdct.apply_window();
		_mdct.mdct();
		//printf("\n\tfreq: "); dump();
		_mdct.imdct();
		//_mdct.apply_window();

		for(int i = 0; i < mdct_type::N2; ++i)
			_mdct.data[i] += _overlap[i];

		for(int i = 0; i < mdct_type::N2; ++i)
			_overlap[i] = _mdct.data[mdct_type::N2 + i];

		printf("\nresult: "); dump(mdct_type::N2);
		printf("\n");
	}
};

int main(int argc, char *argv[]) {

	if (argc > 1 && argv[1][0] == 'b' && argv[1][1] == 'm') {
		mdct_type mdct;
		for(int i = 0; i < 1000000; ++i)
			mdct.mdct();
		return 0;
	}
	if (argc > 1 && argv[1][0] == 'b' && argv[1][1] == 'f') {
		fft_type fft;
		for(int i = 0; i < 2000000; ++i)
			fft.fft();
		return 0;
	}
	if (argc > 1 && argv[1][0] == 't') {
		fft_type fft;
		for(int i = 0; i < fft_type::N; ++i) {
			fft.data[i] = std::complex<float>((float)((i / 4) & 1), 0);
		}
		fft.fft();
		for(int i = 0; i < fft_type::N; ++i) {
			printf("%f, %f = %f\n", fft.data[i].real(), fft.data[i].imag(), std::abs(fft.data[i]));
		}
		fft.ifft();

		for(int i = 0; i < fft_type::N; ++i) {
			fft.data[i] -= std::complex<float>((float)((i / 4) & 1), 0);
			printf("%f, %f\n", fft.data[i].real(), fft.data[i].imag());
		}

		return 0;
	}
	if (argc > 1 && argv[1][0] == 'f')
	{
		printf("reference: \n");
		mdct_test<clunk::ref_mdct_context<3, clunk::sin_window_func, float> > test;
		test.feed();
		test.feed();
		test.feed();
		test.feed();
		printf("fft based: \n");
		mdct_test<clunk::mdct_context<3, clunk::sin_window_func, float> > test2;
		test2.feed();
		test2.feed();
		test2.feed();
		test2.feed();
		return 0;
	}

	clunk::sdl::Backend backend(44100, 2, 1024);
	clunk::Context &context = backend.get_context();

	clunk::Object * o = context.create_object();
	clunk::Sample * s = clunk::WavFile::load(context, "scissors.wav");
	clunk::Sample * h = clunk::WavFile::load(context, "helicopter.wav");

	static const int d = 3, n = 72;
	clunk::DistanceModel dm(clunk::DistanceModel::Exponent, false);
	dm.rolloff_factor = 0.7f;
	context.set_distance_model(dm);

	context.save("test_out.raw");
	backend.start();
/*	o->play("l", new clunk::Source(s, false, clunk::v3f(-d, 0, 0)));
	sleep(1);
	//o->play("c", new clunk::Source(s, false, clunk::v3f(0, 0, 0)));
	//sleep(1);
	o->play("r", new clunk::Source(s, false, clunk::v3f(d, 0, 0)));
	sleep(1);

	o->play("u", new clunk::Source(s, false, clunk::v3f(0, d, 0)));
	sleep(1);

	o->play("b", new clunk::Source(s, false, clunk::v3f(0, 0, d)));
	sleep(1);
*/
	o->play("h", new clunk::Source(h, true));

	for(int i = 0; i <= n; ++i) {
		float a = float(2 * M_PI * i / n);
		clunk::v3f pos(cos(a) * d, sin(a) * d * 2, 1);
		o->set_position(pos);
		printf("%g %g %g\n", pos.x, pos.y, pos.z);
		usleep(100000);
	}

/*	for(int i = 0; i <= n; ++i) {
		float a = M_PI * i / n;
		o->play("s", new clunk::Source(s, false, clunk::v3f(cos(a), -0.25f, sin(a)) * d));
		usleep(500000);
	}
*/	backend.stop();
	return 0;
}
<|endoftext|>