<commit_before>//---------------------------------------------------------- -*- Mode: C++ -*-
// $Id$
//
// Created 2011/10/11
// Author: Mike Ovsiannikov
//
// Copyright 2011-2012 Quantcast Corp.
//
// This file is part of Kosmos File System (KFS).
//
// 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.
//
// \file MemLock.cc
// \brief Process common memory locking code.
//
//----------------------------------------------------------------------------

#include "MemLock.h"
#include "StdAllocator.h"

#include "qcdio/QCUtils.h"

#include <sys/mman.h>
#include <sys/resource.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

#include <algorithm>

#ifdef KFS_OS_NAME_LINUX
#   include <malloc.h>
#endif

namespace KFS
{
using std::string;
using std::min;
using std::max;

class MallocSetup
{
public:
    MallocSetup(
        int64_t      inSize,
        int64_t      inMaxStlPoolSize,
        const char** inErrMsgPtr = 0)
        : mAllocPtr(0),
          mStdPtr(0),
          mAllocator()
    {
#ifdef KFS_OS_NAME_LINUX
        if (! mallopt(M_TRIM_THRESHOLD, -1)) {
            if (inErrMsgPtr) {
                *inErrMsgPtr = "mallopt trim_threshold:";
            }
            return;
        }
#endif
        if (inMaxStlPoolSize > 0) {
            const int64_t theAllocCnt = min(
                int64_t(10) << 20,
                inMaxStlPoolSize / kStdMaxAllocSize
            ) + 1;
            mStdPtr = new StdAlloc::pointer[theAllocCnt];
            int64_t i;
            for (i = 0; i < theAllocCnt - 1; i++) {
                if (! (mStdPtr[i] = mAllocator.allocate(kStdMaxAllocSize))) {
                    return;
                }
            }
            mStdPtr[i] = 0;
        }
        // Force sbrk / heap allocation.
        mAllocPtr = new ForcePageAlloc[
            max(int64_t(0), inSize / ForcePageAlloc::kBufSize)
        ];
    }
    ~MallocSetup()
    {
        if (mStdPtr) {
            StdAlloc::pointer* thePtr = mStdPtr;
            while (*thePtr) {
                mAllocator.deallocate(*thePtr, kStdMaxAllocSize);
            }
            delete [] mStdPtr;
        }
        delete [] mAllocPtr;

    }
    bool IsError()
        { return (! mAllocPtr); }
private:
    enum { kStdMaxAllocSize = 256 };
    struct ForcePageAlloc
    {
        enum { kPageSize            = 4  << 10 };
        enum { kMallocMmapThreshold = 64 << 10 }; // Default is 128K
        enum { kBufSize             = kMallocMmapThreshold - kPageSize };
        ForcePageAlloc()
            : mBufPtr(new char[kBufSize])
        {
            char*       thePtr    = mBufPtr;
            char* const theEndPtr = thePtr + kBufSize;
            while (thePtr < theEndPtr) {
                *thePtr = 0xFF;
                thePtr += kPageSize;
            }
        }
        ~ForcePageAlloc()
            { delete [] mBufPtr; }
        char* const mBufPtr;
    };
    typedef StdAllocator<char> StdAlloc;

    ForcePageAlloc*    mAllocPtr;
    StdAlloc::pointer* mStdPtr;
    StdAlloc           mAllocator;

    MallocSetup(
        const MallocSetup&);
    MallocSetup& operator=(
        const MallocSetup&);
};

static void
AllocThreadStack()
{
    char theBuf[256 << 10];
    memset(theBuf, 0xFF, sizeof(theBuf));
}

int
LockProcessMemory(
    int64_t inMaxLockedMemorySize,
    int64_t inMaxHeapSize,
    int64_t inMaxStlPoolSize,
    string* outErrMsgPtr)
{
    if (inMaxLockedMemorySize == 0) {
        return 0;
    }
    int         theRet    = 0;
#ifndef KFS_OS_NAME_CYGWIN
    const char* theMsgPtr = 0;
    if (inMaxLockedMemorySize == 0 && munlockall()) {
        theRet    = errno;
        theMsgPtr = "munlockall:";
    } else {
        const int64_t kPgAlign = 8 <<10;
        struct rlimit theLim   = {0};
        if (getrlimit(RLIMIT_MEMLOCK, &theLim)) {
            theRet    = errno;
            theMsgPtr = "getrlimit memlock:";
        } else {
            theLim.rlim_cur = (rlim_t)((inMaxLockedMemorySize + kPgAlign - 1) /
                kPgAlign * kPgAlign);
            if (theLim.rlim_max < theLim.rlim_cur) {
                // An attempt to raise it should succeed with enough privileges.
                theLim.rlim_max = theLim.rlim_cur;
            }
            if (setrlimit(RLIMIT_MEMLOCK, &theLim)) {
                theRet    = errno;
                theMsgPtr = "setrlimit memlock:";
            } else {
                AllocThreadStack();
                // Try to grow the heap.
                MallocSetup mallocSetup(
                    inMaxHeapSize, inMaxStlPoolSize, &theMsgPtr);
                if (mallocSetup.IsError()) {
                    theRet = errno;
                    if (! theMsgPtr) {
                        theMsgPtr = "malloc:";
                    }
                }
                if (mlockall(MCL_CURRENT | MCL_FUTURE)) {
                    theRet    = errno;
                    theMsgPtr = "mlockall:";
                }
            }
        }
    }
    if (theRet != 0 && outErrMsgPtr) {
        *outErrMsgPtr = QCUtils::SysError(theRet, theMsgPtr);
    }
#else
    AllocThreadStack();
#endif
    return theRet;
}

} // namespace KFS
<commit_msg>Common library: fix std pool de-allocation with memory locking.<commit_after>//---------------------------------------------------------- -*- Mode: C++ -*-
// $Id$
//
// Created 2011/10/11
// Author: Mike Ovsiannikov
//
// Copyright 2011-2012 Quantcast Corp.
//
// This file is part of Kosmos File System (KFS).
//
// 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.
//
// \file MemLock.cc
// \brief Process common memory locking code.
//
//----------------------------------------------------------------------------

#include "MemLock.h"
#include "StdAllocator.h"

#include "qcdio/QCUtils.h"

#include <sys/mman.h>
#include <sys/resource.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

#include <algorithm>

#ifdef KFS_OS_NAME_LINUX
#   include <malloc.h>
#endif

namespace KFS
{
using std::string;
using std::min;
using std::max;

class MallocSetup
{
public:
    MallocSetup(
        int64_t      inSize,
        int64_t      inMaxStlPoolSize,
        const char** inErrMsgPtr = 0)
        : mAllocPtr(0),
          mStdPtr(0),
          mAllocator()
    {
#ifdef KFS_OS_NAME_LINUX
        if (! mallopt(M_TRIM_THRESHOLD, -1)) {
            if (inErrMsgPtr) {
                *inErrMsgPtr = "mallopt trim_threshold:";
            }
            return;
        }
#endif
        if (inMaxStlPoolSize > 0) {
            const int64_t theAllocCnt = min(
                int64_t(10) << 20,
                inMaxStlPoolSize / kStdMaxAllocSize
            ) + 1;
            mStdPtr = new StdAlloc::pointer[theAllocCnt];
            int64_t i;
            for (i = 0; i < theAllocCnt - 1; i++) {
                if (! (mStdPtr[i] = mAllocator.allocate(kStdMaxAllocSize))) {
                    return;
                }
            }
            mStdPtr[i] = 0;
        }
        // Force sbrk / heap allocation.
        mAllocPtr = new ForcePageAlloc[
            max(int64_t(0), inSize / ForcePageAlloc::kBufSize)
        ];
    }
    ~MallocSetup()
    {
        if (mStdPtr) {
            StdAlloc::pointer* thePtr = mStdPtr;
            while (*thePtr) {
                mAllocator.deallocate(*thePtr++, kStdMaxAllocSize);
            }
            delete [] mStdPtr;
        }
        delete [] mAllocPtr;

    }
    bool IsError()
        { return (! mAllocPtr); }
private:
    enum { kStdMaxAllocSize = 256 };
    struct ForcePageAlloc
    {
        enum { kPageSize            = 4  << 10 };
        enum { kMallocMmapThreshold = 64 << 10 }; // Default is 128K
        enum { kBufSize             = kMallocMmapThreshold - kPageSize };
        ForcePageAlloc()
            : mBufPtr(new char[kBufSize])
        {
            char*       thePtr    = mBufPtr;
            char* const theEndPtr = thePtr + kBufSize;
            while (thePtr < theEndPtr) {
                *thePtr = 0xFF;
                thePtr += kPageSize;
            }
        }
        ~ForcePageAlloc()
            { delete [] mBufPtr; }
        char* const mBufPtr;
    };
    typedef StdAllocator<char> StdAlloc;

    ForcePageAlloc*    mAllocPtr;
    StdAlloc::pointer* mStdPtr;
    StdAlloc           mAllocator;

    MallocSetup(
        const MallocSetup&);
    MallocSetup& operator=(
        const MallocSetup&);
};

static void
AllocThreadStack()
{
    char theBuf[256 << 10];
    memset(theBuf, 0xFF, sizeof(theBuf));
}

int
LockProcessMemory(
    int64_t inMaxLockedMemorySize,
    int64_t inMaxHeapSize,
    int64_t inMaxStlPoolSize,
    string* outErrMsgPtr)
{
    if (inMaxLockedMemorySize == 0) {
        return 0;
    }
    int         theRet    = 0;
#ifndef KFS_OS_NAME_CYGWIN
    const char* theMsgPtr = 0;
    if (inMaxLockedMemorySize == 0 && munlockall()) {
        theRet    = errno;
        theMsgPtr = "munlockall:";
    } else {
        const int64_t kPgAlign = 8 <<10;
        struct rlimit theLim   = {0};
        if (getrlimit(RLIMIT_MEMLOCK, &theLim)) {
            theRet    = errno;
            theMsgPtr = "getrlimit memlock:";
        } else {
            theLim.rlim_cur = (rlim_t)((inMaxLockedMemorySize + kPgAlign - 1) /
                kPgAlign * kPgAlign);
            if (theLim.rlim_max < theLim.rlim_cur) {
                // An attempt to raise it should succeed with enough privileges.
                theLim.rlim_max = theLim.rlim_cur;
            }
            if (setrlimit(RLIMIT_MEMLOCK, &theLim)) {
                theRet    = errno;
                theMsgPtr = "setrlimit memlock:";
            } else {
                AllocThreadStack();
                // Try to grow the heap.
                MallocSetup mallocSetup(
                    inMaxHeapSize, inMaxStlPoolSize, &theMsgPtr);
                if (mallocSetup.IsError()) {
                    theRet = errno;
                    if (! theMsgPtr) {
                        theMsgPtr = "malloc:";
                    }
                }
                if (mlockall(MCL_CURRENT | MCL_FUTURE)) {
                    theRet    = errno;
                    theMsgPtr = "mlockall:";
                }
            }
        }
    }
    if (theRet != 0 && outErrMsgPtr) {
        *outErrMsgPtr = QCUtils::SysError(theRet, theMsgPtr);
    }
#else
    AllocThreadStack();
#endif
    return theRet;
}

} // namespace KFS
<|endoftext|>


<commit_before>/*
    kopeteiface.cpp - Kopete DCOP Interface

    Copyright (c) 2002 by Hendrik vom Lehn       <hennevl@hennevl.de>

    Kopete    (c) 2002-2003      by the Kopete developers  <kopete-devel@kde.org>

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

#include <kmessagebox.h>
#include <klocale.h>
#include <kconfig.h>
#include <kglobal.h>

#include "kopeteiface.h"
#include "kopetemetacontact.h"
#include "kopetecontactlist.h"
#include "kopeteaccount.h"
#include "kopeteaccountmanager.h"
#include "kopetepluginmanager.h"
#include "kopeteprotocol.h"
#include "kopeteuiglobal.h"
#include "kopeteaway.h"
#include "kopetecontact.h"

KopeteIface::KopeteIface() : DCOPObject( "KopeteIface" )
{
	KConfig *config = KGlobal::config();
	config->setGroup("AutoAway");

	if (config->readBoolEntry("UseAutoAway", true))
	{
		connectDCOPSignal("kdesktop", "KScreensaverIface",
			"KDE_start_screensaver()", "setAutoAway()", false);
	}
	else
	{
		disconnectDCOPSignal("kdesktop", "KScreensaverIface",
			"KDE_start_screensaver()", "setAutoAway()");
	}
}

QStringList KopeteIface::contacts()
{
	return KopeteContactList::contactList()->contacts();
}

QStringList KopeteIface::reachableContacts()
{
	return KopeteContactList::contactList()->reachableContacts();
}

QStringList KopeteIface::onlineContacts()
{
	QStringList result;
	QPtrList<KopeteContact> list = KopeteContactList::contactList()->onlineContacts();
	QPtrListIterator<KopeteContact> it( list );
	for( ; it.current(); ++it )
		result.append( it.current()->contactId() );

	return result;
}

QStringList KopeteIface::contactsStatus()
{
	return KopeteContactList::contactList()->contactStatuses();
}

QStringList KopeteIface::fileTransferContacts()
{
	return KopeteContactList::contactList()->fileTransferContacts();
}

QStringList KopeteIface::contactFileProtocols(const QString &displayName)
{
	return KopeteContactList::contactList()->contactFileProtocols(displayName);
}

void KopeteIface::messageContact( const QString &displayName, const QString &messageText )
{
	KopeteContactList::contactList()->messageContact( displayName, messageText );
}
/*
void KopeteIface::sendFile(const QString &displayName, const KURL &sourceURL,
	const QString &altFileName, uint fileSize)
{
	return KopeteContactList::contactList()->sendFile(displayName, sourceURL, altFileName, fileSize);
}

*/

QString KopeteIface::onlineStatus( const QString &metaContactId )
{
	KopeteMetaContact *m = KopeteContactList::contactList()->metaContact( metaContactId );
	if( m )
	{
		KopeteOnlineStatus status = m->status();
		return status.description();
	}

	return "Unknown Contact";
}

void KopeteIface::messageContactById( const QString &metaContactId )
{
	KopeteMetaContact *m = KopeteContactList::contactList()->metaContact( metaContactId );
	if( m )
	{
		m->execute();
	}
}

bool KopeteIface::addContact( const QString &protocolName, const QString &accountId, const QString &contactId,
	const QString &displayName, const QString &groupName )
{
		//Get the protocol instance
	KopeteAccount *myAccount = KopeteAccountManager::manager()->findAccount( protocolName, accountId );

	if( myAccount )
	{
		QString contactName;

		//If the nickName isn't specified we need to display the userId in the prompt
		if( displayName.isEmpty() || displayName.isNull() )
			contactName = contactId;
		else
			contactName = displayName;

		// Confirm with the user before we add the contact
		if( KMessageBox::questionYesNo( Kopete::UI::Global::mainWidget(), i18n( "An external application is attempting to add the "
			" '%1' contact '%2' to your contact list. Do you want to allow this?" )
			.arg( protocolName ).arg( contactName ), i18n( "Allow Contact?" ) ) == 3 ) // Yes == 3
		{
			//User said Yes
			myAccount->addContact( contactId, displayName, 0L, KopeteAccount::DontChangeKABC, groupName, false );
			return true;
		} else {
			//User said No
			return false;
		}

	} else {
		//This protocol is not loaded
		KMessageBox::queuedMessageBox( Kopete::UI::Global::mainWidget(), KMessageBox::Error,
				 i18n("An external application has attempted to add a contact using "
				      " the %1 protocol, which either does not exist or is not loaded.").arg( protocolName ),
				i18n("Missing Protocol"));

		return false;
	}
}

QStringList KopeteIface::accounts()
{
	QStringList list;
	QPtrList<KopeteAccount> m_accounts=KopeteAccountManager::manager()->accounts();
	QPtrListIterator<KopeteAccount> it( m_accounts );
	KopeteAccount *account;
	while ( ( account = it.current() ) != 0 )
	{
		++it;

		list += ( account->protocol()->pluginId() +"||" + account->accountId() );
	}

	return list;

}

void KopeteIface::connect(const QString &protocolId, const QString &accountId )
{
	QPtrListIterator<KopeteAccount> it( KopeteAccountManager::manager()->accounts() );
	KopeteAccount *account;
	while ( ( account = it.current() ) != 0 )
	{
		++it;

		if( ( account->accountId() == accountId) )
		{
			if( protocolId.isEmpty() || account->protocol()->pluginId() == protocolId )
			{
				account->connect();
				break;
			}
		}
	}
}

void KopeteIface::disconnect(const QString &protocolId, const QString &accountId )
{
	QPtrListIterator<KopeteAccount> it( KopeteAccountManager::manager()->accounts() );
	KopeteAccount *account;
	while ( ( account = it.current() ) != 0 )
	{
		++it;

		if( ( account->accountId() == accountId) )
		{
			if( protocolId.isEmpty() || account->protocol()->pluginId() == protocolId )
			{
				account->disconnect();
				break;
			}
		}
	}
}

void KopeteIface::connectAll()
{
	KopeteAccountManager::manager()->connectAll();
}

void KopeteIface::disconnectAll()
{
	KopeteAccountManager::manager()->disconnectAll();
}

bool KopeteIface::loadPlugin( const QString &name )
{
	if ( KopetePluginManager::self()->setPluginEnabled( name ) )
	{
		QString argument = name;
		if ( !argument.startsWith( "kopete_" ) )
			argument.prepend( "kopete_" );
		return KopetePluginManager::self()->loadPlugin( argument );
	}
	else
	{
		return false;
	}
}

bool KopeteIface::unloadPlugin( const QString &name )
{
	if ( KopetePluginManager::self()->setPluginEnabled( name, false ) )
	{
		QString argument = name;
		if ( !argument.startsWith( "kopete_" ) )
			argument.prepend( "kopete_" );
		return KopetePluginManager::self()->unloadPlugin( argument );
	}
	else
	{
		return false;
	}
}

void KopeteIface::setAway()
{
	KopeteAccountManager::manager()->setAwayAll();
}

void KopeteIface::setAway(const QString &msg)
{
	KopeteAccountManager::manager()->setAwayAll(msg);
}

void KopeteIface::setAvailable()
{
	KopeteAccountManager::manager()->setAvailableAll();
}

void KopeteIface::setAutoAway()
{
	KopeteAway::getInstance()->setAutoAway();
}

// vim: set noet ts=4 sts=4 sw=4:

<commit_msg>Fix bug 77136. If the group name is blank, use the top level group. If the display name is blank, use the contact id as the display name.<commit_after>/*
    kopeteiface.cpp - Kopete DCOP Interface

    Copyright (c) 2002 by Hendrik vom Lehn       <hennevl@hennevl.de>

    Kopete    (c) 2002-2003      by the Kopete developers  <kopete-devel@kde.org>

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

#include <kmessagebox.h>
#include <klocale.h>
#include <kconfig.h>
#include <kglobal.h>

#include "kopeteiface.h"
#include "kopetemetacontact.h"
#include "kopetecontactlist.h"
#include "kopeteaccount.h"
#include "kopeteaccountmanager.h"
#include "kopetepluginmanager.h"
#include "kopeteprotocol.h"
#include "kopeteuiglobal.h"
#include "kopeteaway.h"
#include "kopetegroup.h"
#include "kopetecontact.h"

KopeteIface::KopeteIface() : DCOPObject( "KopeteIface" )
{
	KConfig *config = KGlobal::config();
	config->setGroup("AutoAway");

	if (config->readBoolEntry("UseAutoAway", true))
	{
		connectDCOPSignal("kdesktop", "KScreensaverIface",
			"KDE_start_screensaver()", "setAutoAway()", false);
	}
	else
	{
		disconnectDCOPSignal("kdesktop", "KScreensaverIface",
			"KDE_start_screensaver()", "setAutoAway()");
	}
}

QStringList KopeteIface::contacts()
{
	return KopeteContactList::contactList()->contacts();
}

QStringList KopeteIface::reachableContacts()
{
	return KopeteContactList::contactList()->reachableContacts();
}

QStringList KopeteIface::onlineContacts()
{
	QStringList result;
	QPtrList<KopeteContact> list = KopeteContactList::contactList()->onlineContacts();
	QPtrListIterator<KopeteContact> it( list );
	for( ; it.current(); ++it )
		result.append( it.current()->contactId() );

	return result;
}

QStringList KopeteIface::contactsStatus()
{
	return KopeteContactList::contactList()->contactStatuses();
}

QStringList KopeteIface::fileTransferContacts()
{
	return KopeteContactList::contactList()->fileTransferContacts();
}

QStringList KopeteIface::contactFileProtocols(const QString &displayName)
{
	return KopeteContactList::contactList()->contactFileProtocols(displayName);
}

void KopeteIface::messageContact( const QString &displayName, const QString &messageText )
{
	KopeteContactList::contactList()->messageContact( displayName, messageText );
}
/*
void KopeteIface::sendFile(const QString &displayName, const KURL &sourceURL,
	const QString &altFileName, uint fileSize)
{
	return KopeteContactList::contactList()->sendFile(displayName, sourceURL, altFileName, fileSize);
}

*/

QString KopeteIface::onlineStatus( const QString &metaContactId )
{
	KopeteMetaContact *m = KopeteContactList::contactList()->metaContact( metaContactId );
	if( m )
	{
		KopeteOnlineStatus status = m->status();
		return status.description();
	}

	return "Unknown Contact";
}

void KopeteIface::messageContactById( const QString &metaContactId )
{
	KopeteMetaContact *m = KopeteContactList::contactList()->metaContact( metaContactId );
	if( m )
	{
		m->execute();
	}
}

bool KopeteIface::addContact( const QString &protocolName, const QString &accountId, const QString &contactId,
	const QString &displayName, const QString &groupName )
{
		//Get the protocol instance
	KopeteAccount *myAccount = KopeteAccountManager::manager()->findAccount( protocolName, accountId );

	if( myAccount )
	{
		QString contactName;
		QString realGroupName;
		//If the nickName isn't specified we need to display the userId in the prompt
		if( displayName.isEmpty() || displayName.isNull() )
			contactName = contactId;
		else
			contactName = displayName;

		if ( !groupName.isEmpty() )
			realGroupName = groupName;

		// Confirm with the user before we add the contact
		if( KMessageBox::questionYesNo( Kopete::UI::Global::mainWidget(), i18n( "An external application is attempting to add the "
			" '%1' contact '%2' to your contact list. Do you want to allow this?" )
			.arg( protocolName ).arg( contactName ), i18n( "Allow Contact?" ) ) == 3 ) // Yes == 3
		{
			//User said Yes
			myAccount->addContact( contactId, contactName, 0L, KopeteAccount::DontChangeKABC, realGroupName, false );
			return true;
		} else {
			//User said No
			return false;
		}

	} else {
		//This protocol is not loaded
		KMessageBox::queuedMessageBox( Kopete::UI::Global::mainWidget(), KMessageBox::Error,
				 i18n("An external application has attempted to add a contact using "
				      " the %1 protocol, which either does not exist or is not loaded.").arg( protocolName ),
				i18n("Missing Protocol"));

		return false;
	}
}

QStringList KopeteIface::accounts()
{
	QStringList list;
	QPtrList<KopeteAccount> m_accounts=KopeteAccountManager::manager()->accounts();
	QPtrListIterator<KopeteAccount> it( m_accounts );
	KopeteAccount *account;
	while ( ( account = it.current() ) != 0 )
	{
		++it;

		list += ( account->protocol()->pluginId() +"||" + account->accountId() );
	}

	return list;

}

void KopeteIface::connect(const QString &protocolId, const QString &accountId )
{
	QPtrListIterator<KopeteAccount> it( KopeteAccountManager::manager()->accounts() );
	KopeteAccount *account;
	while ( ( account = it.current() ) != 0 )
	{
		++it;

		if( ( account->accountId() == accountId) )
		{
			if( protocolId.isEmpty() || account->protocol()->pluginId() == protocolId )
			{
				account->connect();
				break;
			}
		}
	}
}

void KopeteIface::disconnect(const QString &protocolId, const QString &accountId )
{
	QPtrListIterator<KopeteAccount> it( KopeteAccountManager::manager()->accounts() );
	KopeteAccount *account;
	while ( ( account = it.current() ) != 0 )
	{
		++it;

		if( ( account->accountId() == accountId) )
		{
			if( protocolId.isEmpty() || account->protocol()->pluginId() == protocolId )
			{
				account->disconnect();
				break;
			}
		}
	}
}

void KopeteIface::connectAll()
{
	KopeteAccountManager::manager()->connectAll();
}

void KopeteIface::disconnectAll()
{
	KopeteAccountManager::manager()->disconnectAll();
}

bool KopeteIface::loadPlugin( const QString &name )
{
	if ( KopetePluginManager::self()->setPluginEnabled( name ) )
	{
		QString argument = name;
		if ( !argument.startsWith( "kopete_" ) )
			argument.prepend( "kopete_" );
		return KopetePluginManager::self()->loadPlugin( argument );
	}
	else
	{
		return false;
	}
}

bool KopeteIface::unloadPlugin( const QString &name )
{
	if ( KopetePluginManager::self()->setPluginEnabled( name, false ) )
	{
		QString argument = name;
		if ( !argument.startsWith( "kopete_" ) )
			argument.prepend( "kopete_" );
		return KopetePluginManager::self()->unloadPlugin( argument );
	}
	else
	{
		return false;
	}
}

void KopeteIface::setAway()
{
	KopeteAccountManager::manager()->setAwayAll();
}

void KopeteIface::setAway(const QString &msg)
{
	KopeteAccountManager::manager()->setAwayAll(msg);
}

void KopeteIface::setAvailable()
{
	KopeteAccountManager::manager()->setAvailableAll();
}

void KopeteIface::setAutoAway()
{
	KopeteAway::getInstance()->setAutoAway();
}

// vim: set noet ts=4 sts=4 sw=4:

<|endoftext|>


<commit_before>#include "StateSpace.h"

StateSpace::StateSpace(const unsigned int _angle_bins, const unsigned int _velocity_bins, const unsigned int _torque_bins):
	angle_bins(_angle_bins),
	velocity_bins(_velocity_bins),
	torque_bins(_torque_bins),
	space( _angle_bins, std::vector<std::vector<PriorityQueue<Action*,double>>> ( _velocity_bins, std::vector<PriorityQueue<Action*,double>> ( _torque_bins, PriorityQueue<Action*,double> (HeapType::MAX) ) ) )

{}

StateSpace::~StateSpace()
{
	//ridiculously extensive clean-up
	for(unsigned int i=0 ; i<angle_max ; ++i)
	{
		for(unsigned int j=0 ; j<velocity_max ; ++j)
		{
			for(unsigned int k=0 ; k<torque_max ; ++k)
			{
				PriorityQueue<Action*,double>& queue1=space[i][j][k];

				for(auto iter=queue1.begin(),queue1=list.end() ; iter!=end ; ++iter)
				{
					delete *iter;
				}
			}
		}
	}
}

StateSpace::SubscriptProxy1 StateSpace::operator[](const double angle)
{
	//error if angle exceeds bounds
	if(std::abs(angle)>2*M_PI)throw std::domain_error("angle argument exceeded");
	//descretise index
	int discrete_index=std::round(angle*100/angle_bins)+angle_bins/2;

	//return appropriate object
	return SubscriptProxy1(space[discrete_index]);
}
<commit_msg>Update StateSpace3.cpp<commit_after>#include "StateSpace.h"

StateSpace::StateSpace(const unsigned int _angle_bins, const unsigned int _velocity_bins, const unsigned int _torque_bins, PriorityQueue<Action*,double> queue):
	angle_bins(_angle_bins),
	velocity_bins(_velocity_bins),
	torque_bins(_torque_bins),
	space( _angle_bins, std::vector<std::vector<PriorityQueue<Action*,double>>> ( _velocity_bins, std::vector<PriorityQueue<Action*,double>> ( _torque_bins, PriorityQueue<Action*,double> (queue) ) ) )

{}

StateSpace::~StateSpace()
{
	//ridiculously extensive clean-up
	for(unsigned int i=0 ; i<angle_max ; ++i)
	{
		for(unsigned int j=0 ; j<velocity_max ; ++j)
		{
			for(unsigned int k=0 ; k<torque_max ; ++k)
			{
				PriorityQueue<Action*,double>& queue1=space[i][j][k];

				for(auto iter=queue1.begin(),queue1=list.end() ; iter!=end ; ++iter)
				{
					delete *iter;
				}
			}
		}
	}
}

StateSpace::SubscriptProxy1 StateSpace::operator[](const double angle)
{
	//error if angle exceeds bounds
	if(std::abs(angle)>2*M_PI)throw std::domain_error("angle argument exceeded");
	//descretise index
	int discrete_index=std::round(angle*100/angle_bins)+angle_bins/2;

	//return appropriate object
	return SubscriptProxy1(space[discrete_index]);
}

//searches state space by state object
PriorityQueue<Action *, double> StateSpace::StateSearch(State & state)
{
	return (*this)[state->RobotState][state->theta][state->theta_dot];
}

<|endoftext|>


<commit_before>#include "ddViewManager.h"
#include "ddGLWidgetView.h"
#include "ddQVTKWidgetView.h"
#include "ddDRCView.h"
#include "ddSpreadsheetView.h"
#include "ddMacros.h"

#include <QTabWidget>
#include <QTabBar>
#include <QVBoxLayout>
#include <QMap>
#include <QSplitter>

#include <cstdio>

class MyTabWidget : public QTabWidget
{
public:

  MyTabWidget(QWidget* parent=0) : QTabWidget(parent)
  {
  }

  void updateTabBar()
  {
    this->tabBar()->setVisible(this->count() > 1);
  }
};

//-----------------------------------------------------------------------------
class ddViewManager::ddInternal
{
public:

  ddInternal()
  {
    this->CurrentTabIndex = -1;
  }

  int CurrentTabIndex;

  QTabWidget* TabWidget;

  QMap<QString, ddViewBase*> Views;

  QList<QSplitter*> Splitters;
};

//-----------------------------------------------------------------------------
ddViewManager::ddViewManager(QWidget* parent) : QWidget(parent)
{
  this->Internal = new ddInternal;

  QVBoxLayout* layout = new QVBoxLayout(this);
  layout->setMargin(0);

  QTabWidget* tabWidget = new MyTabWidget(this);
  tabWidget->setTabPosition(QTabWidget::West);
  tabWidget->setDocumentMode(true);
  layout->addWidget(tabWidget);
  this->Internal->TabWidget = tabWidget;

  this->connect(this->Internal->TabWidget, SIGNAL(currentChanged(int)), SLOT(onCurrentTabChanged(int)));

  this->addDefaultPage();
}

//-----------------------------------------------------------------------------
ddViewManager::~ddViewManager()
{
  delete this->Internal;
}

//-----------------------------------------------------------------------------
QTabWidget* ddViewManager::tabWidget() const
{
  return this->Internal->TabWidget;
}

//-----------------------------------------------------------------------------
ddViewBase* ddViewManager::findView(const QString& viewName) const
{
  return this->Internal->Views.value(viewName);
}

//-----------------------------------------------------------------------------
QString ddViewManager::viewName(ddViewBase* view)
{
  return this->Internal->Views.key(view);
}

//-----------------------------------------------------------------------------
void ddViewManager::switchToView(const QString& viewName)
{
  for (int i = 0; i < this->Internal->TabWidget->count(); ++i)
  {
    if (this->Internal->TabWidget->tabText(i) == viewName)
    {
      this->Internal->TabWidget->setCurrentIndex(i);
      return;
    }
  }
}

//-----------------------------------------------------------------------------
ddViewBase* ddViewManager::currentView() const
{
  return this->findView(this->Internal->TabWidget->tabText(this->Internal->TabWidget->currentIndex()));
}

//-----------------------------------------------------------------------------
void ddViewManager::onCurrentTabChanged(int currentIndex)
{
  ddViewBase* previousView = 0;
  if (this->Internal->CurrentTabIndex >= 0)
  {
    previousView = this->findView(this->Internal->TabWidget->tabText(this->Internal->CurrentTabIndex));
  }
  this->Internal->CurrentTabIndex = currentIndex;
  emit this->currentViewChanged(previousView, this->currentView());
}

//-----------------------------------------------------------------------------
void ddViewManager::addView(ddViewBase* view, const QString& viewName, int pageIndex)
{
  QSplitter* splitter = 0;
  if (pageIndex >= 0 && pageIndex < this->Internal->Splitters.length())
  {
    splitter = this->Internal->Splitters[pageIndex];
  }
  else
  {
    splitter = new QSplitter();
    this->Internal->Splitters.append(splitter);
    this->tabWidget()->addTab(splitter, viewName);
  }

  splitter->addWidget(view);

  this->Internal->Views[viewName] = view;
  static_cast<MyTabWidget*>(this->tabWidget())->updateTabBar();
}

//-----------------------------------------------------------------------------
ddViewBase* ddViewManager::createView(const QString& viewName, const QString& viewType, int pageIndex)
{
  ddViewBase* view = 0;
  if (viewName == "VTK View")
  {
    view = new ddQVTKWidgetView;
  }
  else if (viewName == "Spreadsheet View")
  {
    view = new ddSpreadsheetView;
  }

  if (view)
  {
    this->addView(view, viewName, pageIndex);
  }

  return view;
}

//-----------------------------------------------------------------------------
void ddViewManager::addDefaultPage()
{
  this->addView(new ddQVTKWidgetView, "DRC View");
}
<commit_msg>fix typo: compare viewType, not viewName in ddViewManager::createView()<commit_after>#include "ddViewManager.h"
#include "ddGLWidgetView.h"
#include "ddQVTKWidgetView.h"
#include "ddDRCView.h"
#include "ddSpreadsheetView.h"
#include "ddMacros.h"

#include <QTabWidget>
#include <QTabBar>
#include <QVBoxLayout>
#include <QMap>
#include <QSplitter>

#include <cstdio>

class MyTabWidget : public QTabWidget
{
public:

  MyTabWidget(QWidget* parent=0) : QTabWidget(parent)
  {
  }

  void updateTabBar()
  {
    this->tabBar()->setVisible(this->count() > 1);
  }
};

//-----------------------------------------------------------------------------
class ddViewManager::ddInternal
{
public:

  ddInternal()
  {
    this->CurrentTabIndex = -1;
  }

  int CurrentTabIndex;

  QTabWidget* TabWidget;

  QMap<QString, ddViewBase*> Views;

  QList<QSplitter*> Splitters;
};

//-----------------------------------------------------------------------------
ddViewManager::ddViewManager(QWidget* parent) : QWidget(parent)
{
  this->Internal = new ddInternal;

  QVBoxLayout* layout = new QVBoxLayout(this);
  layout->setMargin(0);

  QTabWidget* tabWidget = new MyTabWidget(this);
  tabWidget->setTabPosition(QTabWidget::West);
  tabWidget->setDocumentMode(true);
  layout->addWidget(tabWidget);
  this->Internal->TabWidget = tabWidget;

  this->connect(this->Internal->TabWidget, SIGNAL(currentChanged(int)), SLOT(onCurrentTabChanged(int)));

  this->addDefaultPage();
}

//-----------------------------------------------------------------------------
ddViewManager::~ddViewManager()
{
  delete this->Internal;
}

//-----------------------------------------------------------------------------
QTabWidget* ddViewManager::tabWidget() const
{
  return this->Internal->TabWidget;
}

//-----------------------------------------------------------------------------
ddViewBase* ddViewManager::findView(const QString& viewName) const
{
  return this->Internal->Views.value(viewName);
}

//-----------------------------------------------------------------------------
QString ddViewManager::viewName(ddViewBase* view)
{
  return this->Internal->Views.key(view);
}

//-----------------------------------------------------------------------------
void ddViewManager::switchToView(const QString& viewName)
{
  for (int i = 0; i < this->Internal->TabWidget->count(); ++i)
  {
    if (this->Internal->TabWidget->tabText(i) == viewName)
    {
      this->Internal->TabWidget->setCurrentIndex(i);
      return;
    }
  }
}

//-----------------------------------------------------------------------------
ddViewBase* ddViewManager::currentView() const
{
  return this->findView(this->Internal->TabWidget->tabText(this->Internal->TabWidget->currentIndex()));
}

//-----------------------------------------------------------------------------
void ddViewManager::onCurrentTabChanged(int currentIndex)
{
  ddViewBase* previousView = 0;
  if (this->Internal->CurrentTabIndex >= 0)
  {
    previousView = this->findView(this->Internal->TabWidget->tabText(this->Internal->CurrentTabIndex));
  }
  this->Internal->CurrentTabIndex = currentIndex;
  emit this->currentViewChanged(previousView, this->currentView());
}

//-----------------------------------------------------------------------------
void ddViewManager::addView(ddViewBase* view, const QString& viewName, int pageIndex)
{
  QSplitter* splitter = 0;
  if (pageIndex >= 0 && pageIndex < this->Internal->Splitters.length())
  {
    splitter = this->Internal->Splitters[pageIndex];
  }
  else
  {
    splitter = new QSplitter();
    this->Internal->Splitters.append(splitter);
    this->tabWidget()->addTab(splitter, viewName);
  }

  splitter->addWidget(view);

  this->Internal->Views[viewName] = view;
  static_cast<MyTabWidget*>(this->tabWidget())->updateTabBar();
}

//-----------------------------------------------------------------------------
ddViewBase* ddViewManager::createView(const QString& viewName, const QString& viewType, int pageIndex)
{
  ddViewBase* view = 0;
  if (viewType == "VTK View")
  {
    view = new ddQVTKWidgetView;
  }
  else if (viewType == "Spreadsheet View")
  {
    view = new ddSpreadsheetView;
  }

  if (view)
  {
    this->addView(view, viewName, pageIndex);
  }

  return view;
}

//-----------------------------------------------------------------------------
void ddViewManager::addDefaultPage()
{
  this->addView(new ddQVTKWidgetView, "DRC View");
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2007-2008 The Florida State University
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders 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.
 *
 * Authors: Stephen Hines
 */

#ifndef __ARCH_ARM_REGISTERS_HH__
#define __ARCH_ARM_REGISTERS_HH__

#include "arch/arm/max_inst_regs.hh"
#include "arch/arm/intregs.hh"
#include "arch/arm/miscregs.hh"

namespace ArmISA {

using ArmISAInst::MaxInstSrcRegs;
using ArmISAInst::MaxInstDestRegs;

typedef uint8_t  RegIndex;

typedef uint64_t IntReg;

// floating point register file entry type
typedef uint32_t FloatRegBits;
typedef float FloatReg;

// cop-0/cop-1 system control register
typedef uint64_t MiscReg;

// Constants Related to the number of registers
const int NumIntArchRegs = NUM_ARCH_INTREGS;
const int NumFloatArchRegs = 16;
const int NumFloatSpecialRegs = 5;
const int NumInternalProcRegs = 0;

const int NumIntRegs = NUM_INTREGS;
const int NumFloatRegs = NumFloatArchRegs + NumFloatSpecialRegs;

const int NumMiscRegs = NUM_MISCREGS;

// semantically meaningful register indices
const int ReturnValueReg = 0;
const int ReturnValueReg1 = 1;
const int ReturnValueReg2 = 2;
const int ArgumentReg0 = 0;
const int ArgumentReg1 = 1;
const int ArgumentReg2 = 2;
const int ArgumentReg3 = 3;
const int FramePointerReg = 11;
const int StackPointerReg = INTREG_SP;
const int ReturnAddressReg = INTREG_LR;
const int PCReg = INTREG_PC;

const int ZeroReg = INTREG_ZERO;

const int SyscallNumReg = ReturnValueReg;
const int SyscallPseudoReturnReg = ReturnValueReg;
const int SyscallSuccessReg = ReturnValueReg;

// These help enumerate all the registers for dependence tracking.
const int FP_Base_DepTag = NumIntRegs;
const int Ctrl_Base_DepTag = FP_Base_DepTag + NumFloatRegs;

typedef union {
    IntReg   intreg;
    FloatReg fpreg;
    MiscReg  ctrlreg;
} AnyReg;

enum FPControlRegNums {
   FIR = NumFloatArchRegs,
   FCCR,
   FEXR,
   FENR,
   FCSR
};

enum FCSRBits {
    Inexact = 1,
    Underflow,
    Overflow,
    DivideByZero,
    Invalid,
    Unimplemented
};

enum FCSRFields {
    Flag_Field = 1,
    Enable_Field = 6,
    Cause_Field = 11
};

} // namespace ArmISA

#endif
<commit_msg>ARM: Get rid of NumInternalProcRegs.<commit_after>/*
 * Copyright (c) 2007-2008 The Florida State University
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders 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.
 *
 * Authors: Stephen Hines
 */

#ifndef __ARCH_ARM_REGISTERS_HH__
#define __ARCH_ARM_REGISTERS_HH__

#include "arch/arm/max_inst_regs.hh"
#include "arch/arm/intregs.hh"
#include "arch/arm/miscregs.hh"

namespace ArmISA {

using ArmISAInst::MaxInstSrcRegs;
using ArmISAInst::MaxInstDestRegs;

typedef uint8_t  RegIndex;

typedef uint64_t IntReg;

// floating point register file entry type
typedef uint32_t FloatRegBits;
typedef float FloatReg;

// cop-0/cop-1 system control register
typedef uint64_t MiscReg;

// Constants Related to the number of registers
const int NumIntArchRegs = NUM_ARCH_INTREGS;
const int NumFloatArchRegs = 16;
const int NumFloatSpecialRegs = 5;

const int NumIntRegs = NUM_INTREGS;
const int NumFloatRegs = NumFloatArchRegs + NumFloatSpecialRegs;

const int NumMiscRegs = NUM_MISCREGS;

// semantically meaningful register indices
const int ReturnValueReg = 0;
const int ReturnValueReg1 = 1;
const int ReturnValueReg2 = 2;
const int ArgumentReg0 = 0;
const int ArgumentReg1 = 1;
const int ArgumentReg2 = 2;
const int ArgumentReg3 = 3;
const int FramePointerReg = 11;
const int StackPointerReg = INTREG_SP;
const int ReturnAddressReg = INTREG_LR;
const int PCReg = INTREG_PC;

const int ZeroReg = INTREG_ZERO;

const int SyscallNumReg = ReturnValueReg;
const int SyscallPseudoReturnReg = ReturnValueReg;
const int SyscallSuccessReg = ReturnValueReg;

// These help enumerate all the registers for dependence tracking.
const int FP_Base_DepTag = NumIntRegs;
const int Ctrl_Base_DepTag = FP_Base_DepTag + NumFloatRegs;

typedef union {
    IntReg   intreg;
    FloatReg fpreg;
    MiscReg  ctrlreg;
} AnyReg;

enum FPControlRegNums {
   FIR = NumFloatArchRegs,
   FCCR,
   FEXR,
   FENR,
   FCSR
};

enum FCSRBits {
    Inexact = 1,
    Underflow,
    Overflow,
    DivideByZero,
    Invalid,
    Unimplemented
};

enum FCSRFields {
    Flag_Field = 1,
    Enable_Field = 6,
    Cause_Field = 11
};

} // namespace ArmISA

#endif
<|endoftext|>


<commit_before>
//
// This source file is part of appleseed.
// Visit https://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2019 Esteban Tovagliari, The appleseedhq Organization
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "cpurenderdevice.h"

// appleseed.renderer headers.
#include "renderer/global/globallogger.h"
#include "renderer/kernel/rendering/oiioerrorhandler.h"
#include "renderer/kernel/rendering/renderercomponents.h"
#include "renderer/kernel/rendering/rendererservices.h"
#include "renderer/kernel/shading/closures.h"
#include "renderer/kernel/shading/oslshadingsystem.h"
#include "renderer/kernel/texturing/oiiotexturesystem.h"
#include "renderer/kernel/texturing/texturestore.h"
#include "renderer/modeling/frame/frame.h"
#include "renderer/modeling/project/project.h"
#include "renderer/modeling/scene/scene.h"

// appleseed.foundation headers.
#include "foundation/containers/dictionary.h"
#include "foundation/utility/searchpaths.h"

// Standard headers.
#include <cstddef>
#include <string>

using namespace foundation;

namespace renderer
{

CPURenderDevice::CPURenderDevice(
    Project&                project,
    const ParamArray&       params)
  : RenderDeviceBase(project, params)
  , m_texture_store(*project.get_scene(), params.child("texture_store"))
{
    m_error_handler = new OIIOErrorHandler();
#ifndef NDEBUG
    m_error_handler->verbosity(OIIO::ErrorHandler::VERBOSE);
#endif

    RENDERER_LOG_DEBUG("creating oiio texture system...");
    m_texture_system = OIIOTextureSystemFactory::create(false);
    m_texture_system->attribute("automip", 0);
    m_texture_system->attribute("accept_untiled", 1);
    m_texture_system->attribute("accept_unmipped", 1);
    m_texture_system->attribute("gray_to_rgb", 1);
    m_texture_system->attribute("latlong_up", "y");
    m_texture_system->attribute("flip_t", 1);

    m_renderer_services =
        new RendererServices(
            project,
            reinterpret_cast<OIIO::TextureSystem&>(*m_texture_system));

    RENDERER_LOG_DEBUG("creating osl shading system...");
    m_shading_system =
        OSLShadingSystemFactory::create(
            m_renderer_services,
            m_texture_system,
            m_error_handler);
    m_shading_system->attribute("lockgeom", 1);
    m_shading_system->attribute("colorspace", "Linear");
    m_shading_system->attribute("commonspace", "world");
    m_shading_system->attribute("statistics:level", 1);
    m_shading_system->attribute(
        "raytypes",
        OSL::TypeDesc(
            OSL::TypeDesc::STRING,
            static_cast<int>(VisibilityFlags::Count)),
        VisibilityFlags::Names);
#ifndef NDEBUG
    m_shading_system->attribute("compile_report", 1);
    m_shading_system->attribute("countlayerexecs", 1);
    m_shading_system->attribute("clearmemory", 1);
#endif

    // Register appleseed's closures into OSL's shading system.
    register_closures(*m_shading_system);
}

CPURenderDevice::~CPURenderDevice()
{
    m_components.reset();

    RENDERER_LOG_DEBUG("destroying osl shading system...");
    get_project().get_scene()->release_optimized_osl_shader_groups();
    m_shading_system->release();
    delete m_renderer_services;

    const std::string stats = m_texture_system->getstats();
    const std::string modified_stats = prefix_all_lines(trim_both(stats), "oiio: ");
    RENDERER_LOG_DEBUG("%s", modified_stats.c_str());

    RENDERER_LOG_DEBUG("destroying oiio texture system...");
    m_texture_system->release();
    delete m_error_handler;

    // Print texture store performance statistics.
    RENDERER_LOG_DEBUG("%s", m_texture_store.get_statistics().to_string().c_str());
}

bool CPURenderDevice::initialize(
    const SearchPaths&      resource_search_paths,
    ITileCallbackFactory*   tile_callback_factory,
    IAbortSwitch&           abort_switch)
{
    // Construct a search paths string from the project's search paths.
    const std::string project_search_paths =
        to_string(get_project().search_paths().to_string_reversed(SearchPaths::osl_path_separator()));

    // Initialize OIIO.
    const size_t texture_cache_size_bytes =
        get_params().child("texture_store").get_optional<size_t>(
            "max_size",
            TextureStore::get_default_size());
    RENDERER_LOG_INFO(
        "setting oiio texture cache size to %s.",
        pretty_size(texture_cache_size_bytes).c_str());
    const float texture_cache_size_mb =
        static_cast<float>(texture_cache_size_bytes) / (1024 * 1024);
    m_texture_system->attribute("max_memory_MB", texture_cache_size_mb);

    // Set OIIO search paths.
    std::string prev_oiio_search_path;
    m_texture_system->getattribute("searchpath", prev_oiio_search_path);
    if (prev_oiio_search_path != project_search_paths)
    {
        RENDERER_LOG_INFO("setting oiio search paths to %s", project_search_paths.c_str());
        m_texture_system->invalidate_all(true);
        m_texture_system->attribute("searchpath", project_search_paths);
    }

    // Also use the project search paths to look for OpenImageIO plugins.
    m_texture_system->attribute("plugin_searchpath", project_search_paths);

    // Initialize OSL.
    m_renderer_services->initialize(m_texture_store);

    // Create renderer components.
    m_components.reset(
        new RendererComponents(
            get_project(),
            get_params(),
            tile_callback_factory,
            m_texture_store,
            *m_texture_system,
            *m_shading_system));

    // Set OSL search paths.
    std::string prev_osl_search_paths;
    m_shading_system->getattribute("searchpath:shader", prev_osl_search_paths);
    if (prev_osl_search_paths != project_search_paths)
    {
        RENDERER_LOG_INFO("setting osl shader search paths to %s", project_search_paths.c_str());
        get_project().get_scene()->release_optimized_osl_shader_groups();
        m_shading_system->attribute("searchpath:shader", project_search_paths);
    }

    // Initialize the shader compiler, if the OSL headers are found.
    if (resource_search_paths.exist("stdosl.h"))
    {
        const APIString stdosl_path = resource_search_paths.qualify("stdosl.h");
        RENDERER_LOG_INFO("found OSL headers in %s", stdosl_path.c_str());
        m_osl_compiler = ShaderCompilerFactory::create(stdosl_path.c_str());
    }
    else
        RENDERER_LOG_INFO("OSL headers not found.");

    // Re-optimize shader groups that need updating.
    if (!get_project().get_scene()->create_optimized_osl_shader_groups(
            *m_shading_system,
            m_osl_compiler.get(),
            &abort_switch))
    {
        return false;
    }

    return m_components->create();
}

bool CPURenderDevice::build_or_update_scene()
{
    // Updating the trace context causes ray tracing acceleration structures to be updated or rebuilt.
    get_project().update_trace_context();
    return true;
}

bool CPURenderDevice::load_checkpoint(Frame& frame, const size_t pass_count)
{
    return
        frame.load_checkpoint(
            &m_components->get_shading_result_framebuffer_factory(),
            pass_count);
}

IRendererController* CPURenderDevice::get_frame_renderer_controller()
{
    return m_components->get_frame_renderer().get_renderer_controller();
}

bool CPURenderDevice::on_render_begin(
    OnRenderBeginRecorder&  recorder,
    IAbortSwitch*           abort_switch)
{
    return m_components->on_render_begin(recorder, abort_switch);
}

bool CPURenderDevice::on_frame_begin(
    OnFrameBeginRecorder&   recorder,
    IAbortSwitch*           abort_switch)
{
    return m_components->on_frame_begin(recorder, abort_switch);
}

const IRenderContext& CPURenderDevice::get_render_context() const
{
    return m_context;
}

IRendererController::Status CPURenderDevice::render_frame(
    ITileCallbackFactory*   tile_callback_factory,
    IRendererController&    renderer_controller,
    IAbortSwitch&           abort_switch)
{
    IFrameRenderer& frame_renderer = m_components->get_frame_renderer();
    assert(!frame_renderer.is_rendering());

    // Start rendering the frame.
    frame_renderer.start_rendering();

    // Wait until the frame is completed or rendering is aborted.
    const IRendererController::Status status =
        wait_for_event(frame_renderer, renderer_controller);

    switch (status)
    {
      case IRendererController::TerminateRendering:
      case IRendererController::AbortRendering:
      case IRendererController::ReinitializeRendering:
        frame_renderer.terminate_rendering();
        break;

      case IRendererController::RestartRendering:
        frame_renderer.stop_rendering();
        break;

      assert_otherwise;
    }

    assert(!frame_renderer.is_rendering());

    return status;
}

void CPURenderDevice::print_settings() const
{
    m_components->print_settings();
}

Dictionary CPURenderDevice::get_metadata()
{
    Dictionary metadata;
    return metadata;
}

}   // namespace renderer
<commit_msg>Enable OIIO's automip<commit_after>
//
// This source file is part of appleseed.
// Visit https://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2019 Esteban Tovagliari, The appleseedhq Organization
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "cpurenderdevice.h"

// appleseed.renderer headers.
#include "renderer/global/globallogger.h"
#include "renderer/kernel/rendering/oiioerrorhandler.h"
#include "renderer/kernel/rendering/renderercomponents.h"
#include "renderer/kernel/rendering/rendererservices.h"
#include "renderer/kernel/shading/closures.h"
#include "renderer/kernel/shading/oslshadingsystem.h"
#include "renderer/kernel/texturing/oiiotexturesystem.h"
#include "renderer/kernel/texturing/texturestore.h"
#include "renderer/modeling/frame/frame.h"
#include "renderer/modeling/project/project.h"
#include "renderer/modeling/scene/scene.h"

// appleseed.foundation headers.
#include "foundation/containers/dictionary.h"
#include "foundation/utility/searchpaths.h"

// Standard headers.
#include <cstddef>
#include <string>

using namespace foundation;

namespace renderer
{

CPURenderDevice::CPURenderDevice(
    Project&                project,
    const ParamArray&       params)
  : RenderDeviceBase(project, params)
  , m_texture_store(*project.get_scene(), params.child("texture_store"))
{
    m_error_handler = new OIIOErrorHandler();
#ifndef NDEBUG
    m_error_handler->verbosity(OIIO::ErrorHandler::VERBOSE);
#endif

    RENDERER_LOG_DEBUG("creating oiio texture system...");
    m_texture_system = OIIOTextureSystemFactory::create(false);
    m_texture_system->attribute("automip", 1);
    m_texture_system->attribute("accept_untiled", 1);
    m_texture_system->attribute("accept_unmipped", 1);
    m_texture_system->attribute("gray_to_rgb", 1);
    m_texture_system->attribute("latlong_up", "y");
    m_texture_system->attribute("flip_t", 1);

    m_renderer_services =
        new RendererServices(
            project,
            reinterpret_cast<OIIO::TextureSystem&>(*m_texture_system));

    RENDERER_LOG_DEBUG("creating osl shading system...");
    m_shading_system =
        OSLShadingSystemFactory::create(
            m_renderer_services,
            m_texture_system,
            m_error_handler);
    m_shading_system->attribute("lockgeom", 1);
    m_shading_system->attribute("colorspace", "Linear");
    m_shading_system->attribute("commonspace", "world");
    m_shading_system->attribute("statistics:level", 1);
    m_shading_system->attribute(
        "raytypes",
        OSL::TypeDesc(
            OSL::TypeDesc::STRING,
            static_cast<int>(VisibilityFlags::Count)),
        VisibilityFlags::Names);
#ifndef NDEBUG
    m_shading_system->attribute("compile_report", 1);
    m_shading_system->attribute("countlayerexecs", 1);
    m_shading_system->attribute("clearmemory", 1);
#endif

    // Register appleseed's closures into OSL's shading system.
    register_closures(*m_shading_system);
}

CPURenderDevice::~CPURenderDevice()
{
    m_components.reset();

    RENDERER_LOG_DEBUG("destroying osl shading system...");
    get_project().get_scene()->release_optimized_osl_shader_groups();
    m_shading_system->release();
    delete m_renderer_services;

    const std::string stats = m_texture_system->getstats();
    const std::string modified_stats = prefix_all_lines(trim_both(stats), "oiio: ");
    RENDERER_LOG_DEBUG("%s", modified_stats.c_str());

    RENDERER_LOG_DEBUG("destroying oiio texture system...");
    m_texture_system->release();
    delete m_error_handler;

    // Print texture store performance statistics.
    RENDERER_LOG_DEBUG("%s", m_texture_store.get_statistics().to_string().c_str());
}

bool CPURenderDevice::initialize(
    const SearchPaths&      resource_search_paths,
    ITileCallbackFactory*   tile_callback_factory,
    IAbortSwitch&           abort_switch)
{
    // Construct a search paths string from the project's search paths.
    const std::string project_search_paths =
        to_string(get_project().search_paths().to_string_reversed(SearchPaths::osl_path_separator()));

    // Initialize OIIO.
    const size_t texture_cache_size_bytes =
        get_params().child("texture_store").get_optional<size_t>(
            "max_size",
            TextureStore::get_default_size());
    RENDERER_LOG_INFO(
        "setting oiio texture cache size to %s.",
        pretty_size(texture_cache_size_bytes).c_str());
    const float texture_cache_size_mb =
        static_cast<float>(texture_cache_size_bytes) / (1024 * 1024);
    m_texture_system->attribute("max_memory_MB", texture_cache_size_mb);

    // Set OIIO search paths.
    std::string prev_oiio_search_path;
    m_texture_system->getattribute("searchpath", prev_oiio_search_path);
    if (prev_oiio_search_path != project_search_paths)
    {
        RENDERER_LOG_INFO("setting oiio search paths to %s", project_search_paths.c_str());
        m_texture_system->invalidate_all(true);
        m_texture_system->attribute("searchpath", project_search_paths);
    }

    // Also use the project search paths to look for OpenImageIO plugins.
    m_texture_system->attribute("plugin_searchpath", project_search_paths);

    // Initialize OSL.
    m_renderer_services->initialize(m_texture_store);

    // Create renderer components.
    m_components.reset(
        new RendererComponents(
            get_project(),
            get_params(),
            tile_callback_factory,
            m_texture_store,
            *m_texture_system,
            *m_shading_system));

    // Set OSL search paths.
    std::string prev_osl_search_paths;
    m_shading_system->getattribute("searchpath:shader", prev_osl_search_paths);
    if (prev_osl_search_paths != project_search_paths)
    {
        RENDERER_LOG_INFO("setting osl shader search paths to %s", project_search_paths.c_str());
        get_project().get_scene()->release_optimized_osl_shader_groups();
        m_shading_system->attribute("searchpath:shader", project_search_paths);
    }

    // Initialize the shader compiler, if the OSL headers are found.
    if (resource_search_paths.exist("stdosl.h"))
    {
        const APIString stdosl_path = resource_search_paths.qualify("stdosl.h");
        RENDERER_LOG_INFO("found OSL headers in %s", stdosl_path.c_str());
        m_osl_compiler = ShaderCompilerFactory::create(stdosl_path.c_str());
    }
    else
        RENDERER_LOG_INFO("OSL headers not found.");

    // Re-optimize shader groups that need updating.
    if (!get_project().get_scene()->create_optimized_osl_shader_groups(
            *m_shading_system,
            m_osl_compiler.get(),
            &abort_switch))
    {
        return false;
    }

    return m_components->create();
}

bool CPURenderDevice::build_or_update_scene()
{
    // Updating the trace context causes ray tracing acceleration structures to be updated or rebuilt.
    get_project().update_trace_context();
    return true;
}

bool CPURenderDevice::load_checkpoint(Frame& frame, const size_t pass_count)
{
    return
        frame.load_checkpoint(
            &m_components->get_shading_result_framebuffer_factory(),
            pass_count);
}

IRendererController* CPURenderDevice::get_frame_renderer_controller()
{
    return m_components->get_frame_renderer().get_renderer_controller();
}

bool CPURenderDevice::on_render_begin(
    OnRenderBeginRecorder&  recorder,
    IAbortSwitch*           abort_switch)
{
    return m_components->on_render_begin(recorder, abort_switch);
}

bool CPURenderDevice::on_frame_begin(
    OnFrameBeginRecorder&   recorder,
    IAbortSwitch*           abort_switch)
{
    return m_components->on_frame_begin(recorder, abort_switch);
}

const IRenderContext& CPURenderDevice::get_render_context() const
{
    return m_context;
}

IRendererController::Status CPURenderDevice::render_frame(
    ITileCallbackFactory*   tile_callback_factory,
    IRendererController&    renderer_controller,
    IAbortSwitch&           abort_switch)
{
    IFrameRenderer& frame_renderer = m_components->get_frame_renderer();
    assert(!frame_renderer.is_rendering());

    // Start rendering the frame.
    frame_renderer.start_rendering();

    // Wait until the frame is completed or rendering is aborted.
    const IRendererController::Status status =
        wait_for_event(frame_renderer, renderer_controller);

    switch (status)
    {
      case IRendererController::TerminateRendering:
      case IRendererController::AbortRendering:
      case IRendererController::ReinitializeRendering:
        frame_renderer.terminate_rendering();
        break;

      case IRendererController::RestartRendering:
        frame_renderer.stop_rendering();
        break;

      assert_otherwise;
    }

    assert(!frame_renderer.is_rendering());

    return status;
}

void CPURenderDevice::print_settings() const
{
    m_components->print_settings();
}

Dictionary CPURenderDevice::get_metadata()
{
    Dictionary metadata;
    return metadata;
}

}   // namespace renderer
<|endoftext|>


<commit_before>
//
// This source file is part of appleseed.
// Visit https://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2019 Esteban Tovagliari, The appleseedhq Organization
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "cpurenderdevice.h"

// appleseed.renderer headers.
#include "renderer/global/globallogger.h"
#include "renderer/kernel/rendering/oiioerrorhandler.h"
#include "renderer/kernel/rendering/renderercomponents.h"
#include "renderer/kernel/rendering/rendererservices.h"
#include "renderer/kernel/shading/closures.h"
#include "renderer/kernel/shading/oslshadingsystem.h"
#include "renderer/kernel/texturing/oiiotexturesystem.h"
#include "renderer/modeling/frame/frame.h"
#include "renderer/modeling/project/project.h"
#include "renderer/modeling/scene/scene.h"
#include "renderer/kernel/texturing/texturestore.h"

// appleseed.foundation headers.
#include "foundation/utility/containers/dictionary.h"
#include "foundation/utility/searchpaths.h"

// Standard headers.
#include <cstddef>
#include <string>

using namespace foundation;
using namespace std;

namespace renderer
{

CPURenderDevice::CPURenderDevice(
    Project&                project,
    const ParamArray&       params)
  : RenderDeviceBase(project, params)
  , m_texture_store(*project.get_scene(), params.child("texture_store"))
{
    m_error_handler = new OIIOErrorHandler();
#ifndef NDEBUG
    m_error_handler->verbosity(OIIO::ErrorHandler::VERBOSE);
#endif

    RENDERER_LOG_DEBUG("creating oiio texture system...");
    m_texture_system = OIIOTextureSystemFactory::create(false);
    m_texture_system->attribute("automip", 0);
    m_texture_system->attribute("accept_untiled", 1);
    m_texture_system->attribute("accept_unmipped", 1);
    m_texture_system->attribute("gray_to_rgb", 1);
    m_texture_system->attribute("latlong_up", "y");
    m_texture_system->attribute("flip_t", 1);

    m_renderer_services = new RendererServices(
        project,
        reinterpret_cast<OIIO::TextureSystem&>(*m_texture_system));

    RENDERER_LOG_DEBUG("creating osl shading system...");
    m_shading_system =
        OSLShadingSystemFactory::create(
            m_renderer_services,
            m_texture_system,
            m_error_handler);
    m_shading_system->attribute("lockgeom", 1);
    m_shading_system->attribute("colorspace", "Linear");
    m_shading_system->attribute("commonspace", "world");
    m_shading_system->attribute("statistics:level", 1);
    m_shading_system->attribute(
        "raytypes",
        OSL::TypeDesc(
            OSL::TypeDesc::STRING,
            static_cast<int>(VisibilityFlags::Count)),
        VisibilityFlags::Names);
#ifndef NDEBUG
    m_shading_system->attribute("compile_report", 1);
    m_shading_system->attribute("countlayerexecs", 1);
    m_shading_system->attribute("clearmemory", 1);
#endif

    // Register appleseed's closures into OSL's shading system.
    register_closures(*m_shading_system);
}

CPURenderDevice::~CPURenderDevice()
{
    RENDERER_LOG_DEBUG("destroying osl shading system...");
    get_project().get_scene()->release_optimized_osl_shader_groups();
    m_shading_system->release();
    delete m_renderer_services;

    const string stats = m_texture_system->getstats();
    const string modified_stats = prefix_all_lines(trim_both(stats), "oiio: ");
    RENDERER_LOG_DEBUG("%s", modified_stats.c_str());

    RENDERER_LOG_DEBUG("destroying oiio texture system...");
    m_texture_system->release();
    delete m_error_handler;

    // Print texture store performance statistics.
    RENDERER_LOG_DEBUG("%s", m_texture_store.get_statistics().to_string().c_str());
}

bool CPURenderDevice::initialize(
    const SearchPaths&      resource_search_paths,
    ITileCallbackFactory*   tile_callback_factory,
    IAbortSwitch&           abort_switch)
{
    // Construct a search paths string from the project's search paths.
    const string project_search_paths =
        to_string(get_project().search_paths().to_string_reversed(SearchPaths::osl_path_separator()));

    // Initialize OIIO.
    const size_t texture_cache_size_bytes =
        get_params().child("texture_store").get_optional<size_t>(
            "max_size",
            TextureStore::get_default_size());
    RENDERER_LOG_INFO(
        "setting oiio texture cache size to %s.",
        pretty_size(texture_cache_size_bytes).c_str());
    const float texture_cache_size_mb =
        static_cast<float>(texture_cache_size_bytes) / (1024 * 1024);
    m_texture_system->attribute("max_memory_MB", texture_cache_size_mb);

    // Set OIIO search paths.
    string prev_oiio_search_path;
    m_texture_system->getattribute("searchpath", prev_oiio_search_path);
    if (prev_oiio_search_path != project_search_paths)
    {
        RENDERER_LOG_INFO("setting oiio search paths to %s", project_search_paths.c_str());
        m_texture_system->invalidate_all(true);
        m_texture_system->attribute("searchpath", project_search_paths);
    }

    // Also use the project search paths to look for OpenImageIO plugins.
    m_texture_system->attribute("plugin_searchpath", project_search_paths);

    // Initialize OSL.
    m_renderer_services->initialize(m_texture_store);

    // Create renderer components.
    m_components.reset(
        new RendererComponents(
            get_project(),
            get_params(),
            tile_callback_factory,
            m_texture_store,
            *m_texture_system,
            *m_shading_system));

    // Set OSL search paths.
    string prev_osl_search_paths;
    m_shading_system->getattribute("searchpath:shader", prev_osl_search_paths);
    if (prev_osl_search_paths != project_search_paths)
    {
        RENDERER_LOG_INFO("setting osl shader search paths to %s", project_search_paths.c_str());
        get_project().get_scene()->release_optimized_osl_shader_groups();
        m_shading_system->attribute("searchpath:shader", project_search_paths);
    }

    // Initialize the shader compiler, if the OSL headers are found.
    if (resource_search_paths.exist("stdosl.h"))
    {
        const APIString stdosl_path = resource_search_paths.qualify("stdosl.h");
        RENDERER_LOG_INFO("found OSL headers in %s", stdosl_path.c_str());
        m_osl_compiler = ShaderCompilerFactory::create(stdosl_path.c_str());
    }
    else
        RENDERER_LOG_INFO("OSL headers not found.");

    // Re-optimize shader groups that need updating.
    if (!get_project().get_scene()->create_optimized_osl_shader_groups(
            *m_shading_system,
            m_osl_compiler.get(),
            &abort_switch))
    {
        return false;
    }

    return m_components->create();
}

bool CPURenderDevice::build_or_update_scene()
{
    // Updating the trace context causes ray tracing acceleration structures to be updated or rebuilt.
    get_project().update_trace_context();
    return true;
}

bool CPURenderDevice::load_checkpoint(Frame& frame, const size_t pass_count)
{
    return
        frame.load_checkpoint(
            &m_components->get_shading_result_framebuffer_factory(),
            pass_count);
}

IRendererController* CPURenderDevice::get_frame_renderer_controller()
{
    return m_components->get_frame_renderer().get_renderer_controller();
}

bool CPURenderDevice::on_render_begin(
    OnRenderBeginRecorder&  recorder,
    IAbortSwitch*           abort_switch)
{
    return m_components->on_render_begin(recorder, abort_switch);
}

bool CPURenderDevice::on_frame_begin(
    OnFrameBeginRecorder&   recorder,
    IAbortSwitch*           abort_switch)
{
    return m_components->on_frame_begin(recorder, abort_switch);
}

const IRenderContext& CPURenderDevice::get_render_context() const
{
    return m_context;
}

IRendererController::Status CPURenderDevice::render_frame(
    ITileCallbackFactory*   tile_callback_factory,
    IRendererController&    renderer_controller,
    IAbortSwitch&           abort_switch)
{
    IFrameRenderer& frame_renderer = m_components->get_frame_renderer();
    assert(!frame_renderer.is_rendering());

    // Start rendering the frame.
    frame_renderer.start_rendering();

    // Wait until the the frame is completed or rendering is aborted.
    const IRendererController::Status status =
        wait_for_event(frame_renderer, renderer_controller);

    switch (status)
    {
      case IRendererController::TerminateRendering:
      case IRendererController::AbortRendering:
      case IRendererController::ReinitializeRendering:
        frame_renderer.terminate_rendering();
        break;

      case IRendererController::RestartRendering:
        frame_renderer.stop_rendering();
        break;

      assert_otherwise;
    }

    assert(!frame_renderer.is_rendering());

    return status;
}

void CPURenderDevice::print_settings() const
{
    m_components->print_settings();
}

Dictionary CPURenderDevice::get_metadata()
{
    Dictionary metadata;
    return metadata;
}

}   // namespace renderer
<commit_msg>Fix rare crash of appleseed on exit<commit_after>
//
// This source file is part of appleseed.
// Visit https://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2019 Esteban Tovagliari, The appleseedhq Organization
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "cpurenderdevice.h"

// appleseed.renderer headers.
#include "renderer/global/globallogger.h"
#include "renderer/kernel/rendering/oiioerrorhandler.h"
#include "renderer/kernel/rendering/renderercomponents.h"
#include "renderer/kernel/rendering/rendererservices.h"
#include "renderer/kernel/shading/closures.h"
#include "renderer/kernel/shading/oslshadingsystem.h"
#include "renderer/kernel/texturing/oiiotexturesystem.h"
#include "renderer/modeling/frame/frame.h"
#include "renderer/modeling/project/project.h"
#include "renderer/modeling/scene/scene.h"
#include "renderer/kernel/texturing/texturestore.h"

// appleseed.foundation headers.
#include "foundation/utility/containers/dictionary.h"
#include "foundation/utility/searchpaths.h"

// Standard headers.
#include <cstddef>
#include <string>

using namespace foundation;
using namespace std;

namespace renderer
{

CPURenderDevice::CPURenderDevice(
    Project&                project,
    const ParamArray&       params)
  : RenderDeviceBase(project, params)
  , m_texture_store(*project.get_scene(), params.child("texture_store"))
{
    m_error_handler = new OIIOErrorHandler();
#ifndef NDEBUG
    m_error_handler->verbosity(OIIO::ErrorHandler::VERBOSE);
#endif

    RENDERER_LOG_DEBUG("creating oiio texture system...");
    m_texture_system = OIIOTextureSystemFactory::create(false);
    m_texture_system->attribute("automip", 0);
    m_texture_system->attribute("accept_untiled", 1);
    m_texture_system->attribute("accept_unmipped", 1);
    m_texture_system->attribute("gray_to_rgb", 1);
    m_texture_system->attribute("latlong_up", "y");
    m_texture_system->attribute("flip_t", 1);

    m_renderer_services =
        new RendererServices(
            project,
            reinterpret_cast<OIIO::TextureSystem&>(*m_texture_system));

    RENDERER_LOG_DEBUG("creating osl shading system...");
    m_shading_system =
        OSLShadingSystemFactory::create(
            m_renderer_services,
            m_texture_system,
            m_error_handler);
    m_shading_system->attribute("lockgeom", 1);
    m_shading_system->attribute("colorspace", "Linear");
    m_shading_system->attribute("commonspace", "world");
    m_shading_system->attribute("statistics:level", 1);
    m_shading_system->attribute(
        "raytypes",
        OSL::TypeDesc(
            OSL::TypeDesc::STRING,
            static_cast<int>(VisibilityFlags::Count)),
        VisibilityFlags::Names);
#ifndef NDEBUG
    m_shading_system->attribute("compile_report", 1);
    m_shading_system->attribute("countlayerexecs", 1);
    m_shading_system->attribute("clearmemory", 1);
#endif

    // Register appleseed's closures into OSL's shading system.
    register_closures(*m_shading_system);
}

CPURenderDevice::~CPURenderDevice()
{
    m_components.reset();

    RENDERER_LOG_DEBUG("destroying osl shading system...");
    get_project().get_scene()->release_optimized_osl_shader_groups();
    m_shading_system->release();
    delete m_renderer_services;

    const string stats = m_texture_system->getstats();
    const string modified_stats = prefix_all_lines(trim_both(stats), "oiio: ");
    RENDERER_LOG_DEBUG("%s", modified_stats.c_str());

    RENDERER_LOG_DEBUG("destroying oiio texture system...");
    m_texture_system->release();
    delete m_error_handler;

    // Print texture store performance statistics.
    RENDERER_LOG_DEBUG("%s", m_texture_store.get_statistics().to_string().c_str());
}

bool CPURenderDevice::initialize(
    const SearchPaths&      resource_search_paths,
    ITileCallbackFactory*   tile_callback_factory,
    IAbortSwitch&           abort_switch)
{
    // Construct a search paths string from the project's search paths.
    const string project_search_paths =
        to_string(get_project().search_paths().to_string_reversed(SearchPaths::osl_path_separator()));

    // Initialize OIIO.
    const size_t texture_cache_size_bytes =
        get_params().child("texture_store").get_optional<size_t>(
            "max_size",
            TextureStore::get_default_size());
    RENDERER_LOG_INFO(
        "setting oiio texture cache size to %s.",
        pretty_size(texture_cache_size_bytes).c_str());
    const float texture_cache_size_mb =
        static_cast<float>(texture_cache_size_bytes) / (1024 * 1024);
    m_texture_system->attribute("max_memory_MB", texture_cache_size_mb);

    // Set OIIO search paths.
    string prev_oiio_search_path;
    m_texture_system->getattribute("searchpath", prev_oiio_search_path);
    if (prev_oiio_search_path != project_search_paths)
    {
        RENDERER_LOG_INFO("setting oiio search paths to %s", project_search_paths.c_str());
        m_texture_system->invalidate_all(true);
        m_texture_system->attribute("searchpath", project_search_paths);
    }

    // Also use the project search paths to look for OpenImageIO plugins.
    m_texture_system->attribute("plugin_searchpath", project_search_paths);

    // Initialize OSL.
    m_renderer_services->initialize(m_texture_store);

    // Create renderer components.
    m_components.reset(
        new RendererComponents(
            get_project(),
            get_params(),
            tile_callback_factory,
            m_texture_store,
            *m_texture_system,
            *m_shading_system));

    // Set OSL search paths.
    string prev_osl_search_paths;
    m_shading_system->getattribute("searchpath:shader", prev_osl_search_paths);
    if (prev_osl_search_paths != project_search_paths)
    {
        RENDERER_LOG_INFO("setting osl shader search paths to %s", project_search_paths.c_str());
        get_project().get_scene()->release_optimized_osl_shader_groups();
        m_shading_system->attribute("searchpath:shader", project_search_paths);
    }

    // Initialize the shader compiler, if the OSL headers are found.
    if (resource_search_paths.exist("stdosl.h"))
    {
        const APIString stdosl_path = resource_search_paths.qualify("stdosl.h");
        RENDERER_LOG_INFO("found OSL headers in %s", stdosl_path.c_str());
        m_osl_compiler = ShaderCompilerFactory::create(stdosl_path.c_str());
    }
    else
        RENDERER_LOG_INFO("OSL headers not found.");

    // Re-optimize shader groups that need updating.
    if (!get_project().get_scene()->create_optimized_osl_shader_groups(
            *m_shading_system,
            m_osl_compiler.get(),
            &abort_switch))
    {
        return false;
    }

    return m_components->create();
}

bool CPURenderDevice::build_or_update_scene()
{
    // Updating the trace context causes ray tracing acceleration structures to be updated or rebuilt.
    get_project().update_trace_context();
    return true;
}

bool CPURenderDevice::load_checkpoint(Frame& frame, const size_t pass_count)
{
    return
        frame.load_checkpoint(
            &m_components->get_shading_result_framebuffer_factory(),
            pass_count);
}

IRendererController* CPURenderDevice::get_frame_renderer_controller()
{
    return m_components->get_frame_renderer().get_renderer_controller();
}

bool CPURenderDevice::on_render_begin(
    OnRenderBeginRecorder&  recorder,
    IAbortSwitch*           abort_switch)
{
    return m_components->on_render_begin(recorder, abort_switch);
}

bool CPURenderDevice::on_frame_begin(
    OnFrameBeginRecorder&   recorder,
    IAbortSwitch*           abort_switch)
{
    return m_components->on_frame_begin(recorder, abort_switch);
}

const IRenderContext& CPURenderDevice::get_render_context() const
{
    return m_context;
}

IRendererController::Status CPURenderDevice::render_frame(
    ITileCallbackFactory*   tile_callback_factory,
    IRendererController&    renderer_controller,
    IAbortSwitch&           abort_switch)
{
    IFrameRenderer& frame_renderer = m_components->get_frame_renderer();
    assert(!frame_renderer.is_rendering());

    // Start rendering the frame.
    frame_renderer.start_rendering();

    // Wait until the the frame is completed or rendering is aborted.
    const IRendererController::Status status =
        wait_for_event(frame_renderer, renderer_controller);

    switch (status)
    {
      case IRendererController::TerminateRendering:
      case IRendererController::AbortRendering:
      case IRendererController::ReinitializeRendering:
        frame_renderer.terminate_rendering();
        break;

      case IRendererController::RestartRendering:
        frame_renderer.stop_rendering();
        break;

      assert_otherwise;
    }

    assert(!frame_renderer.is_rendering());

    return status;
}

void CPURenderDevice::print_settings() const
{
    m_components->print_settings();
}

Dictionary CPURenderDevice::get_metadata()
{
    Dictionary metadata;
    return metadata;
}

}   // namespace renderer
<|endoftext|>