<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: UpdateLockManager.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: kz $ $Date: 2006-12-12 19:08:05 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sd.hxx"

#include "UpdateLockManager.hxx"

#include "MutexOwner.hxx"
#include "ViewShellBase.hxx"

#ifndef _COM_SUN_STAR_FRAME_XLAYOUTMANAGER_HPP_
#include <com/sun/star/frame/XLayoutManager.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XLAYOUTMANAGEREVENTBROADCASTER_HPP_
#include <com/sun/star/frame/XLayoutManagerEventBroadcaster.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_LAYOUTMANAGEREVENTS_HPP_
#include <com/sun/star/frame/LayoutManagerEvents.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif

#ifndef _CPPUHELPER_COMPBASE1_HXX_
#include <cppuhelper/compbase1.hxx>
#endif

#include <vcl/timer.hxx>
#include <sfx2/viewfrm.hxx>

using namespace ::com::sun::star::uno;
using namespace ::com::sun::star;

namespace {
typedef cppu::WeakComponentImplHelper1<frame::XLayoutManagerListener> InterfaceBase;
}

namespace sd {

/** This implementation class not only implements the Lock() and Unlock()
    methods but as well listens for the right combination of events to call
    Unlock() when all is ready after the PaneManager has switched (some of)
    its view shells.
*/

class UpdateLockManager::Implementation
    : protected MutexOwner,
      public InterfaceBase
{
public:
    Implementation (ViewShellBase& rBase);
    virtual ~Implementation (void);

    void Lock (void);
    void Unlock (void);
    bool IsLocked (void) const;

    /** Unlock regardless of the current lock level.
    */
    void ForceUnlock (void);

private:
    ViewShellBase& mrBase;
    /// A lock level greater than 0 indicates that the ViewShellBase is locked.
    sal_Int32 mnLockDepth;
    /// The emergency timer to unlock the ViewShellBase when all else fails.
    Timer maTimer;
    /// Remember when to unlock after a layout event from frame::XLayoutManager
    bool mbUnlockOnNextLayout;
    /// Remember whether we are listening to the frame::XLayoutManager
    bool mbListenerIsRegistered;
    /// Remember whether the frame::XLayoutManager is locked.
    bool mbLayouterIsLocked;
    /** We hold a weak reference to the layout manager in order to have
        access to it even when the ViewShellBase object is not valid anymore
        and can not be used to obtain the layout manager.
    */
    WeakReference<frame::XLayoutManager> mxLayoutManager;

    //=====  frame::XLayoutEventListener  =====================================

    /** The event of the layouter are observed to find the best moment for
        unlocking.  This is the first layout after the lock level of the
        layouter drops to one (we hold a lock to it ourselves which we
        release when unlocking).
    */
    virtual void SAL_CALL layoutEvent (
        const lang::EventObject& xSource,
        sal_Int16 eLayoutEvent,
        const Any& rInfo)
        throw (uno::RuntimeException);

    //=====  lang::XEventListener  ============================================
    virtual void SAL_CALL
        disposing (const lang::EventObject& rEventObject)
        throw (::com::sun::star::uno::RuntimeException);

    virtual void SAL_CALL disposing (void);

    /** This is only a fallback to make the office usable when for some
        reason the intended way of unlocking it failed.
    */
    DECL_LINK(Timeout, void*);

    /** Convenience method that finds the layout manager associated with the
        frame that shows the ViewShellBase.
    */
    Reference<frame::XLayoutManager> GetLayoutManager (void);

    Implementation (const Implementation&); // Not implemented.
    Implementation& operator= (const Implementation&); // Not implemented.
};

//===== UpdateLockManager =====================================================

UpdateLockManager::UpdateLockManager (ViewShellBase& rBase)
    : mpImpl(new Implementation(rBase))
{
    mpImpl->acquire();
}

UpdateLockManager::~UpdateLockManager (void)
{
    if (mpImpl != NULL)
    {
        mpImpl->ForceUnlock();
        mpImpl->release();
    }
}

void UpdateLockManager::Disable (void)
{
    if (mpImpl != NULL)
    {
        mpImpl->ForceUnlock();
        mpImpl->release();
        mpImpl = NULL;
    }
}

void UpdateLockManager::Lock (void)
{
    if (mpImpl != NULL)
        mpImpl->Lock();
}

void UpdateLockManager::Unlock (void)
{
    if (mpImpl != NULL)
        mpImpl->Unlock();
}

bool UpdateLockManager::IsLocked (void) const
{
    if (mpImpl != NULL)
        return mpImpl->IsLocked();
    else
        return false;
}

//===== UpdateLock::Implementation ============================================

UpdateLockManager::Implementation::Implementation (ViewShellBase& rBase)
    : InterfaceBase(maMutex),
      mrBase(rBase),
      mnLockDepth(0),
      maTimer(),
      mbUnlockOnNextLayout(false),
      mbListenerIsRegistered(false),
      mbLayouterIsLocked(false)
{
}

UpdateLockManager::Implementation::~Implementation (void)
{
    OSL_ASSERT(mnLockDepth==0);
    ForceUnlock();
}

void UpdateLockManager::Implementation::Lock (void)
{
    ++mnLockDepth;
    if (mnLockDepth == 1)
    {
        Reference<frame::XLayoutManager> xLayouter (GetLayoutManager());
        if (xLayouter.is())
        {
            // Register as event listener.
            Reference<frame::XLayoutManagerEventBroadcaster> xBroadcaster (
                xLayouter, UNO_QUERY);
            if (xBroadcaster.is())
            {
                mbListenerIsRegistered = true;
                xBroadcaster->addLayoutManagerEventListener(
                    Reference<frame::XLayoutManagerListener> (
                        static_cast<XWeak*>(this), UNO_QUERY) );
            }

            // Lock the layout manager.
            mbLayouterIsLocked = true;
            xLayouter->lock();
        }

        // As a fallback, when the notification mechanism does not work (or is
        // incorrectly used) we use a timer that will unlock us eventually.
        maTimer.SetTimeout(5000 /*ms*/);
        maTimer.SetTimeoutHdl(LINK(this,UpdateLockManager::Implementation,Timeout));
        maTimer.Start();
    }
}

void UpdateLockManager::Implementation::Unlock (void)
{
    --mnLockDepth;

    if (mnLockDepth == 0)
    {
        // Stop the timer.  We don't need it anymore.
        maTimer.Stop();

        try
        {
            Reference<frame::XLayoutManager> xLayouter (GetLayoutManager());
            if (xLayouter.is())
            {
                // Detach from the layouter.
                if (mbListenerIsRegistered)
                {
                    Reference<frame::XLayoutManagerEventBroadcaster> xBroadcaster (
                        xLayouter, UNO_QUERY);
                    if (xBroadcaster.is())
                    {
                        mbListenerIsRegistered = false;
                        xBroadcaster->removeLayoutManagerEventListener(
                            Reference<frame::XLayoutManagerListener> (
                                static_cast<XWeak*>(this), UNO_QUERY) );
                    }
                }

                // Unlock the layouter.
                if (mbLayouterIsLocked)
                {
                    mbLayouterIsLocked = false;
                    xLayouter->unlock();
                }
            }
        }
        catch (RuntimeException)
        { }

        // Force a rearrangement of the UI elements of the views.
        mrBase.Rearrange();
    }
}

bool UpdateLockManager::Implementation::IsLocked (void) const
{
    return (mnLockDepth > 0);
}

void UpdateLockManager::Implementation::ForceUnlock (void)
{
    while (IsLocked())
        Unlock();
}

void SAL_CALL UpdateLockManager::Implementation::layoutEvent (
    const lang::EventObject&,
    sal_Int16 eLayoutEvent,
    const Any& rInfo)
    throw (uno::RuntimeException)
{
    switch (eLayoutEvent)
    {
        case frame::LayoutManagerEvents::LOCK:
        {
            sal_Int32 nLockCount;
            rInfo >>= nLockCount;
        }
        break;

        case frame::LayoutManagerEvents::UNLOCK:
        {
            sal_Int32 nLockCount;
            rInfo >>= nLockCount;
            if (nLockCount == 1)
            {
                // The lock count dropped to one.  This means that we are
                // the only one that still holds a lock to the layout
                // manager.  We unlock the layout manager now and the
                // ViewShellBase on the next layout of the layout manager.
                mbUnlockOnNextLayout = true;
                Reference<frame::XLayoutManager> xLayouter (GetLayoutManager());
                if (xLayouter.is() && mbLayouterIsLocked)
                {
                    mbLayouterIsLocked = false;
                    xLayouter->unlock();
                }
            }
        }
        break;

        case frame::LayoutManagerEvents::LAYOUT:
            // Unlock when the layout manager is not still locked.
            if (mbUnlockOnNextLayout)
                Unlock();
            break;
    }
}

void SAL_CALL UpdateLockManager::Implementation::disposing (const lang::EventObject& )
    throw (::com::sun::star::uno::RuntimeException)
{
}

void SAL_CALL UpdateLockManager::Implementation::disposing (void)
{
}

IMPL_LINK(UpdateLockManager::Implementation, Timeout, void*, EMPTYARG)
{
    // This method is only called when all else failed.  We unlock
    // regardless of how deep the lock depth.
    while (mnLockDepth > 0)
        Unlock();
    return 1;
}

Reference< ::com::sun::star::frame::XLayoutManager>
    UpdateLockManager::Implementation::GetLayoutManager (void)
{
    Reference<frame::XLayoutManager> xLayoutManager;

    if (mxLayoutManager.get() == NULL)
    {
        if (mrBase.GetViewFrame()!=NULL
            && mrBase.GetViewFrame()->GetFrame()!=NULL)
        {
            Reference<beans::XPropertySet> xFrameProperties (
                mrBase.GetViewFrame()->GetFrame()->GetFrameInterface(),
                UNO_QUERY);
            if (xFrameProperties.is())
            {
                try
                {
                    Any aValue (xFrameProperties->getPropertyValue(
                        ::rtl::OUString::createFromAscii("LayoutManager")));
                    aValue >>= xLayoutManager;
                }
                catch (const beans::UnknownPropertyException& rException)
                {
                    (void)rException;
                }
            }
            mxLayoutManager = xLayoutManager;
        }
    }
    else
        xLayoutManager = mxLayoutManager;

    return xLayoutManager;
}

} // end of anonymous namespace
<commit_msg>INTEGRATION: CWS pj69 (1.7.2); FILE MERGED 2007/01/03 14:53:11 pjanik 1.7.2.1: #i73070#: Add initializations to prevent warnings.<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: UpdateLockManager.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: vg $ $Date: 2007-01-09 11:36:03 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sd.hxx"

#include "UpdateLockManager.hxx"

#include "MutexOwner.hxx"
#include "ViewShellBase.hxx"

#ifndef _COM_SUN_STAR_FRAME_XLAYOUTMANAGER_HPP_
#include <com/sun/star/frame/XLayoutManager.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XLAYOUTMANAGEREVENTBROADCASTER_HPP_
#include <com/sun/star/frame/XLayoutManagerEventBroadcaster.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_LAYOUTMANAGEREVENTS_HPP_
#include <com/sun/star/frame/LayoutManagerEvents.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif

#ifndef _CPPUHELPER_COMPBASE1_HXX_
#include <cppuhelper/compbase1.hxx>
#endif

#include <vcl/timer.hxx>
#include <sfx2/viewfrm.hxx>

using namespace ::com::sun::star::uno;
using namespace ::com::sun::star;

namespace {
typedef cppu::WeakComponentImplHelper1<frame::XLayoutManagerListener> InterfaceBase;
}

namespace sd {

/** This implementation class not only implements the Lock() and Unlock()
    methods but as well listens for the right combination of events to call
    Unlock() when all is ready after the PaneManager has switched (some of)
    its view shells.
*/

class UpdateLockManager::Implementation
    : protected MutexOwner,
      public InterfaceBase
{
public:
    Implementation (ViewShellBase& rBase);
    virtual ~Implementation (void);

    void Lock (void);
    void Unlock (void);
    bool IsLocked (void) const;

    /** Unlock regardless of the current lock level.
    */
    void ForceUnlock (void);

private:
    ViewShellBase& mrBase;
    /// A lock level greater than 0 indicates that the ViewShellBase is locked.
    sal_Int32 mnLockDepth;
    /// The emergency timer to unlock the ViewShellBase when all else fails.
    Timer maTimer;
    /// Remember when to unlock after a layout event from frame::XLayoutManager
    bool mbUnlockOnNextLayout;
    /// Remember whether we are listening to the frame::XLayoutManager
    bool mbListenerIsRegistered;
    /// Remember whether the frame::XLayoutManager is locked.
    bool mbLayouterIsLocked;
    /** We hold a weak reference to the layout manager in order to have
        access to it even when the ViewShellBase object is not valid anymore
        and can not be used to obtain the layout manager.
    */
    WeakReference<frame::XLayoutManager> mxLayoutManager;

    //=====  frame::XLayoutEventListener  =====================================

    /** The event of the layouter are observed to find the best moment for
        unlocking.  This is the first layout after the lock level of the
        layouter drops to one (we hold a lock to it ourselves which we
        release when unlocking).
    */
    virtual void SAL_CALL layoutEvent (
        const lang::EventObject& xSource,
        sal_Int16 eLayoutEvent,
        const Any& rInfo)
        throw (uno::RuntimeException);

    //=====  lang::XEventListener  ============================================
    virtual void SAL_CALL
        disposing (const lang::EventObject& rEventObject)
        throw (::com::sun::star::uno::RuntimeException);

    virtual void SAL_CALL disposing (void);

    /** This is only a fallback to make the office usable when for some
        reason the intended way of unlocking it failed.
    */
    DECL_LINK(Timeout, void*);

    /** Convenience method that finds the layout manager associated with the
        frame that shows the ViewShellBase.
    */
    Reference<frame::XLayoutManager> GetLayoutManager (void);

    Implementation (const Implementation&); // Not implemented.
    Implementation& operator= (const Implementation&); // Not implemented.
};

//===== UpdateLockManager =====================================================

UpdateLockManager::UpdateLockManager (ViewShellBase& rBase)
    : mpImpl(new Implementation(rBase))
{
    mpImpl->acquire();
}

UpdateLockManager::~UpdateLockManager (void)
{
    if (mpImpl != NULL)
    {
        mpImpl->ForceUnlock();
        mpImpl->release();
    }
}

void UpdateLockManager::Disable (void)
{
    if (mpImpl != NULL)
    {
        mpImpl->ForceUnlock();
        mpImpl->release();
        mpImpl = NULL;
    }
}

void UpdateLockManager::Lock (void)
{
    if (mpImpl != NULL)
        mpImpl->Lock();
}

void UpdateLockManager::Unlock (void)
{
    if (mpImpl != NULL)
        mpImpl->Unlock();
}

bool UpdateLockManager::IsLocked (void) const
{
    if (mpImpl != NULL)
        return mpImpl->IsLocked();
    else
        return false;
}

//===== UpdateLock::Implementation ============================================

UpdateLockManager::Implementation::Implementation (ViewShellBase& rBase)
    : InterfaceBase(maMutex),
      mrBase(rBase),
      mnLockDepth(0),
      maTimer(),
      mbUnlockOnNextLayout(false),
      mbListenerIsRegistered(false),
      mbLayouterIsLocked(false)
{
}

UpdateLockManager::Implementation::~Implementation (void)
{
    OSL_ASSERT(mnLockDepth==0);
    ForceUnlock();
}

void UpdateLockManager::Implementation::Lock (void)
{
    ++mnLockDepth;
    if (mnLockDepth == 1)
    {
        Reference<frame::XLayoutManager> xLayouter (GetLayoutManager());
        if (xLayouter.is())
        {
            // Register as event listener.
            Reference<frame::XLayoutManagerEventBroadcaster> xBroadcaster (
                xLayouter, UNO_QUERY);
            if (xBroadcaster.is())
            {
                mbListenerIsRegistered = true;
                xBroadcaster->addLayoutManagerEventListener(
                    Reference<frame::XLayoutManagerListener> (
                        static_cast<XWeak*>(this), UNO_QUERY) );
            }

            // Lock the layout manager.
            mbLayouterIsLocked = true;
            xLayouter->lock();
        }

        // As a fallback, when the notification mechanism does not work (or is
        // incorrectly used) we use a timer that will unlock us eventually.
        maTimer.SetTimeout(5000 /*ms*/);
        maTimer.SetTimeoutHdl(LINK(this,UpdateLockManager::Implementation,Timeout));
        maTimer.Start();
    }
}

void UpdateLockManager::Implementation::Unlock (void)
{
    --mnLockDepth;

    if (mnLockDepth == 0)
    {
        // Stop the timer.  We don't need it anymore.
        maTimer.Stop();

        try
        {
            Reference<frame::XLayoutManager> xLayouter (GetLayoutManager());
            if (xLayouter.is())
            {
                // Detach from the layouter.
                if (mbListenerIsRegistered)
                {
                    Reference<frame::XLayoutManagerEventBroadcaster> xBroadcaster (
                        xLayouter, UNO_QUERY);
                    if (xBroadcaster.is())
                    {
                        mbListenerIsRegistered = false;
                        xBroadcaster->removeLayoutManagerEventListener(
                            Reference<frame::XLayoutManagerListener> (
                                static_cast<XWeak*>(this), UNO_QUERY) );
                    }
                }

                // Unlock the layouter.
                if (mbLayouterIsLocked)
                {
                    mbLayouterIsLocked = false;
                    xLayouter->unlock();
                }
            }
        }
        catch (RuntimeException)
        { }

        // Force a rearrangement of the UI elements of the views.
        mrBase.Rearrange();
    }
}

bool UpdateLockManager::Implementation::IsLocked (void) const
{
    return (mnLockDepth > 0);
}

void UpdateLockManager::Implementation::ForceUnlock (void)
{
    while (IsLocked())
        Unlock();
}

void SAL_CALL UpdateLockManager::Implementation::layoutEvent (
    const lang::EventObject&,
    sal_Int16 eLayoutEvent,
    const Any& rInfo)
    throw (uno::RuntimeException)
{
    switch (eLayoutEvent)
    {
        case frame::LayoutManagerEvents::LOCK:
        {
            sal_Int32 nLockCount;
            rInfo >>= nLockCount;
        }
        break;

        case frame::LayoutManagerEvents::UNLOCK:
        {
            sal_Int32 nLockCount = 0;
            rInfo >>= nLockCount;
            if (nLockCount == 1)
            {
                // The lock count dropped to one.  This means that we are
                // the only one that still holds a lock to the layout
                // manager.  We unlock the layout manager now and the
                // ViewShellBase on the next layout of the layout manager.
                mbUnlockOnNextLayout = true;
                Reference<frame::XLayoutManager> xLayouter (GetLayoutManager());
                if (xLayouter.is() && mbLayouterIsLocked)
                {
                    mbLayouterIsLocked = false;
                    xLayouter->unlock();
                }
            }
        }
        break;

        case frame::LayoutManagerEvents::LAYOUT:
            // Unlock when the layout manager is not still locked.
            if (mbUnlockOnNextLayout)
                Unlock();
            break;
    }
}

void SAL_CALL UpdateLockManager::Implementation::disposing (const lang::EventObject& )
    throw (::com::sun::star::uno::RuntimeException)
{
}

void SAL_CALL UpdateLockManager::Implementation::disposing (void)
{
}

IMPL_LINK(UpdateLockManager::Implementation, Timeout, void*, EMPTYARG)
{
    // This method is only called when all else failed.  We unlock
    // regardless of how deep the lock depth.
    while (mnLockDepth > 0)
        Unlock();
    return 1;
}

Reference< ::com::sun::star::frame::XLayoutManager>
    UpdateLockManager::Implementation::GetLayoutManager (void)
{
    Reference<frame::XLayoutManager> xLayoutManager;

    if (mxLayoutManager.get() == NULL)
    {
        if (mrBase.GetViewFrame()!=NULL
            && mrBase.GetViewFrame()->GetFrame()!=NULL)
        {
            Reference<beans::XPropertySet> xFrameProperties (
                mrBase.GetViewFrame()->GetFrame()->GetFrameInterface(),
                UNO_QUERY);
            if (xFrameProperties.is())
            {
                try
                {
                    Any aValue (xFrameProperties->getPropertyValue(
                        ::rtl::OUString::createFromAscii("LayoutManager")));
                    aValue >>= xLayoutManager;
                }
                catch (const beans::UnknownPropertyException& rException)
                {
                    (void)rException;
                }
            }
            mxLayoutManager = xLayoutManager;
        }
    }
    else
        xLayoutManager = mxLayoutManager;

    return xLayoutManager;
}

} // end of anonymous namespace
<|endoftext|>


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

/* $Id$ */

//_________________________________________________________________________
//  Class to perform flattening of the event plane distribution
//       It stores necessary parameterizations and apply when requested
//
//*-- Author: Dmitri Peressounko (RRC KI)

// --- ROOT system ---

#include "TMath.h"
#include "TH2.h"

// --- Standard library ---

// --- AliRoot header files ---

#include "AliPHOSEPFlattener.h"

ClassImp(AliPHOSEPFlattener)

//____________________________________________________________________________
AliPHOSEPFlattener::AliPHOSEPFlattener() :
  TNamed(),
  fNCentrBins(0),
  fNHarmonics(0),
  fNparam(0),
  fParam(0x0)
{
  // default ctor
//  Nothing to initialize
}

//____________________________________________________________________________
AliPHOSEPFlattener::AliPHOSEPFlattener(const char * name) :
  TNamed(name,"PHOSEPFlattener"),
  fNCentrBins(0),
  fNHarmonics(0),
  fNparam(0),
  fParam(0x0)
{
//  Nothing to initialize
}
//____________________________________________________________________________
AliPHOSEPFlattener::AliPHOSEPFlattener(const AliPHOSEPFlattener & fl):
  TNamed(fl.GetName(),"PHOSEPFlattener"),
  fNCentrBins(0),
  fNHarmonics(0),
  fNparam(0),
  fParam(0x0)

{

  fNCentrBins = fl.fNCentrBins ;
  fNHarmonics = fl.fNHarmonics ;
  fNparam     = fl.fNparam ;
  fParam = new Double32_t[fNparam] ;
  for(Int_t i=0; i<fNparam; i++)
    fParam[i]=fl.fParam[i] ;
}

//____________________________________________________________________________
AliPHOSEPFlattener & AliPHOSEPFlattener::operator = (const AliPHOSEPFlattener & fl)
{
  SetName(fl.GetName()) ;
  fNCentrBins = fl.fNCentrBins ;
  fNHarmonics = fl.fNHarmonics ;
  fNparam     = fl.fNparam ;
  if(fParam) delete [] fParam ;
  fParam = new Double32_t[fNparam] ;
  for(Int_t i=0; i<fNparam; i++)
    fParam[i]=fl.fParam[i] ;

  return *this;
}
//____________________________________________________________________________
AliPHOSEPFlattener::~AliPHOSEPFlattener()
{
// Nothing to delete
  fNCentrBins = 0 ;
  fNHarmonics = 0 ;
  fNparam     = 0 ;
  if(fParam)
    delete [] fParam ;
  fParam = 0x0 ;

}
//____________________________________________________________________________
Double_t AliPHOSEPFlattener::MakeFlat(Double_t oldPhi,Double_t centrality)const
{
  //Apply flattening using existing parameterizations
  if(fNCentrBins==0) return oldPhi; //No correction encoded

  Double_t result = oldPhi ;
  //Centrality bin
  Int_t icen=(Int_t) (centrality*fNCentrBins/100.) ;
  if(icen>=fNCentrBins)icen = fNCentrBins-1 ;

  //Offset in the array
  icen=icen*fNHarmonics ;

  for(Int_t i = 0; i<fNHarmonics; i+=2){
    Double_t c = fParam[icen+i] ;  //Mean cos(n*phi) for a given centrality
    Double_t s = fParam[icen+i+1]; //Mean sin(n*phi) for a given centrality
    result += c*TMath::Sin((i/2+1)*oldPhi)-s*TMath::Cos((i/2+1)*oldPhi) ;
  }
  return result ;
}
//____________________________________________________________________________
void AliPHOSEPFlattener::SetParameterization(TH2 * h){
 //Fill parameterizations
 //We expect histogram with <cos(i*phi)>, <sin(i*phi)> with centrality bins in x axis
 //and harmonics: <cos(x)>, <sin(x)>, <cos(2x)>, <sin(2x)>, .... in y axis

  fNCentrBins = h->GetXaxis()->GetNbins() ;
  fNHarmonics = h->GetYaxis()->GetNbins() ;
  fNparam     = fNCentrBins*fNHarmonics ;
  if(fParam) delete [] fParam ;
  fParam = new Double32_t[fNparam] ;
  for(Int_t i=0; i<fNCentrBins; i++)
    for(Int_t j=0; j<fNHarmonics; j++)
      fParam[i*fNHarmonics+j]=h->GetBinContent(i+1,j+1) ;
}

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

/* $Id$ */

//_________________________________________________________________________
//  Class to perform flattening of the event plane distribution
//       It stores necessary parameterizations and apply when requested
//
//*-- Author: Dmitri Peressounko (RRC KI)

// --- ROOT system ---

#include "TMath.h"
#include "TH2.h"

// --- Standard library ---

// --- AliRoot header files ---

#include "AliPHOSEPFlattener.h"

ClassImp(AliPHOSEPFlattener)

//____________________________________________________________________________
AliPHOSEPFlattener::AliPHOSEPFlattener() :
  TNamed(),
  fNCentrBins(0),
  fNHarmonics(0),
  fNparam(0),
  fParam(0x0)
{
  // default ctor
//  Nothing to initialize
}

//____________________________________________________________________________
AliPHOSEPFlattener::AliPHOSEPFlattener(const char * name) :
  TNamed(name,"PHOSEPFlattener"),
  fNCentrBins(0),
  fNHarmonics(0),
  fNparam(0),
  fParam(0x0)
{
//  Nothing to initialize
}
//____________________________________________________________________________
AliPHOSEPFlattener::AliPHOSEPFlattener(const AliPHOSEPFlattener & fl):
  TNamed(fl.GetName(),"PHOSEPFlattener"),
  fNCentrBins(0),
  fNHarmonics(0),
  fNparam(0),
  fParam(0x0)

{

  fNCentrBins = fl.fNCentrBins ;
  fNHarmonics = fl.fNHarmonics ;
  fNparam     = fl.fNparam ;
  fParam = new Double32_t[fNparam] ;
  for(Int_t i=0; i<fNparam; i++)
    fParam[i]=fl.fParam[i] ;
}

//____________________________________________________________________________
AliPHOSEPFlattener & AliPHOSEPFlattener::operator = (const AliPHOSEPFlattener & fl)
{
  SetName(fl.GetName()) ;
  fNCentrBins = fl.fNCentrBins ;
  fNHarmonics = fl.fNHarmonics ;
  fNparam     = fl.fNparam ;
  if(fParam) delete [] fParam ;
  fParam = new Double32_t[fNparam] ;
  for(Int_t i=0; i<fNparam; i++)
    fParam[i]=fl.fParam[i] ;

  return *this;
}
//____________________________________________________________________________
AliPHOSEPFlattener::~AliPHOSEPFlattener()
{
// Nothing to delete
  fNCentrBins = 0 ;
  fNHarmonics = 0 ;
  fNparam     = 0 ;
  if(fParam)
    delete [] fParam ;
  fParam = 0x0 ;

}
//____________________________________________________________________________
Double_t AliPHOSEPFlattener::MakeFlat(Double_t oldPhi,Double_t centrality)const
{
  //Apply flattening using existing parameterizations
  if(fNCentrBins==0) return oldPhi; //No correction encoded

  Double_t result = oldPhi ;
  //Centrality bin
  Int_t icen=(Int_t) (centrality*fNCentrBins/100.) ;
  if(icen>=fNCentrBins)icen = fNCentrBins-1 ;

  //Offset in the array
  icen=icen*fNHarmonics ;

  for(Int_t i = 1; i<=fNHarmonics/2; i++){
    Double_t c = 1./i*fParam[icen+2*i-2] ;  //Mean cos(n*phi) for a given centrality
    Double_t s = 1./i*fParam[icen+2*i-1]; //Mean sin(n*phi) for a given centrality
    result += c*TMath::Sin(i*oldPhi)-s*TMath::Cos(i*oldPhi) ;
  }
  return result ;
}
//____________________________________________________________________________
void AliPHOSEPFlattener::SetParameterization(TH2 * h){
 //Fill parameterizations
 //We expect histogram with <cos(i*phi)>, <sin(i*phi)> with centrality bins in x axis
 //and harmonics: <cos(x)>, <sin(x)>, <cos(2x)>, <sin(2x)>, .... in y axis

  fNCentrBins = h->GetXaxis()->GetNbins() ;
  fNHarmonics = h->GetYaxis()->GetNbins() ;
  fNparam     = fNCentrBins*fNHarmonics ;
  if(fParam) delete [] fParam ;
  fParam = new Double32_t[fNparam] ;
  for(Int_t i=0; i<fNCentrBins; i++)
    for(Int_t j=0; j<fNHarmonics; j++)
      fParam[i*fNHarmonics+j]=h->GetBinContent(i+1,j+1) ;
}

<|endoftext|>


<commit_before>/*
 * Copyright 2015 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include <map>
#include <seastar/core/future.hh>
#include <seastar/core/future-util.hh>
#include <seastar/core/gate.hh>
#include <seastar/core/shared_future.hh>

#include "seastarx.hh"

namespace utils {

/*
 * Small utility to order func()->post() operation
 * so that the "post" step is guaranteed to only be run
 * when all func+post-ops for lower valued keys (T) are
 * completed.
 */
template<typename T, typename Comp = std::less<T>, typename Clock = steady_clock_type>
class flush_queue {
public:
    using timeout_clock = Clock;
    using time_point = typename timeout_clock::time_point;
    using promise_type = shared_promise<with_clock<timeout_clock>>;
private:
    // Lifting the restriction of a single "post"
    // per key; Use a "ref count" for each execution
    struct notifier {
        promise_type pr;
        size_t count = 0;
    };

    typedef std::map<T, notifier, Comp> map_type;
    typedef typename map_type::reverse_iterator reverse_iterator;
    typedef typename map_type::iterator iterator;

    map_type _map;
    // embed all ops in a seastar::gate as well
    // so we can effectively block incoming ops
    seastar::gate _gate;
    bool _chain_exceptions;

    template<typename Func, typename... Args>
    static auto call_helper(Func&& func, future<Args...> f) {
        using futurator = futurize<std::result_of_t<Func(Args&&...)>>;
        try {
            return futurator::apply(std::forward<Func>(func), f.get());
        } catch (...) {
            return futurator::make_exception_future(std::current_exception());
        }
    }
    template<typename... Types>
    static future<Types...> handle_failed_future(future<Types...> f, promise_type& pr) {
        assert(f.failed());
        auto ep = std::move(f).get_exception();
        pr.set_exception(ep);
        return make_exception_future<Types...>(ep);
    }
public:
    flush_queue(bool chain_exceptions = false)
        : _chain_exceptions(chain_exceptions)
    {}
    // we are repeatedly using lambdas with "this" captured.
    // allowing moving would not be wise.
    flush_queue(flush_queue&&) = delete;
    flush_queue(const flush_queue&) = delete;

    /*
     * Runs func() followed by post(), but guaranteeing that
     * all operations with lower <T> keys have completed before
     * post() is executed.
     *
     * Post is invoked on the return value of Func
     * Returns a future containing the result of post()
     *
     * Any exception from Func is forwarded to end result, but
     * in case of exception post is _not_ run.
     */
    template<typename Func, typename Post>
    auto run_with_ordered_post_op(T rp, Func&& func, Post&& post) {
        // Slightly eased restrictions: We allow inserting an element
        // if it is either larger than any existing one, or if it
        // already is in the map. If either condition is true we can
        // uphold the guarantee to enforce ordered "post" execution
        // and signalling of all larger elements.
        if (!_map.empty() && !_map.contains(rp) && rp < _map.rbegin()->first) {
            throw std::invalid_argument(format("Attempting to insert key out of order: {}", rp));
        }

        _gate.enter();
        _map[rp].count++;

        using futurator = futurize<std::result_of_t<Func()>>;

        return futurator::invoke(std::forward<Func>(func)).then_wrapped([this, rp, post = std::forward<Post>(post)](typename futurator::type f) mutable {
            auto i = _map.find(rp);
            assert(i != _map.end());

            using post_result = decltype(call_helper(std::forward<Post>(post), std::move(f)));

            auto run_post = [this, post = std::forward<Post>(post), f = std::move(f), i]() mutable {
                assert(i == _map.begin());
                return call_helper(std::forward<Post>(post), std::move(f)).then_wrapped([this, i](post_result f) {
                    if (--i->second.count == 0) {
                        auto pr = std::move(i->second.pr);
                        assert(i == _map.begin());
                        _map.erase(i);
                        if (f.failed() && _chain_exceptions) {
                            return handle_failed_future(std::move(f), pr);
                        } else {
                            pr.set_value();
                        }
                    }
                    return f;
                });
            };

            if (i == _map.begin()) {
                return run_post();
            }

            --i;

            return i->second.pr.get_shared_future().then(std::move(run_post));
        }).finally([this] {
            // note: would have liked to use "with_gate", but compiler fails to
            // infer return type then, since we use "auto" because of future
            // chaining
            _gate.leave();
        });
    }
private:
    // waits for the entry at "i" to complete (and thus all before it)
    future<> wait_for_pending(reverse_iterator i, time_point timeout = time_point::max()) {
        if (i == _map.rend()) {
            return make_ready_future<>();
        }
        return i->second.pr.get_shared_future(timeout);
    }
public:
    // Waits for all operations currently active to finish
    future<> wait_for_pending(time_point timeout = time_point::max()) {
        return wait_for_pending(_map.rbegin(), timeout);
    }
    // Waits for all operations whose key is less than or equal to "rp"
    // to complete
    future<> wait_for_pending(T rp, time_point timeout = time_point::max()) {
        auto i = _map.upper_bound(rp);
        return wait_for_pending(reverse_iterator(i), timeout);
    }
    bool empty() const {
        return _map.empty();
    }
    size_t size() const {
        return _map.size();
    }
    bool has_operation(T rp) const {
        return _map.contains(rp);
    }
    T highest_key() const {
        return _map.rbegin()->first;
    }
    // Closes this queue
    future<> close() {
        return _gate.close();
    }
};

}
<commit_msg>flush_queue: use futurator::invoke<commit_after>/*
 * Copyright 2015 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include <map>
#include <seastar/core/future.hh>
#include <seastar/core/future-util.hh>
#include <seastar/core/gate.hh>
#include <seastar/core/shared_future.hh>

#include "seastarx.hh"

namespace utils {

/*
 * Small utility to order func()->post() operation
 * so that the "post" step is guaranteed to only be run
 * when all func+post-ops for lower valued keys (T) are
 * completed.
 */
template<typename T, typename Comp = std::less<T>, typename Clock = steady_clock_type>
class flush_queue {
public:
    using timeout_clock = Clock;
    using time_point = typename timeout_clock::time_point;
    using promise_type = shared_promise<with_clock<timeout_clock>>;
private:
    // Lifting the restriction of a single "post"
    // per key; Use a "ref count" for each execution
    struct notifier {
        promise_type pr;
        size_t count = 0;
    };

    typedef std::map<T, notifier, Comp> map_type;
    typedef typename map_type::reverse_iterator reverse_iterator;
    typedef typename map_type::iterator iterator;

    map_type _map;
    // embed all ops in a seastar::gate as well
    // so we can effectively block incoming ops
    seastar::gate _gate;
    bool _chain_exceptions;

    template<typename Func, typename... Args>
    static auto call_helper(Func&& func, future<Args...> f) {
        using futurator = futurize<std::result_of_t<Func(Args&&...)>>;
        try {
            return futurator::invoke(std::forward<Func>(func), f.get());
        } catch (...) {
            return futurator::make_exception_future(std::current_exception());
        }
    }
    template<typename... Types>
    static future<Types...> handle_failed_future(future<Types...> f, promise_type& pr) {
        assert(f.failed());
        auto ep = std::move(f).get_exception();
        pr.set_exception(ep);
        return make_exception_future<Types...>(ep);
    }
public:
    flush_queue(bool chain_exceptions = false)
        : _chain_exceptions(chain_exceptions)
    {}
    // we are repeatedly using lambdas with "this" captured.
    // allowing moving would not be wise.
    flush_queue(flush_queue&&) = delete;
    flush_queue(const flush_queue&) = delete;

    /*
     * Runs func() followed by post(), but guaranteeing that
     * all operations with lower <T> keys have completed before
     * post() is executed.
     *
     * Post is invoked on the return value of Func
     * Returns a future containing the result of post()
     *
     * Any exception from Func is forwarded to end result, but
     * in case of exception post is _not_ run.
     */
    template<typename Func, typename Post>
    auto run_with_ordered_post_op(T rp, Func&& func, Post&& post) {
        // Slightly eased restrictions: We allow inserting an element
        // if it is either larger than any existing one, or if it
        // already is in the map. If either condition is true we can
        // uphold the guarantee to enforce ordered "post" execution
        // and signalling of all larger elements.
        if (!_map.empty() && !_map.contains(rp) && rp < _map.rbegin()->first) {
            throw std::invalid_argument(format("Attempting to insert key out of order: {}", rp));
        }

        _gate.enter();
        _map[rp].count++;

        using futurator = futurize<std::result_of_t<Func()>>;

        return futurator::invoke(std::forward<Func>(func)).then_wrapped([this, rp, post = std::forward<Post>(post)](typename futurator::type f) mutable {
            auto i = _map.find(rp);
            assert(i != _map.end());

            using post_result = decltype(call_helper(std::forward<Post>(post), std::move(f)));

            auto run_post = [this, post = std::forward<Post>(post), f = std::move(f), i]() mutable {
                assert(i == _map.begin());
                return call_helper(std::forward<Post>(post), std::move(f)).then_wrapped([this, i](post_result f) {
                    if (--i->second.count == 0) {
                        auto pr = std::move(i->second.pr);
                        assert(i == _map.begin());
                        _map.erase(i);
                        if (f.failed() && _chain_exceptions) {
                            return handle_failed_future(std::move(f), pr);
                        } else {
                            pr.set_value();
                        }
                    }
                    return f;
                });
            };

            if (i == _map.begin()) {
                return run_post();
            }

            --i;

            return i->second.pr.get_shared_future().then(std::move(run_post));
        }).finally([this] {
            // note: would have liked to use "with_gate", but compiler fails to
            // infer return type then, since we use "auto" because of future
            // chaining
            _gate.leave();
        });
    }
private:
    // waits for the entry at "i" to complete (and thus all before it)
    future<> wait_for_pending(reverse_iterator i, time_point timeout = time_point::max()) {
        if (i == _map.rend()) {
            return make_ready_future<>();
        }
        return i->second.pr.get_shared_future(timeout);
    }
public:
    // Waits for all operations currently active to finish
    future<> wait_for_pending(time_point timeout = time_point::max()) {
        return wait_for_pending(_map.rbegin(), timeout);
    }
    // Waits for all operations whose key is less than or equal to "rp"
    // to complete
    future<> wait_for_pending(T rp, time_point timeout = time_point::max()) {
        auto i = _map.upper_bound(rp);
        return wait_for_pending(reverse_iterator(i), timeout);
    }
    bool empty() const {
        return _map.empty();
    }
    size_t size() const {
        return _map.size();
    }
    bool has_operation(T rp) const {
        return _map.contains(rp);
    }
    T highest_key() const {
        return _map.rbegin()->first;
    }
    // Closes this queue
    future<> close() {
        return _gate.close();
    }
};

}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dqs_align_workarounds.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2017,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

#include <fapi2.H>
#include <lib/workarounds/dqs_align_workarounds.H>
#include <lib/phy/seq.H>
#include <lib/phy/phy_cntrl.H>

namespace mss
{

namespace workarounds
{

namespace dqs_align
{

///
/// @brief Sets tRFC cyles for sequencer
/// @param[in] i_target the fapi2 target of the port
/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
///
fapi2::ReturnCode set_timing0_trfc(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target)
{
    // May need to add freq/tRFI attr dependency later but for now use this value
    // Provided by Ryan King
    constexpr size_t TRFC_CYCLES = 9;

    fapi2::buffer<uint64_t> l_data;
    FAPI_TRY( mss::seq::read_timing0(i_target, l_data) );

    mss::seq::set_trfc_cycles(l_data, TRFC_CYCLES);
    FAPI_TRY( mss::seq::write_timing0(i_target, l_data) );

fapi_try_exit:
    return fapi2::current_err;
}

///
/// @brief Set PHY sequencer to trigger refresh during init cal
/// @param[in] i_target the fapi2 target of the port
/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
///
fapi2::ReturnCode set_init_cal_refresh(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target)
{
    // Hard coded settings provided by Ryan King for this workaround
    constexpr size_t REF_COUNT = 0xF;
    constexpr size_t REF_CNTL = 0b11;
    constexpr size_t REF_INTERVAL = 0b0010011;

    fapi2::buffer<uint64_t> l_data;
    FAPI_TRY( mss::pc::read_init_cal_config1(i_target, l_data) );

    mss::pc::set_refresh_count(l_data, REF_COUNT);
    mss::pc::set_refresh_control(l_data, REF_CNTL);
    mss::pc::set_refresh_all_ranks(l_data, mss::HIGH);
    mss::pc::set_snoop_dis(l_data, mss::LOW);
    mss::pc::set_refresh_interval(l_data, REF_INTERVAL);

    FAPI_TRY( mss::pc::write_init_cal_config1(i_target, l_data) )

fapi_try_exit:
    return fapi2::current_err;
}

///
/// @brief Set PHY sequencer to trigger refresh during init cal
/// @param[in] i_target the fapi2 target of the port
/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
///
fapi2::ReturnCode refresh(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target)
{
    uint8_t l_attr = 0;
    FAPI_TRY( mss::phy_seq_refresh(i_target, l_attr) );

    if( l_attr == fapi2::ENUM_ATTR_MSS_PHY_SEQ_REFRESH_DISABLE )
    {
        FAPI_INF("Skipping workaround to trigger refresh for the PHY sequencer %s", mss::c_str(i_target));
        return fapi2::FAPI2_RC_SUCCESS;
    }

    FAPI_TRY( set_timing0_trfc(i_target),
              "set_timing0_trfc() failed for %s", mss::c_str(i_target) );

    FAPI_TRY( set_init_cal_refresh(i_target),
              "set_init_cal_refresh() failed for %s", mss::c_str(i_target) );

fapi_try_exit:
    return fapi2::current_err;
}

}
}
}
<commit_msg>Turn off PHY refresh for RD_CNTR - RD_VREF<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dqs_align_workarounds.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2017,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

#include <fapi2.H>
#include <lib/workarounds/dqs_align_workarounds.H>
#include <p9_mc_scom_addresses.H>
#include <mss_attribute_accessors.H>
#include <lib/phy/seq.H>
#include <lib/phy/phy_cntrl.H>

namespace mss
{

namespace workarounds
{

namespace dqs_align
{

///
/// @brief Sets tRFC cyles for sequencer
/// @param[in] i_target the fapi2 target of the port
/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
///
fapi2::ReturnCode set_timing0_trfc(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target)
{
    // May need to add freq/tRFI attr dependency later but for now use this value
    // Provided by Ryan King
    constexpr size_t TRFC_CYCLES = 9;

    fapi2::buffer<uint64_t> l_data;
    FAPI_TRY( mss::seq::read_timing0(i_target, l_data) );

    mss::seq::set_trfc_cycles(l_data, TRFC_CYCLES);
    FAPI_TRY( mss::seq::write_timing0(i_target, l_data) );

fapi_try_exit:
    return fapi2::current_err;
}

///
/// @brief Set PHY sequencer to trigger refresh during init cal
/// @param[in] i_target the fapi2 target of the port
/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
///
fapi2::ReturnCode set_init_cal_refresh(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target)
{
    // Hard coded settings provided by Ryan King for this workaround
    constexpr size_t REF_COUNT = 0xF;
    constexpr size_t REF_CNTL = 0b11;
    constexpr size_t REF_INTERVAL = 0b0010011;

    fapi2::buffer<uint64_t> l_data;
    FAPI_TRY( mss::pc::read_init_cal_config1(i_target, l_data) );

    mss::pc::set_refresh_count(l_data, REF_COUNT);
    mss::pc::set_refresh_control(l_data, REF_CNTL);
    mss::pc::set_refresh_all_ranks(l_data, mss::HIGH);
    mss::pc::set_snoop_dis(l_data, mss::LOW);
    mss::pc::set_refresh_interval(l_data, REF_INTERVAL);

    FAPI_TRY( mss::pc::write_init_cal_config1(i_target, l_data) )

fapi_try_exit:
    return fapi2::current_err;
}

///
/// @brief Clear the PHY sequencer refresh
/// @param[in] i_target the fapi2 target of the port
/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
///
fapi2::ReturnCode clear_init_cal_refresh(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target)
{
    // Turns off refresh
    constexpr size_t REF_CNTL = 0b00;

    fapi2::buffer<uint64_t> l_data;
    FAPI_TRY( mss::pc::read_init_cal_config1(i_target, l_data) );

    mss::pc::set_refresh_control(l_data, REF_CNTL);

    FAPI_TRY( mss::pc::write_init_cal_config1(i_target, l_data) )

fapi_try_exit:
    return fapi2::current_err;
}

///
/// @brief Set PHY sequencer to trigger refresh during init cal
/// @param[in] i_target the fapi2 target of the port
/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
///
fapi2::ReturnCode turn_on_refresh(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target)
{
    uint8_t l_attr = 0;
    FAPI_TRY( mss::phy_seq_refresh(i_target, l_attr) );

    if( l_attr == fapi2::ENUM_ATTR_MSS_PHY_SEQ_REFRESH_DISABLE )
    {
        FAPI_INF("Skipping workaround to trigger refresh for the PHY sequencer %s", mss::c_str(i_target));
        return fapi2::FAPI2_RC_SUCCESS;
    }

    FAPI_TRY( set_timing0_trfc(i_target),
              "set_timing0_trfc() failed for %s", mss::c_str(i_target) );

    FAPI_TRY( set_init_cal_refresh(i_target),
              "set_init_cal_refresh() failed for %s", mss::c_str(i_target) );

fapi_try_exit:
    return fapi2::current_err;
}

///
/// @brief Turn off refresh after dqs training has been run
/// @param[in] i_target the fapi2 target of the port
/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
///
fapi2::ReturnCode turn_off_refresh(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target)
{
    uint8_t l_attr = 0;
    FAPI_TRY( mss::phy_seq_refresh(i_target, l_attr) );

    if( l_attr == fapi2::ENUM_ATTR_MSS_PHY_SEQ_REFRESH_DISABLE )
    {
        FAPI_INF("Refresh for PHY sequencer is already off %s", mss::c_str(i_target));
        return fapi2::FAPI2_RC_SUCCESS;
    }

    FAPI_TRY( clear_init_cal_refresh(i_target),
              "set_init_cal_refresh() failed for %s", mss::c_str(i_target) );

fapi_try_exit:
    return fapi2::current_err;
}

}
}
}
<|endoftext|>


<commit_before>// For conditions of distribution and use, see copyright notice in license.txt
// Based on Mesmerizer.cs in libopenmetaverse

/*
 * Copyright (c) 2008, openmetaverse.org
 * All rights reserved.
 *
 * - Redistribution and use in source and binary forms, with or without
 *   modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 * - Neither the name of the openmetaverse.org nor the names
 *   of its contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 *
 * This code comes from the OpenSim project. Meshmerizer is written by dahlia
 * <dahliatrimble@gmail.com>
 */

#include "StableHeaders.h"
#include "Environment/PrimGeometryUtils.h"
#include "Environment/PrimMesher.h"
#include "RexTypes.h"
#include "RexLogicModule.h"
#include "OgreMaterialUtils.h"
#include "OgreMaterialResource.h"
#include "Renderer.h"
#include "ServiceManager.h"
#include "CoreException.h"
#include "EC_OpenSimPrim.h"

#ifndef unix
#include <float.h>
#else
#include "CoreTypes.h"
#endif

#include <Ogre.h>

namespace RexLogic
{
    static Ogre::ManualObject* prim_manual_object = 0;

    void TransformUV(Ogre::Vector2& uv, float repeat_u, float repeat_v, float offset_u, float offset_v, float rot_sin, float rot_cos)
    {
        const static Ogre::Vector2 half(0.5f, 0.5f);

        Ogre::Vector2 centered = uv - half;

        uv.x = centered.y * rot_sin + centered.x * rot_cos;
        uv.y = -centered.x * rot_sin + centered.y * rot_cos;

        uv.x *= repeat_u;
        uv.y *= repeat_v;

        uv.x += offset_u;
        uv.y -= offset_v;

        uv += half;
    }

    bool CheckCoord(const PrimMesher::Coord& pos)
    {
        if (_isnan(pos.X) || _isnan(pos.Y) || _isnan(pos.Z))
            return false;
        if (!_finite(pos.X) || !_finite(pos.Y) || !_finite(pos.Z))
            return false;

        return true;
    }

    Ogre::ManualObject* CreatePrimGeometry(Foundation::Framework* framework, EC_OpenSimPrim& primitive, bool optimisations_enabled)
    {
        PROFILE(Primitive_CreateGeometry)

        if (!primitive.HasPrimShapeData)
            return 0;

        // Create only a single manual object for prim geometry and reuse it over and over, to avoid Ogre generating
        // a huge load of unnecessary D3D resources, that are never used for anything visible (the manual object will
        // be converted to a mesh anyway)
        if (!prim_manual_object)
        {
            OgreRenderer::RendererPtr renderer = framework->GetServiceManager()->GetService<OgreRenderer::Renderer>(Foundation::Service::ST_Renderer).lock();
            if (!renderer)
                return 0;
            Ogre::SceneManager *sceneMgr = renderer->GetSceneManager();
            prim_manual_object = sceneMgr->createManualObject(renderer->GetUniqueObjectName());
            if (!prim_manual_object)
                return 0;
        }

        std::string mat_override;
        if ((primitive.Materials[0].Type == RexTypes::RexAT_MaterialScript) && (!RexTypes::IsNull(primitive.Materials[0].asset_id)))
        {
            mat_override = primitive.Materials[0].asset_id;

            // If cannot find the override material, use default
            // We will probably get resource ready event later for the material & redo this prim
            boost::shared_ptr<OgreRenderer::Renderer> renderer = framework->GetServiceManager()->
                GetService<OgreRenderer::Renderer>(Foundation::Service::ST_Renderer).lock();
            if (!renderer->GetResource(mat_override, OgreRenderer::OgreMaterialResource::GetTypeStatic()))
            {
                mat_override = "LitTextured";
            }
        }

        try
        {
            float profileBegin = primitive.ProfileBegin.Get();
            float profileEnd = 1.0f - primitive.ProfileEnd.Get();
            float profileHollow = primitive.ProfileHollow.Get();

            int sides = 4;
            if ((primitive.ProfileCurve.Get() & 0x07) == RexTypes::SHAPE_EQUILATERAL_TRIANGLE)
                sides = 3;
            else if ((primitive.ProfileCurve.Get() & 0x07) == RexTypes::SHAPE_CIRCLE)
                // Reduced prim lod!!!
                sides = 12;
                //sides = 24;
            else if ((primitive.ProfileCurve.Get() & 0x07) == RexTypes::SHAPE_HALF_CIRCLE)
            {
                // half circle, prim is a sphere
                // Reduced prim lod!!!
                sides = 12;
                //sides = 24;

                profileBegin = 0.5f * profileBegin + 0.5f;
                profileEnd = 0.5f * profileEnd + 0.5f;
            }

            int hollowSides = sides;
            if ((primitive.ProfileCurve.Get() & 0xf0) == RexTypes::HOLLOW_CIRCLE)
                // Reduced prim lod!!!
                hollowSides = 12;
                //hollowSides = 24;
            else if ((primitive.ProfileCurve.Get() & 0xf0) == RexTypes::HOLLOW_SQUARE)
                hollowSides = 4;
            else if ((primitive.ProfileCurve.Get() & 0xf0) == RexTypes::HOLLOW_TRIANGLE)
                hollowSides = 3;

            PrimMesher::PrimMesh primMesh(sides, profileBegin, profileEnd, profileHollow, hollowSides);
            primMesh.topShearX = primitive.PathShearX.Get();
            primMesh.topShearY = primitive.PathShearY.Get();
            primMesh.pathCutBegin = primitive.PathBegin.Get();
            primMesh.pathCutEnd = 1.0f - primitive.PathEnd.Get();

            if (primitive.PathCurve.Get() == RexTypes::EXTRUSION_STRAIGHT)
            {
                primMesh.twistBegin = primitive.PathTwistBegin.Get() * 180;
                primMesh.twistEnd = primitive.PathTwist.Get() * 180;
                primMesh.taperX = primitive.PathScaleX.Get() - 1.0f;
                primMesh.taperY = primitive.PathScaleY.Get() - 1.0f;
                primMesh.ExtrudeLinear();
            }
            else
            {
                primMesh.holeSizeX = (2.0f - primitive.PathScaleX.Get());
                primMesh.holeSizeY = (2.0f - primitive.PathScaleY.Get());
                primMesh.radius = primitive.PathRadiusOffset.Get();
                primMesh.revolutions = primitive.PathRevolutions.Get();
                primMesh.skew = primitive.PathSkew.Get();
                primMesh.twistBegin = primitive.PathTwistBegin.Get() * 360;
                primMesh.twistEnd = primitive.PathTwist.Get() * 360;
                primMesh.taperX = primitive.PathTaperX.Get();
                primMesh.taperY = primitive.PathTaperY.Get();
                primMesh.ExtrudeCircular();
            }

            PROFILE(Primitive_CreateManualObject)
            prim_manual_object->clear();
            prim_manual_object->setBoundingBox(Ogre::AxisAlignedBox());

            // Check for highly illegal coordinates in any of the faces
            for (int i = 0; i < primMesh.viewerFaces.size(); ++i)
            {
                if (!(CheckCoord(primMesh.viewerFaces[i].v1) && CheckCoord(primMesh.viewerFaces[i].v2) && CheckCoord(primMesh.viewerFaces[i].v3)))
                {
                    RexLogicModule::LogError("NaN or infinite number encountered in prim face coordinates. Skipping geometry creation.");
                    return 0;
                }
            }

            std::string mat_name;
            std::string prev_mat_name;

            uint indices = 0;
            bool first_face = true;

            for (int i = 0; i < primMesh.viewerFaces.size(); ++i)
            {
                int facenum = primMesh.viewerFaces[i].primFaceNumber;

                Color color = primitive.PrimDefaultColor;
                ColorMap::const_iterator c = primitive.PrimColors.find(facenum);
                if (c != primitive.PrimColors.end())
                    color = c->second;

                // Skip face if very transparent
                if (color.a <= 0.11f)
                    continue;

                if (!mat_override.empty())
                    mat_name = mat_override;
                else
                {
                    unsigned variation = OgreRenderer::LEGACYMAT_VERTEXCOL;

                    // Check for transparency
                    if (color.a < 1.0f)
                        variation = OgreRenderer::LEGACYMAT_VERTEXCOLALPHA;

                    // Check for fullbright
                    bool fullbright = (primitive.PrimDefaultMaterialType & RexTypes::MATERIALTYPE_FULLBRIGHT) != 0;
                    MaterialTypeMap::const_iterator mt = primitive.PrimMaterialTypes.find(facenum);
                    if (mt != primitive.PrimMaterialTypes.end())
                        fullbright = (mt->second & RexTypes::MATERIALTYPE_FULLBRIGHT) != 0;
                    if (fullbright)
                        variation |= OgreRenderer::LEGACYMAT_FULLBRIGHT;

                    std::string suffix = OgreRenderer::GetMaterialSuffix(variation);

                    // Try to find face's texture in texturemap, use default if not found
                    std::string texture_name = primitive.PrimDefaultTextureID;
                    TextureMap::const_iterator t = primitive.PrimTextures.find(facenum);
                    if (t != primitive.PrimTextures.end())
                        texture_name = t->second;

                    mat_name = texture_name + suffix;

                    // Create the material here if texture yet missing, the material will be updated later
                    OgreRenderer::GetOrCreateLegacyMaterial(texture_name, variation);
                }

                // Get texture mapping parameters
                float repeat_u = primitive.PrimDefaultRepeatU;
                float repeat_v = primitive.PrimDefaultRepeatV;
                float offset_u = primitive.PrimDefaultOffsetU;
                float offset_v = primitive.PrimDefaultOffsetV;
                float rot = primitive.PrimDefaultUVRotation;
                if (primitive.PrimRepeatU.find(facenum) != primitive.PrimRepeatU.end())
                    repeat_u = primitive.PrimRepeatU[facenum];
                if (primitive.PrimRepeatV.find(facenum) != primitive.PrimRepeatV.end())
                    repeat_v = primitive.PrimRepeatV[facenum];
                if (primitive.PrimOffsetU.find(facenum) != primitive.PrimOffsetU.end())
                    offset_u = primitive.PrimOffsetU[facenum];
                if (primitive.PrimOffsetV.find(facenum) != primitive.PrimOffsetV.end())
                    offset_v = primitive.PrimOffsetV[facenum];
                if (primitive.PrimUVRotation.find(facenum) != primitive.PrimUVRotation.end())
                    rot = primitive.PrimUVRotation[facenum];
                float rot_sin = sin(-rot);
                float rot_cos = cos(-rot);

                if (optimisations_enabled || primitive.DrawType == RexTypes::DRAWTYPE_MESH)
                {
                    if ((first_face) || (mat_name != prev_mat_name))
                    {
                        if (indices)
                            prim_manual_object->end();
                        indices = 0;
                        prim_manual_object->begin(mat_name, Ogre::RenderOperation::OT_TRIANGLE_LIST);
                        prev_mat_name = mat_name;
                        first_face = false;
                    }
                }
                else
                {
                    if (facenum != 0 && i % 2 == 0)
                    {
                        if (indices)
                            prim_manual_object->end();
                        indices = 0;
                        prim_manual_object->begin(mat_name, Ogre::RenderOperation::OT_TRIANGLE_LIST);
                    }
                }

                Ogre::Vector3 pos1(primMesh.viewerFaces[i].v1.X, primMesh.viewerFaces[i].v1.Y, primMesh.viewerFaces[i].v1.Z);
                Ogre::Vector3 pos2(primMesh.viewerFaces[i].v2.X, primMesh.viewerFaces[i].v2.Y, primMesh.viewerFaces[i].v2.Z);
                Ogre::Vector3 pos3(primMesh.viewerFaces[i].v3.X, primMesh.viewerFaces[i].v3.Y, primMesh.viewerFaces[i].v3.Z);

                Ogre::Vector3 n1(primMesh.viewerFaces[i].n1.X, primMesh.viewerFaces[i].n1.Y, primMesh.viewerFaces[i].n1.Z);
                Ogre::Vector3 n2(primMesh.viewerFaces[i].n2.X, primMesh.viewerFaces[i].n2.Y, primMesh.viewerFaces[i].n2.Z);
                Ogre::Vector3 n3(primMesh.viewerFaces[i].n3.X, primMesh.viewerFaces[i].n3.Y, primMesh.viewerFaces[i].n3.Z);

                Ogre::Vector2 uv1(primMesh.viewerFaces[i].uv1.U, primMesh.viewerFaces[i].uv1.V);
                Ogre::Vector2 uv2(primMesh.viewerFaces[i].uv2.U, primMesh.viewerFaces[i].uv2.V);
                Ogre::Vector2 uv3(primMesh.viewerFaces[i].uv3.U, primMesh.viewerFaces[i].uv3.V);

                TransformUV(uv1, repeat_u, repeat_v, offset_u, offset_v, rot_sin, rot_cos);
                TransformUV(uv2, repeat_u, repeat_v, offset_u, offset_v, rot_sin, rot_cos);
                TransformUV(uv3, repeat_u, repeat_v, offset_u, offset_v, rot_sin, rot_cos);

                prim_manual_object->position(pos1);
                prim_manual_object->normal(n1);
                prim_manual_object->textureCoord(uv1);
                prim_manual_object->colour(color.r, color.g, color.b, color.a);

                prim_manual_object->position(pos2);
                prim_manual_object->normal(n2);
                prim_manual_object->textureCoord(uv2);
                prim_manual_object->colour(color.r, color.g, color.b, color.a);

                prim_manual_object->position(pos3);
                prim_manual_object->normal(n3);
                prim_manual_object->textureCoord(uv3);
                prim_manual_object->colour(color.r, color.g, color.b, color.a);

                prim_manual_object->index(indices++);
                prim_manual_object->index(indices++);
                prim_manual_object->index(indices++);
            }

            // End last subsection
            if (indices)
                prim_manual_object->end();
        }
        catch (Exception& e)
        {
            RexLogicModule::LogError(std::string("Exception while creating primitive geometry: ") + e.what());
            return 0;
        }

        return prim_manual_object;
    }
}<commit_msg>fix mediaurl-related crash<commit_after>// For conditions of distribution and use, see copyright notice in license.txt
// Based on Mesmerizer.cs in libopenmetaverse

/*
 * Copyright (c) 2008, openmetaverse.org
 * All rights reserved.
 *
 * - Redistribution and use in source and binary forms, with or without
 *   modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 * - Neither the name of the openmetaverse.org nor the names
 *   of its contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 *
 * This code comes from the OpenSim project. Meshmerizer is written by dahlia
 * <dahliatrimble@gmail.com>
 */

#include "StableHeaders.h"
#include "Environment/PrimGeometryUtils.h"
#include "Environment/PrimMesher.h"
#include "RexTypes.h"
#include "RexLogicModule.h"
#include "OgreMaterialUtils.h"
#include "OgreMaterialResource.h"
#include "Renderer.h"
#include "ServiceManager.h"
#include "CoreException.h"
#include "EC_OpenSimPrim.h"

#ifndef unix
#include <float.h>
#else
#include "CoreTypes.h"
#endif

#include <Ogre.h>

namespace RexLogic
{
    static Ogre::ManualObject* prim_manual_object = 0;

    void TransformUV(Ogre::Vector2& uv, float repeat_u, float repeat_v, float offset_u, float offset_v, float rot_sin, float rot_cos)
    {
        const static Ogre::Vector2 half(0.5f, 0.5f);

        Ogre::Vector2 centered = uv - half;

        uv.x = centered.y * rot_sin + centered.x * rot_cos;
        uv.y = -centered.x * rot_sin + centered.y * rot_cos;

        uv.x *= repeat_u;
        uv.y *= repeat_v;

        uv.x += offset_u;
        uv.y -= offset_v;

        uv += half;
    }

    bool CheckCoord(const PrimMesher::Coord& pos)
    {
        if (_isnan(pos.X) || _isnan(pos.Y) || _isnan(pos.Z))
            return false;
        if (!_finite(pos.X) || !_finite(pos.Y) || !_finite(pos.Z))
            return false;

        return true;
    }

    Ogre::ManualObject* CreatePrimGeometry(Foundation::Framework* framework, EC_OpenSimPrim& primitive, bool optimisations_enabled)
    {
        PROFILE(Primitive_CreateGeometry)

        if (!primitive.HasPrimShapeData)
            return 0;

        // Create only a single manual object for prim geometry and reuse it over and over, to avoid Ogre generating
        // a huge load of unnecessary D3D resources, that are never used for anything visible (the manual object will
        // be converted to a mesh anyway)
        if (!prim_manual_object)
        {
            OgreRenderer::RendererPtr renderer = framework->GetServiceManager()->GetService<OgreRenderer::Renderer>(Foundation::Service::ST_Renderer).lock();
            if (!renderer)
                return 0;
            Ogre::SceneManager *sceneMgr = renderer->GetSceneManager();
            prim_manual_object = sceneMgr->createManualObject(renderer->GetUniqueObjectName());
            if (!prim_manual_object)
                return 0;
        }

        std::string mat_override;
        if ((primitive.Materials[0].Type == RexTypes::RexAT_MaterialScript) && (!RexTypes::IsNull(primitive.Materials[0].asset_id)))
        {
            mat_override = primitive.Materials[0].asset_id;

            // If cannot find the override material, use default
            // We will probably get resource ready event later for the material & redo this prim
            boost::shared_ptr<OgreRenderer::Renderer> renderer = framework->GetServiceManager()->
                GetService<OgreRenderer::Renderer>(Foundation::Service::ST_Renderer).lock();
            if (!renderer->GetResource(mat_override, OgreRenderer::OgreMaterialResource::GetTypeStatic()))
            {
                mat_override = "LitTextured";
            }
        }

        try
        {
            float profileBegin = primitive.ProfileBegin.Get();
            float profileEnd = 1.0f - primitive.ProfileEnd.Get();
            float profileHollow = primitive.ProfileHollow.Get();

            int sides = 4;
            if ((primitive.ProfileCurve.Get() & 0x07) == RexTypes::SHAPE_EQUILATERAL_TRIANGLE)
                sides = 3;
            else if ((primitive.ProfileCurve.Get() & 0x07) == RexTypes::SHAPE_CIRCLE)
                // Reduced prim lod!!!
                sides = 12;
                //sides = 24;
            else if ((primitive.ProfileCurve.Get() & 0x07) == RexTypes::SHAPE_HALF_CIRCLE)
            {
                // half circle, prim is a sphere
                // Reduced prim lod!!!
                sides = 12;
                //sides = 24;

                profileBegin = 0.5f * profileBegin + 0.5f;
                profileEnd = 0.5f * profileEnd + 0.5f;
            }

            int hollowSides = sides;
            if ((primitive.ProfileCurve.Get() & 0xf0) == RexTypes::HOLLOW_CIRCLE)
                // Reduced prim lod!!!
                hollowSides = 12;
                //hollowSides = 24;
            else if ((primitive.ProfileCurve.Get() & 0xf0) == RexTypes::HOLLOW_SQUARE)
                hollowSides = 4;
            else if ((primitive.ProfileCurve.Get() & 0xf0) == RexTypes::HOLLOW_TRIANGLE)
                hollowSides = 3;

            PrimMesher::PrimMesh primMesh(sides, profileBegin, profileEnd, profileHollow, hollowSides);
            primMesh.topShearX = primitive.PathShearX.Get();
            primMesh.topShearY = primitive.PathShearY.Get();
            primMesh.pathCutBegin = primitive.PathBegin.Get();
            primMesh.pathCutEnd = 1.0f - primitive.PathEnd.Get();

            if (primitive.PathCurve.Get() == RexTypes::EXTRUSION_STRAIGHT)
            {
                primMesh.twistBegin = primitive.PathTwistBegin.Get() * 180;
                primMesh.twistEnd = primitive.PathTwist.Get() * 180;
                primMesh.taperX = primitive.PathScaleX.Get() - 1.0f;
                primMesh.taperY = primitive.PathScaleY.Get() - 1.0f;
                primMesh.ExtrudeLinear();
            }
            else
            {
                primMesh.holeSizeX = (2.0f - primitive.PathScaleX.Get());
                primMesh.holeSizeY = (2.0f - primitive.PathScaleY.Get());
                primMesh.radius = primitive.PathRadiusOffset.Get();
                primMesh.revolutions = primitive.PathRevolutions.Get();
                primMesh.skew = primitive.PathSkew.Get();
                primMesh.twistBegin = primitive.PathTwistBegin.Get() * 360;
                primMesh.twistEnd = primitive.PathTwist.Get() * 360;
                primMesh.taperX = primitive.PathTaperX.Get();
                primMesh.taperY = primitive.PathTaperY.Get();
                primMesh.ExtrudeCircular();
            }

            PROFILE(Primitive_CreateManualObject)
            prim_manual_object->clear();
            prim_manual_object->setBoundingBox(Ogre::AxisAlignedBox());

            // Check for highly illegal coordinates in any of the faces
            for (int i = 0; i < primMesh.viewerFaces.size(); ++i)
            {
                if (!(CheckCoord(primMesh.viewerFaces[i].v1) && CheckCoord(primMesh.viewerFaces[i].v2) && CheckCoord(primMesh.viewerFaces[i].v3)))
                {
                    RexLogicModule::LogError("NaN or infinite number encountered in prim face coordinates. Skipping geometry creation.");
                    return 0;
                }
            }

            std::string mat_name;
            std::string prev_mat_name;

            uint indices = 0;
            bool first_face = true;

            for (int i = 0; i < primMesh.viewerFaces.size(); ++i)
            {
                int facenum = primMesh.viewerFaces[i].primFaceNumber;

                Color color = primitive.PrimDefaultColor;
                ColorMap::const_iterator c = primitive.PrimColors.find(facenum);
                if (c != primitive.PrimColors.end())
                    color = c->second;

                // Skip face if very transparent
                if (color.a <= 0.11f)
                    continue;

                if (!mat_override.empty())
                    mat_name = mat_override;
                else
                {
                    unsigned variation = OgreRenderer::LEGACYMAT_VERTEXCOL;

                    // Check for transparency
                    if (color.a < 1.0f)
                        variation = OgreRenderer::LEGACYMAT_VERTEXCOLALPHA;

                    // Check for fullbright
                    bool fullbright = (primitive.PrimDefaultMaterialType & RexTypes::MATERIALTYPE_FULLBRIGHT) != 0;
                    MaterialTypeMap::const_iterator mt = primitive.PrimMaterialTypes.find(facenum);
                    if (mt != primitive.PrimMaterialTypes.end())
                        fullbright = (mt->second & RexTypes::MATERIALTYPE_FULLBRIGHT) != 0;
                    if (fullbright)
                        variation |= OgreRenderer::LEGACYMAT_FULLBRIGHT;

                    std::string suffix = OgreRenderer::GetMaterialSuffix(variation);

                    // Try to find face's texture in texturemap, use default if not found
                    std::string texture_name = primitive.PrimDefaultTextureID;
                    TextureMap::const_iterator t = primitive.PrimTextures.find(facenum);
                    if (t != primitive.PrimTextures.end())
                        texture_name = t->second;

                    mat_name = texture_name + suffix;

                    // Create the material here if texture yet missing, the material will be updated later
                    OgreRenderer::GetOrCreateLegacyMaterial(texture_name, variation);
                }

                // Get texture mapping parameters
                float repeat_u = primitive.PrimDefaultRepeatU;
                float repeat_v = primitive.PrimDefaultRepeatV;
                float offset_u = primitive.PrimDefaultOffsetU;
                float offset_v = primitive.PrimDefaultOffsetV;
                float rot = primitive.PrimDefaultUVRotation;
                if (primitive.PrimRepeatU.find(facenum) != primitive.PrimRepeatU.end())
                    repeat_u = primitive.PrimRepeatU[facenum];
                if (primitive.PrimRepeatV.find(facenum) != primitive.PrimRepeatV.end())
                    repeat_v = primitive.PrimRepeatV[facenum];
                if (primitive.PrimOffsetU.find(facenum) != primitive.PrimOffsetU.end())
                    offset_u = primitive.PrimOffsetU[facenum];
                if (primitive.PrimOffsetV.find(facenum) != primitive.PrimOffsetV.end())
                    offset_v = primitive.PrimOffsetV[facenum];
                if (primitive.PrimUVRotation.find(facenum) != primitive.PrimUVRotation.end())
                    rot = primitive.PrimUVRotation[facenum];
                float rot_sin = sin(-rot);
                float rot_cos = cos(-rot);

                if (optimisations_enabled || primitive.DrawType == RexTypes::DRAWTYPE_MESH)
                {
                    if ((first_face) || (mat_name != prev_mat_name))
                    {
                        if (indices)
                            prim_manual_object->end();
                        indices = 0;
                        prim_manual_object->begin(mat_name, Ogre::RenderOperation::OT_TRIANGLE_LIST);
                        prev_mat_name = mat_name;
                        first_face = false;
                    }
                }
                else
                {
                    if (i % 2 == 0)
                    {
                        if (indices)
                            prim_manual_object->end();
                        indices = 0;
                        prim_manual_object->begin(mat_name, Ogre::RenderOperation::OT_TRIANGLE_LIST);
                    }
                }

                Ogre::Vector3 pos1(primMesh.viewerFaces[i].v1.X, primMesh.viewerFaces[i].v1.Y, primMesh.viewerFaces[i].v1.Z);
                Ogre::Vector3 pos2(primMesh.viewerFaces[i].v2.X, primMesh.viewerFaces[i].v2.Y, primMesh.viewerFaces[i].v2.Z);
                Ogre::Vector3 pos3(primMesh.viewerFaces[i].v3.X, primMesh.viewerFaces[i].v3.Y, primMesh.viewerFaces[i].v3.Z);

                Ogre::Vector3 n1(primMesh.viewerFaces[i].n1.X, primMesh.viewerFaces[i].n1.Y, primMesh.viewerFaces[i].n1.Z);
                Ogre::Vector3 n2(primMesh.viewerFaces[i].n2.X, primMesh.viewerFaces[i].n2.Y, primMesh.viewerFaces[i].n2.Z);
                Ogre::Vector3 n3(primMesh.viewerFaces[i].n3.X, primMesh.viewerFaces[i].n3.Y, primMesh.viewerFaces[i].n3.Z);

                Ogre::Vector2 uv1(primMesh.viewerFaces[i].uv1.U, primMesh.viewerFaces[i].uv1.V);
                Ogre::Vector2 uv2(primMesh.viewerFaces[i].uv2.U, primMesh.viewerFaces[i].uv2.V);
                Ogre::Vector2 uv3(primMesh.viewerFaces[i].uv3.U, primMesh.viewerFaces[i].uv3.V);

                TransformUV(uv1, repeat_u, repeat_v, offset_u, offset_v, rot_sin, rot_cos);
                TransformUV(uv2, repeat_u, repeat_v, offset_u, offset_v, rot_sin, rot_cos);
                TransformUV(uv3, repeat_u, repeat_v, offset_u, offset_v, rot_sin, rot_cos);

                prim_manual_object->position(pos1);
                prim_manual_object->normal(n1);
                prim_manual_object->textureCoord(uv1);
                prim_manual_object->colour(color.r, color.g, color.b, color.a);

                prim_manual_object->position(pos2);
                prim_manual_object->normal(n2);
                prim_manual_object->textureCoord(uv2);
                prim_manual_object->colour(color.r, color.g, color.b, color.a);

                prim_manual_object->position(pos3);
                prim_manual_object->normal(n3);
                prim_manual_object->textureCoord(uv3);
                prim_manual_object->colour(color.r, color.g, color.b, color.a);

                prim_manual_object->index(indices++);
                prim_manual_object->index(indices++);
                prim_manual_object->index(indices++);
            }

            // End last subsection
            if (indices)
                prim_manual_object->end();
        }
        catch (Exception& e)
        {
            RexLogicModule::LogError(std::string("Exception while creating primitive geometry: ") + e.what());
            return 0;
        }

        return prim_manual_object;
    }
}
<|endoftext|>


<commit_before>#include "sdca/solver.h"
#include "test_util.h"

#include "sdca/utility/logging.cpp"

template <typename Data,
          typename Result,
          typename Context>
inline void
test_solver_multiclass_basic(
    const Result expected_accuracy,
    Context& ctx
  ) {
  ctx.criteria.epsilon = 64 * std::max(
    static_cast<double>(std::numeric_limits<Data>::epsilon()),
    static_cast<double>(std::numeric_limits<Result>::epsilon()));

  auto solver = sdca::make_solver(ctx);
  solver.solve();

  EXPECT_TRUE(ctx.status == sdca::solver_status::solved);

  const Result accuracy = ctx.train.evals.back().accuracy[0];
  if (accuracy != expected_accuracy) {
    std::printf("%s\n", ctx.to_string().c_str());
    std::printf("%s\n", ctx.status_string().c_str());
  }
  EXPECT_EQ(expected_accuracy, accuracy);
}

template <typename Data,
          typename Result,
          template <typename, typename> class Objective>
inline void
test_solver_multiclass_basic_feature_in(
    Objective<Data, Result>& objective,
    const std::vector<Data>& X,
    const std::vector<sdca::size_type>& Y,
    const Result expected_accuracy
  ) {
  sdca::size_type dn = X.size(), n = Y.size(), m = 2;
  sdca::size_type d = dn / n;
  std::vector<Data> W(d * m); // primal vars
  std::vector<Data> A(m * n); // dual vars

  // Use features
  auto ctx = sdca::make_context_multiclass(
    std::move(objective),
    d, n, &X[0], Y.begin(), &A[0], &W[0]);

  test_solver_multiclass_basic<Data>(expected_accuracy, ctx);

  // Kernel (Gram) matrix
  std::vector<Data> K(n * n);
  sdca::blas_int D = static_cast<sdca::blas_int>(d);
  sdca::blas_int N = static_cast<sdca::blas_int>(n);
  sdca::sdca_blas_gemm(N, N, D, &X[0], D, &X[0], D, &K[0], CblasTrans);

  // Warm restart - use the same dual variables as above
  auto ctx_warm = sdca::make_context_multiclass(
    std::move(ctx.objective),
    n, &K[0], Y.begin(), &A[0]);

  ctx_warm.criteria.eval_on_start = true;
  test_solver_multiclass_basic<Data>(expected_accuracy, ctx_warm);
  EXPECT_TRUE(ctx_warm.epoch == 0UL);

  // Zero the dual variables are train from scratch
  std::fill(A.begin(), A.end(), static_cast<Data>(0));
  auto ctx_ker = sdca::make_context_multiclass(
    std::move(ctx_warm.objective),
    n, &K[0], Y.begin(), &A[0]);

  ctx_ker.criteria.eval_on_start = true;
  test_solver_multiclass_basic<Data>(expected_accuracy, ctx_ker);
  EXPECT_TRUE(ctx_ker.epoch > 0UL);
}

template <typename Data,
          typename Result,
          template <typename, typename> class Objective>
inline void
test_solver_multiclass_basic(
    Objective<Data, Result> objective
  ) {
  sdca::size_type d = 3, n = 4;
  std::vector<Data> X(d * n); // features
  std::vector<sdca::size_type> Y(n); // labels

  // Last column is the offset (bias) feature
  X = {0, 0, 1,
       0, 1, 1,
       1, 0, 1,
       1, 1, 1};

  // OR
  Y = {0, 1, 1, 1};
  test_solver_multiclass_basic_feature_in(objective, X, Y, static_cast<Result>(1));

  // AND
  Y = {0, 0, 0, 1};
  test_solver_multiclass_basic_feature_in(objective, X, Y, static_cast<Result>(1));

  // XOR
  // Perturb the last point to break symmetry
  // (otherwise test fails due to (?) regularized bias term)
  Data eps = static_cast<Data>(0.15);
  X = {0, 0, 1,
       0, 1, 1,
       1, 0, 1,
       1 - eps, 1 - eps, 1};
  Y = {0, 1, 1, 0};
  test_solver_multiclass_basic_feature_in(objective, X, Y, static_cast<Result>(0.75));
}

template <typename Data,
          typename Result>
inline void
test_solver_multiclass_basic_all() {
  Result C = 4;
  test_solver_multiclass_basic(
    sdca::make_objective_l2_entropy_topk<Data, Result>(C));

  test_solver_multiclass_basic(
    sdca::make_objective_l2_hinge_topk<Data, Result>(C));
  test_solver_multiclass_basic(
    sdca::make_objective_l2_hinge_topk_smooth<Data, Result>(C));

  test_solver_multiclass_basic(
    sdca::make_objective_l2_topk_hinge<Data, Result>(C));
  test_solver_multiclass_basic(
    sdca::make_objective_l2_topk_hinge_smooth<Data, Result>(C));
}

TEST(SolverTest, multiclass_basic_problems_all_objectives) {
  sdca::logging::set_level(sdca::logging::level::warning);
  sdca::logging::set_format(sdca::logging::format::short_e);
  test_solver_multiclass_basic_all<float, float>();
  test_solver_multiclass_basic_all<float, double>();
  test_solver_multiclass_basic_all<double, float>();
  test_solver_multiclass_basic_all<double, double>();
}
<commit_msg>Fixed a typo<commit_after>#include "sdca/solver.h"
#include "test_util.h"

#include "sdca/utility/logging.cpp"

template <typename Data,
          typename Result,
          typename Context>
inline void
test_solver_multiclass_basic(
    const Result expected_accuracy,
    Context& ctx
  ) {
  ctx.criteria.epsilon = 64 * std::max(
    static_cast<double>(std::numeric_limits<Data>::epsilon()),
    static_cast<double>(std::numeric_limits<Result>::epsilon()));

  auto solver = sdca::make_solver(ctx);
  solver.solve();

  EXPECT_TRUE(ctx.status == sdca::solver_status::solved);

  const Result accuracy = ctx.train.evals.back().accuracy[0];
  if (accuracy != expected_accuracy) {
    std::printf("%s\n", ctx.to_string().c_str());
    std::printf("%s\n", ctx.status_string().c_str());
  }
  EXPECT_EQ(expected_accuracy, accuracy);
}

template <typename Data,
          typename Result,
          template <typename, typename> class Objective>
inline void
test_solver_multiclass_basic_feature_in(
    Objective<Data, Result>& objective,
    const std::vector<Data>& X,
    const std::vector<sdca::size_type>& Y,
    const Result expected_accuracy
  ) {
  sdca::size_type dn = X.size(), n = Y.size(), m = 2;
  sdca::size_type d = dn / n;
  std::vector<Data> W(d * m); // primal vars
  std::vector<Data> A(m * n); // dual vars

  // Use features
  auto ctx = sdca::make_context_multiclass(
    std::move(objective),
    d, n, &X[0], Y.begin(), &A[0], &W[0]);

  test_solver_multiclass_basic<Data>(expected_accuracy, ctx);

  // Kernel (Gram) matrix
  std::vector<Data> K(n * n);
  sdca::blas_int D = static_cast<sdca::blas_int>(d);
  sdca::blas_int N = static_cast<sdca::blas_int>(n);
  sdca::sdca_blas_gemm(N, N, D, &X[0], D, &X[0], D, &K[0], CblasTrans);

  // Warm restart - use the same dual variables as above
  auto ctx_warm = sdca::make_context_multiclass(
    std::move(ctx.objective),
    n, &K[0], Y.begin(), &A[0]);

  ctx_warm.criteria.eval_on_start = true;
  test_solver_multiclass_basic<Data>(expected_accuracy, ctx_warm);
  EXPECT_TRUE(ctx_warm.epoch == 0UL);

  // Zero the dual variables and train from scratch
  std::fill(A.begin(), A.end(), static_cast<Data>(0));
  auto ctx_ker = sdca::make_context_multiclass(
    std::move(ctx_warm.objective),
    n, &K[0], Y.begin(), &A[0]);

  ctx_ker.criteria.eval_on_start = true;
  test_solver_multiclass_basic<Data>(expected_accuracy, ctx_ker);
  EXPECT_TRUE(ctx_ker.epoch > 0UL);
}

template <typename Data,
          typename Result,
          template <typename, typename> class Objective>
inline void
test_solver_multiclass_basic(
    Objective<Data, Result> objective
  ) {
  sdca::size_type d = 3, n = 4;
  std::vector<Data> X(d * n); // features
  std::vector<sdca::size_type> Y(n); // labels

  // Last column is the offset (bias) feature
  X = {0, 0, 1,
       0, 1, 1,
       1, 0, 1,
       1, 1, 1};

  // OR
  Y = {0, 1, 1, 1};
  test_solver_multiclass_basic_feature_in(objective, X, Y, static_cast<Result>(1));

  // AND
  Y = {0, 0, 0, 1};
  test_solver_multiclass_basic_feature_in(objective, X, Y, static_cast<Result>(1));

  // XOR
  // Perturb the last point to break symmetry
  // (otherwise test fails due to (?) regularized bias term)
  Data eps = static_cast<Data>(0.15);
  X = {0, 0, 1,
       0, 1, 1,
       1, 0, 1,
       1 - eps, 1 - eps, 1};
  Y = {0, 1, 1, 0};
  test_solver_multiclass_basic_feature_in(objective, X, Y, static_cast<Result>(0.75));
}

template <typename Data,
          typename Result>
inline void
test_solver_multiclass_basic_all() {
  Result C = 4;
  test_solver_multiclass_basic(
    sdca::make_objective_l2_entropy_topk<Data, Result>(C));

  test_solver_multiclass_basic(
    sdca::make_objective_l2_hinge_topk<Data, Result>(C));
  test_solver_multiclass_basic(
    sdca::make_objective_l2_hinge_topk_smooth<Data, Result>(C));

  test_solver_multiclass_basic(
    sdca::make_objective_l2_topk_hinge<Data, Result>(C));
  test_solver_multiclass_basic(
    sdca::make_objective_l2_topk_hinge_smooth<Data, Result>(C));
}

TEST(SolverTest, multiclass_basic_problems_all_objectives) {
  sdca::logging::set_level(sdca::logging::level::warning);
  sdca::logging::set_format(sdca::logging::format::short_e);
  test_solver_multiclass_basic_all<float, float>();
  test_solver_multiclass_basic_all<float, double>();
  test_solver_multiclass_basic_all<double, float>();
  test_solver_multiclass_basic_all<double, double>();
}
<|endoftext|>