<commit_before>/***********************************************************************************
** MIT License                                                                    **
**                                                                                **
** Copyright (c) 2018 Victor DENIS (victordenis01@gmail.com)                      **
**                                                                                **
** 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.                                                                      **
***********************************************************************************/

#pragma once
#ifndef SIELOBROWSER_ADDBOOKMARKDIALOG_HPP
#define SIELOBROWSER_ADDBOOKMARKDIALOG_HPP

#include <QDialog>
#include <QDialogButtonBox>
#include <QLabel>
#include <QLineEdit>
#include <QComboBox>

#include <QSpacerItem>

#include <QVBoxLayout>

namespace Sn {
class BookmarksManager;
class AddBookmarkProxyModel;

class AddBookmarkDialog: public QDialog {
Q_OBJECT

public:
	AddBookmarkDialog(const QString& url, const QString& title, QWidget* parent = nullptr,
					  BookmarksManager* bookmarksManager = nullptr);

private slots:
	void accept();

private:
	void setupUI();

	QString m_url{};

	QVBoxLayout* m_layout{nullptr};

	QLabel* m_description{nullptr};
	QLineEdit* m_name{nullptr};
	QComboBox* m_location{nullptr};

	QSpacerItem* m_spacer{nullptr};

	QDialogButtonBox* m_buttonBox{nullptr};

	BookmarksManager* m_bookmarksManager{nullptr};
	AddBookmarkProxyModel* m_proxyModel{nullptr};
};
}

#endif //SIELOBROWSER_ADDBOOKMARKDIALOG_HPP
<commit_msg>Add possibility to edit url<commit_after>/***********************************************************************************
** MIT License                                                                    **
**                                                                                **
** Copyright (c) 2018 Victor DENIS (victordenis01@gmail.com)                      **
**                                                                                **
** 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.                                                                      **
***********************************************************************************/

#pragma once
#ifndef SIELOBROWSER_ADDBOOKMARKDIALOG_HPP
#define SIELOBROWSER_ADDBOOKMARKDIALOG_HPP

#include <QDialog>
#include <QDialogButtonBox>
#include <QLabel>
#include <QLineEdit>
#include <QComboBox>

#include <QSpacerItem>

#include <QVBoxLayout>

namespace Sn {
class BookmarksManager;
class AddBookmarkProxyModel;

class AddBookmarkDialog: public QDialog {
Q_OBJECT

public:
	AddBookmarkDialog(const QString& url, const QString& title, QWidget* parent = nullptr,
					  BookmarksManager* bookmarksManager = nullptr);

private slots:
	void accept();

private:
	void setupUI();

	QString m_url{};

	QVBoxLayout* m_layout{nullptr};

	QLabel* m_description{nullptr};
	QLineEdit* m_name{nullptr};
        QLineEdit* m_urlEdit{nullptr};
	QComboBox* m_location{nullptr};

	QSpacerItem* m_spacer{nullptr};

	QDialogButtonBox* m_buttonBox{nullptr};

	BookmarksManager* m_bookmarksManager{nullptr};
	AddBookmarkProxyModel* m_proxyModel{nullptr};
};
}

#endif //SIELOBROWSER_ADDBOOKMARKDIALOG_HPP
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "CppUnitTest.h"
#include <RoundRobin.h>
#include "ExceptionThrowingRoundRobinTask.h"

using namespace CppRoundRobin;

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace CppRoundRobinTest
{
    TEST_CLASS(RoundRobinTests)
    {
    public:

        TEST_METHOD(GetPeriod)
        {
            RoundRobin robin(1);

            Assert::AreEqual(robin.GetPeriod(), 1);
        }

        TEST_METHOD(SetPeriod)
        {
            RoundRobin robin(5);
            robin.SetPeriod(6);

            Assert::AreEqual(robin.GetPeriod(), 6);
        }

        TEST_METHOD(RunSingleTask)
        {
            RoundRobin robin(1);

            std::shared_ptr<RoundRobinTask> task(new ExceptionThrowingRoundRobinTask(1));
            robin.AddTask(task);

            try
            {
                robin.TimerFired(); // force fire the timer
                robin.Run();
            }
            catch (int e)
            {
                Assert::AreEqual(30, e);
            }
        }
    };
}<commit_msg>random changes<commit_after>#include "stdafx.h"
#include "CppUnitTest.h"
#include <RoundRobin.h>
#include "ExceptionThrowingRoundRobinTask.h"

using namespace CppRoundRobin;

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace CppRoundRobinTest
{
	TEST_CLASS(RoundRobinTests)
	{
	public:

		TEST_METHOD(GetPeriod)
		{
			RoundRobin robin(1);

			Assert::AreEqual(robin.GetPeriod(), 1);
		}

		TEST_METHOD(SetPeriod)
		{
			RoundRobin robin(5);
			robin.SetPeriod(6);

			Assert::AreEqual(robin.GetPeriod(), 6);
		}

		TEST_METHOD(RunSingleTask)
		{
			RoundRobin robin(1);

			std::shared_ptr<RoundRobinTask> task(new ExceptionThrowingRoundRobinTask(1));
			robin.AddTask(task);

			try
			{
				robin.TimerFired(); // force fire the timer
				robin.Run();
			}
			catch (int e)
			{
				Assert::AreEqual(30, e);
			}
		}

		TEST_METHOD(RunMultipleTasks)
		{
			RoundRobin robin(1);

			std::shared_ptr<RoundRobinTask> task(new ExceptionThrowingRoundRobinTask(1000));
			robin.AddTask(task);

			try
			{
				robin.Run();
			}
			catch (int e)
			{
				Assert::AreEqual(30, e);
			}
		}
	};
}<|endoftext|>


<commit_before>/*
   Copyright (c) 2010 Aldo J. Nunez

   Licensed under the Apache License, Version 2.0.
   See the LICENSE text file for details.
*/

#include "Common.h"
#include "StackFrame.h"
#include "Thread.h"
#include "Module.h"
#include "SingleDocumentContext.h"
#include "CodeContext.h"
#include "ExprContext.h"
#include "FrameProperty.h"
#include "RegisterSet.h"

namespace Mago
{
    StackFrame::StackFrame()
        :   mPC( 0 )
    {
        memset( &mFuncSH, 0, sizeof mFuncSH );
        memset( &mBlockSH, 0, sizeof mBlockSH );
    }

    StackFrame::~StackFrame()
    {
    }

    HRESULT StackFrame::GetCodeContext(
       IDebugCodeContext2** ppCodeCxt )
    {
        if ( ppCodeCxt == NULL )
            return E_INVALIDARG;

        HRESULT hr = S_OK;
        RefPtr<CodeContext> codeContext;

        hr = MakeCComObject( codeContext );
        if ( FAILED( hr ) )
            return hr;

        CComPtr<IDebugDocumentContext2> docContext;
        hr = GetDocumentContext( &docContext );
        if ( FAILED( hr ) )
            return hr;

        hr = codeContext->Init( mPC, mModule, docContext );
        if ( FAILED( hr ) )
            return hr;

        return codeContext->QueryInterface( __uuidof( IDebugCodeContext2 ), (void**) ppCodeCxt );
    }

    HRESULT StackFrame::GetDocumentContext(
       IDebugDocumentContext2** ppCxt )
    {
        if ( ppCxt == NULL )
            return E_INVALIDARG;

        HRESULT hr = S_OK;
        RefPtr<SingleDocumentContext>   docContext;
        LineInfo    line;

        hr = MakeCComObject( docContext );
        if ( FAILED( hr ) )
            return hr;

        hr = GetLineInfo( line );
        if ( FAILED( hr ) )
            return hr;

        hr = docContext->Init( line.Filename, line.LineBegin, line.LineEnd, line.LangName, line.LangGuid );
        if ( FAILED( hr ) )
            return hr;

        return docContext->QueryInterface( __uuidof( IDebugDocumentContext2 ), (void**) ppCxt );
    }

    HRESULT StackFrame::GetName(
       BSTR* pbstrName )
    {
        return E_NOTIMPL;
    }

    HRESULT StackFrame::GetInfo(
       FRAMEINFO_FLAGS dwFieldSpec,
       UINT            nRadix,
       FRAMEINFO*      pFrameInfo )
    {
        if ( pFrameInfo == NULL )
            return E_INVALIDARG;

        HRESULT hr = S_OK;

        pFrameInfo->m_dwValidFields = 0;

        if ( (dwFieldSpec & FIF_FRAME) != 0 )
        {
            hr = QueryInterface( __uuidof( IDebugStackFrame2 ), (void**) &pFrameInfo->m_pFrame );
            _ASSERT( hr == S_OK );
            pFrameInfo->m_dwValidFields |= FIF_FRAME;
        }

        if ( (dwFieldSpec & FIF_DEBUG_MODULEP) != 0 )
        {
            if ( mModule.Get() != NULL )
            {
                hr = mModule->QueryInterface( __uuidof( IDebugModule2 ), (void**) &pFrameInfo->m_pModule );
                _ASSERT( hr == S_OK );
                pFrameInfo->m_dwValidFields |= FIF_DEBUG_MODULEP;
            }
        }

        if ( (dwFieldSpec & FIF_STACKRANGE) != 0 )
        {
#if 0
            if ( mDiaStackFrame != NULL )
            {
                // TODO: review all this
                UINT64  base = 0;
                DWORD   size = 0;

                mDiaStackFrame->get_base( &base );
                mDiaStackFrame->get_size( &size );

                pFrameInfo->m_addrMax = base;
                pFrameInfo->m_addrMin = base - size;
                pFrameInfo->m_dwValidFields |= FIF_STACKRANGE;
            }
#endif
        }

        if ( (dwFieldSpec & FIF_DEBUGINFO) != 0 )
        {
            if ( mModule.Get() != NULL )
            {
                RefPtr<MagoST::ISession>    session;

                pFrameInfo->m_fHasDebugInfo = mModule->GetSymbolSession( session );
            }
            else
                pFrameInfo->m_fHasDebugInfo = FALSE;

            pFrameInfo->m_dwValidFields |= FIF_DEBUGINFO;
        }

        if ( (dwFieldSpec & FIF_FUNCNAME) != 0 )
        {
            hr = GetFunctionName( &pFrameInfo->m_bstrFuncName );
            if ( SUCCEEDED( hr ) )
                pFrameInfo->m_dwValidFields |= FIF_FUNCNAME;
        }

        if ( (dwFieldSpec & FIF_RETURNTYPE) != 0 )
        {
            //pFrameInfo->m_bstrReturnType;
            //pFrameInfo->m_dwValidFields |= FIF_RETURNTYPE;
        }

        if ( (dwFieldSpec & FIF_ARGS) != 0 )
        {
            //pFrameInfo->m_bstrArgs;
            //pFrameInfo->m_dwValidFields |= FIF_ARGS;
        }

        if ( (dwFieldSpec & FIF_LANGUAGE) != 0 )
        {
            pFrameInfo->m_bstrLanguage = SysAllocString( L"D" );
            pFrameInfo->m_dwValidFields |= FIF_LANGUAGE;
        }

        if ( (dwFieldSpec & FIF_MODULE) != 0 )
        {
            //pFrameInfo->m_bstrModule;
            //pFrameInfo->m_dwValidFields |= FIF_MODULE;
        }

        //FIF_STALECODE m_fStaleCode
        //FIF_ANNOTATEDFRAME m_fAnnotatedFrame

        return S_OK;
    }

    HRESULT StackFrame::GetPhysicalStackRange(
       UINT64* paddrMin,
       UINT64* paddrMax )
    {
        return E_NOTIMPL;
    }

    HRESULT StackFrame::GetExpressionContext(
       IDebugExpressionContext2** ppExprCxt )
    {
        OutputDebugStringA( "StackFrame::GetExpressionContext\n" );

        HRESULT hr = S_OK;

        if ( mModule == NULL )
            return E_NOT_FOUND;

        hr = MakeExprContext();
        if ( FAILED( hr ) )
            return hr;

        *ppExprCxt = mExprContext;
        (*ppExprCxt)->AddRef();
        return S_OK;
    }

    HRESULT StackFrame::MakeExprContext()
    {
        HRESULT hr = S_OK;

        // ignore any error, because we don't have to have symbols for expression eval
        hr = FindFunction();

        if ( mExprContext == NULL )
        {
            GuardedArea guard( mExprContextGuard );

            if ( mExprContext == NULL )
            {
                RefPtr<ExprContext>         exprContext;

                hr = MakeCComObject( exprContext );
                if ( FAILED( hr ) )
                    return hr;

                hr = exprContext->Init( mModule, mThread, mFuncSH, mBlockSH, mPC, mRegSet );
                if ( FAILED( hr ) )
                    return hr;

                mExprContext = exprContext;
            }
        }

        return S_OK;
    }

    HRESULT StackFrame::GetLanguageInfo(
       BSTR* pbstrLanguage,
       GUID* pguidLanguage )
    {
        return E_NOTIMPL;
    }

    HRESULT StackFrame::GetDebugProperty(
       IDebugProperty2** ppDebugProp )
    {
        OutputDebugStringA( "StackFrame::GetDebugProperty\n" );

        if ( ppDebugProp == NULL )
            return E_INVALIDARG;

        HRESULT hr = S_OK;
        RefPtr<FrameProperty>   frameProp;

        hr = MakeExprContext();
        if ( FAILED( hr ) )
            return hr;

        hr = MakeCComObject( frameProp );
        if ( FAILED( hr ) )
            return hr;

        hr = frameProp->Init( mRegSet, mExprContext );
        if ( FAILED( hr ) )
            return hr;

        *ppDebugProp = frameProp.Detach();
        return S_OK;
    }

    HRESULT StackFrame::EnumProperties(
       DEBUGPROP_INFO_FLAGS      dwFieldSpec,
       UINT                      nRadix,
       REFIID                    refiid,
       DWORD                     dwTimeout,
       ULONG*                    pcelt,
       IEnumDebugPropertyInfo2** ppEnum )
    {
        OutputDebugStringA( "StackFrame::EnumProperties\n" );

        HRESULT hr = S_OK;
        CComPtr<IDebugProperty2>    rootProp;

        hr = GetDebugProperty( &rootProp );
        if ( FAILED( hr ) )
            return hr;

        hr = rootProp->EnumChildren(
            dwFieldSpec,
            nRadix,
            refiid,
            DBG_ATTRIB_ALL,
            NULL,
            dwTimeout,
            ppEnum );
        if ( FAILED( hr ) )
            return hr;

        if ( pcelt != NULL )
        {
            hr = (*ppEnum)->GetCount( pcelt );
            if ( FAILED( hr ) )
                return hr;
        }

        return S_OK;
    }

    HRESULT StackFrame::GetThread(
       IDebugThread2** ppThread )
    {
        if ( ppThread == NULL )
            return E_INVALIDARG;

        return mThread->QueryInterface( __uuidof( IDebugThread2 ), (void**) ppThread );
    }

    //----------------------------------------------------------------------------

    void StackFrame::Init(
        Address pc,
        IRegisterSet* regSet,
        Thread* thread,
        Module* module )
    {
        _ASSERT( regSet != NULL );
        _ASSERT( thread != NULL );
        _ASSERT( module != NULL );

        mPC = pc;
        mRegSet = regSet;
        mThread = thread;
        mModule = module;
    }

    HRESULT StackFrame::GetLineInfo( LineInfo& info )
    {
        HRESULT hr = S_OK;
        RefPtr<MagoST::ISession>    session;

        if ( mModule.Get() == NULL )
            return E_NOT_FOUND;

        if ( !mModule->GetSymbolSession( session ) )
            return E_NOT_FOUND;

        uint16_t    sec = 0;
        uint32_t    offset = 0;
        sec = session->GetSecOffsetFromVA( mPC, offset );
        if ( sec == 0 )
            return E_FAIL;

        MagoST::LineNumber line = { 0 };
        if ( !session->FindLine( sec, offset, line ) )
            return E_FAIL;

        info.LineBegin.dwLine = line.Number;
        //info.LineEnd.dwLine = line.NumberEnd;
        info.LineEnd.dwLine = line.Number;
        info.LineBegin.dwColumn = 0;
        info.LineEnd.dwColumn = 0;

        info.LineBegin.dwLine--;
        info.LineEnd.dwLine--;

        // if there's no column info, then these are 0
        if ( info.LineBegin.dwColumn > 0 )
            info.LineBegin.dwColumn--;
        if ( info.LineEnd.dwColumn > 0 )
            info.LineEnd.dwColumn--;

        MagoST::FileInfo    fileInfo = { 0 };
        hr = session->GetFileInfo( line.CompilandIndex, line.FileIndex, fileInfo );
        if ( FAILED( hr ) )
            return hr;

        hr = Utf8To16( fileInfo.Name, fileInfo.NameLength, info.Filename.m_str );
        if ( FAILED( hr ) )
            return hr;

        // TODO: from the compiland we're supposed to get the language
        info.LangName = L"D";
        info.LangGuid = GetDLanguageId();

        return hr;
    }

    HRESULT StackFrame::GetFunctionName( BSTR* funcName )
    {
        _ASSERT( funcName != NULL );
        HRESULT hr = S_OK;

        hr = GetFunctionNameWithSymbols( funcName );
        if ( FAILED( hr ) )
        {
            hr = GetFunctionNameWithAddress( funcName );
        }

        return hr;
    }

    HRESULT StackFrame::GetFunctionNameWithAddress( BSTR* funcName )
    {
        _ASSERT( funcName != NULL );
        wchar_t addrStr[ 8 + 1 ] = L"";

        _ASSERT( sizeof mPC == 4 );
        swprintf_s( addrStr, L"%08x", mPC );

        *funcName = SysAllocString( addrStr );
        if ( *funcName == NULL )
            return E_OUTOFMEMORY;

        return S_OK;
    }

    HRESULT StackFrame::GetFunctionNameWithSymbols( BSTR* funcName )
    {
        _ASSERT( funcName != NULL );
        HRESULT hr = S_OK;
        RefPtr<MagoST::ISession>    session;
        MagoST::SymInfoData         infoData = { 0 };
        MagoST::ISymbolInfo*        symInfo = NULL;

        if ( mModule.Get() == NULL )
            return E_NOT_FOUND;

        if ( !mModule->GetSymbolSession( session ) )
            return E_NOT_FOUND;

        hr = FindFunction();
        if ( FAILED( hr ) )
            return hr;

        hr = session->GetSymbolInfo( mFuncSH, infoData, symInfo );
        if ( FAILED( hr ) )
            return hr;

        PasString*  pstrName = NULL;
        if ( !symInfo->GetName( pstrName ) )
            return E_NOT_FOUND;

        hr = Utf8To16( pstrName->GetName(), pstrName->GetLength(), *funcName );
        if ( FAILED( hr ) )
            return hr;

        // for reference: you get the language by going to a lexical ancestor
        // that's a compiland, then you get a compiland detail from it

        return hr;
    }

    HRESULT StackFrame::FindFunction()
    {
        HRESULT hr = S_OK;
        RefPtr<MagoST::ISession>    session;
        MagoST::SymHandle           symHandle = { 0 };

        // already found
        if ( memcmp( &mFuncSH, &symHandle, sizeof mFuncSH ) != 0 )
            return S_OK;

        if ( mModule.Get() == NULL )
            return E_NOT_FOUND;

        if ( !mModule->GetSymbolSession( session ) )
            return E_NOT_FOUND;

        uint16_t    sec = 0;
        uint32_t    offset = 0;
        sec = session->GetSecOffsetFromVA( mPC, offset );
        if ( sec == 0 )
            return E_NOT_FOUND;

        // TODO: verify that it's a function or public symbol (or something else?)
        hr = session->FindOuterSymbolByAddr( MagoST::SymHeap_GlobalSymbols, sec, offset, symHandle );
        if ( FAILED( hr ) )
        {
            hr = session->FindOuterSymbolByAddr( MagoST::SymHeap_StaticSymbols, sec, offset, symHandle );
            if ( FAILED( hr ) )
            {
                hr = session->FindOuterSymbolByAddr( MagoST::SymHeap_PublicSymbols, sec, offset, symHandle );
                if ( FAILED( hr ) )
                    return hr;
            }
        }

        mFuncSH = symHandle;

        hr = session->FindInnermostSymbol( mFuncSH, sec, offset, mBlockSH );
        // it might be a public symbol, which doesn't have anything: blocks, args, or locals

        return S_OK;
    }
}
<commit_msg>Removing an assert that was firing, even though it didn't need to. It was firing, because sometimes the module that an address in the callstack is in isn't found.  That's expected sometimes.<commit_after>/*
   Copyright (c) 2010 Aldo J. Nunez

   Licensed under the Apache License, Version 2.0.
   See the LICENSE text file for details.
*/

#include "Common.h"
#include "StackFrame.h"
#include "Thread.h"
#include "Module.h"
#include "SingleDocumentContext.h"
#include "CodeContext.h"
#include "ExprContext.h"
#include "FrameProperty.h"
#include "RegisterSet.h"

namespace Mago
{
    StackFrame::StackFrame()
        :   mPC( 0 )
    {
        memset( &mFuncSH, 0, sizeof mFuncSH );
        memset( &mBlockSH, 0, sizeof mBlockSH );
    }

    StackFrame::~StackFrame()
    {
    }

    HRESULT StackFrame::GetCodeContext(
       IDebugCodeContext2** ppCodeCxt )
    {
        if ( ppCodeCxt == NULL )
            return E_INVALIDARG;

        HRESULT hr = S_OK;
        RefPtr<CodeContext> codeContext;

        hr = MakeCComObject( codeContext );
        if ( FAILED( hr ) )
            return hr;

        CComPtr<IDebugDocumentContext2> docContext;
        hr = GetDocumentContext( &docContext );
        if ( FAILED( hr ) )
            return hr;

        hr = codeContext->Init( mPC, mModule, docContext );
        if ( FAILED( hr ) )
            return hr;

        return codeContext->QueryInterface( __uuidof( IDebugCodeContext2 ), (void**) ppCodeCxt );
    }

    HRESULT StackFrame::GetDocumentContext(
       IDebugDocumentContext2** ppCxt )
    {
        if ( ppCxt == NULL )
            return E_INVALIDARG;

        HRESULT hr = S_OK;
        RefPtr<SingleDocumentContext>   docContext;
        LineInfo    line;

        hr = MakeCComObject( docContext );
        if ( FAILED( hr ) )
            return hr;

        hr = GetLineInfo( line );
        if ( FAILED( hr ) )
            return hr;

        hr = docContext->Init( line.Filename, line.LineBegin, line.LineEnd, line.LangName, line.LangGuid );
        if ( FAILED( hr ) )
            return hr;

        return docContext->QueryInterface( __uuidof( IDebugDocumentContext2 ), (void**) ppCxt );
    }

    HRESULT StackFrame::GetName(
       BSTR* pbstrName )
    {
        return E_NOTIMPL;
    }

    HRESULT StackFrame::GetInfo(
       FRAMEINFO_FLAGS dwFieldSpec,
       UINT            nRadix,
       FRAMEINFO*      pFrameInfo )
    {
        if ( pFrameInfo == NULL )
            return E_INVALIDARG;

        HRESULT hr = S_OK;

        pFrameInfo->m_dwValidFields = 0;

        if ( (dwFieldSpec & FIF_FRAME) != 0 )
        {
            hr = QueryInterface( __uuidof( IDebugStackFrame2 ), (void**) &pFrameInfo->m_pFrame );
            _ASSERT( hr == S_OK );
            pFrameInfo->m_dwValidFields |= FIF_FRAME;
        }

        if ( (dwFieldSpec & FIF_DEBUG_MODULEP) != 0 )
        {
            if ( mModule.Get() != NULL )
            {
                hr = mModule->QueryInterface( __uuidof( IDebugModule2 ), (void**) &pFrameInfo->m_pModule );
                _ASSERT( hr == S_OK );
                pFrameInfo->m_dwValidFields |= FIF_DEBUG_MODULEP;
            }
        }

        if ( (dwFieldSpec & FIF_STACKRANGE) != 0 )
        {
#if 0
            if ( mDiaStackFrame != NULL )
            {
                // TODO: review all this
                UINT64  base = 0;
                DWORD   size = 0;

                mDiaStackFrame->get_base( &base );
                mDiaStackFrame->get_size( &size );

                pFrameInfo->m_addrMax = base;
                pFrameInfo->m_addrMin = base - size;
                pFrameInfo->m_dwValidFields |= FIF_STACKRANGE;
            }
#endif
        }

        if ( (dwFieldSpec & FIF_DEBUGINFO) != 0 )
        {
            if ( mModule.Get() != NULL )
            {
                RefPtr<MagoST::ISession>    session;

                pFrameInfo->m_fHasDebugInfo = mModule->GetSymbolSession( session );
            }
            else
                pFrameInfo->m_fHasDebugInfo = FALSE;

            pFrameInfo->m_dwValidFields |= FIF_DEBUGINFO;
        }

        if ( (dwFieldSpec & FIF_FUNCNAME) != 0 )
        {
            hr = GetFunctionName( &pFrameInfo->m_bstrFuncName );
            if ( SUCCEEDED( hr ) )
                pFrameInfo->m_dwValidFields |= FIF_FUNCNAME;
        }

        if ( (dwFieldSpec & FIF_RETURNTYPE) != 0 )
        {
            //pFrameInfo->m_bstrReturnType;
            //pFrameInfo->m_dwValidFields |= FIF_RETURNTYPE;
        }

        if ( (dwFieldSpec & FIF_ARGS) != 0 )
        {
            //pFrameInfo->m_bstrArgs;
            //pFrameInfo->m_dwValidFields |= FIF_ARGS;
        }

        if ( (dwFieldSpec & FIF_LANGUAGE) != 0 )
        {
            pFrameInfo->m_bstrLanguage = SysAllocString( L"D" );
            pFrameInfo->m_dwValidFields |= FIF_LANGUAGE;
        }

        if ( (dwFieldSpec & FIF_MODULE) != 0 )
        {
            //pFrameInfo->m_bstrModule;
            //pFrameInfo->m_dwValidFields |= FIF_MODULE;
        }

        //FIF_STALECODE m_fStaleCode
        //FIF_ANNOTATEDFRAME m_fAnnotatedFrame

        return S_OK;
    }

    HRESULT StackFrame::GetPhysicalStackRange(
       UINT64* paddrMin,
       UINT64* paddrMax )
    {
        return E_NOTIMPL;
    }

    HRESULT StackFrame::GetExpressionContext(
       IDebugExpressionContext2** ppExprCxt )
    {
        OutputDebugStringA( "StackFrame::GetExpressionContext\n" );

        HRESULT hr = S_OK;

        if ( mModule == NULL )
            return E_NOT_FOUND;

        hr = MakeExprContext();
        if ( FAILED( hr ) )
            return hr;

        *ppExprCxt = mExprContext;
        (*ppExprCxt)->AddRef();
        return S_OK;
    }

    HRESULT StackFrame::MakeExprContext()
    {
        HRESULT hr = S_OK;

        // ignore any error, because we don't have to have symbols for expression eval
        hr = FindFunction();

        if ( mExprContext == NULL )
        {
            GuardedArea guard( mExprContextGuard );

            if ( mExprContext == NULL )
            {
                RefPtr<ExprContext>         exprContext;

                hr = MakeCComObject( exprContext );
                if ( FAILED( hr ) )
                    return hr;

                hr = exprContext->Init( mModule, mThread, mFuncSH, mBlockSH, mPC, mRegSet );
                if ( FAILED( hr ) )
                    return hr;

                mExprContext = exprContext;
            }
        }

        return S_OK;
    }

    HRESULT StackFrame::GetLanguageInfo(
       BSTR* pbstrLanguage,
       GUID* pguidLanguage )
    {
        return E_NOTIMPL;
    }

    HRESULT StackFrame::GetDebugProperty(
       IDebugProperty2** ppDebugProp )
    {
        OutputDebugStringA( "StackFrame::GetDebugProperty\n" );

        if ( ppDebugProp == NULL )
            return E_INVALIDARG;

        HRESULT hr = S_OK;
        RefPtr<FrameProperty>   frameProp;

        hr = MakeExprContext();
        if ( FAILED( hr ) )
            return hr;

        hr = MakeCComObject( frameProp );
        if ( FAILED( hr ) )
            return hr;

        hr = frameProp->Init( mRegSet, mExprContext );
        if ( FAILED( hr ) )
            return hr;

        *ppDebugProp = frameProp.Detach();
        return S_OK;
    }

    HRESULT StackFrame::EnumProperties(
       DEBUGPROP_INFO_FLAGS      dwFieldSpec,
       UINT                      nRadix,
       REFIID                    refiid,
       DWORD                     dwTimeout,
       ULONG*                    pcelt,
       IEnumDebugPropertyInfo2** ppEnum )
    {
        OutputDebugStringA( "StackFrame::EnumProperties\n" );

        HRESULT hr = S_OK;
        CComPtr<IDebugProperty2>    rootProp;

        hr = GetDebugProperty( &rootProp );
        if ( FAILED( hr ) )
            return hr;

        hr = rootProp->EnumChildren(
            dwFieldSpec,
            nRadix,
            refiid,
            DBG_ATTRIB_ALL,
            NULL,
            dwTimeout,
            ppEnum );
        if ( FAILED( hr ) )
            return hr;

        if ( pcelt != NULL )
        {
            hr = (*ppEnum)->GetCount( pcelt );
            if ( FAILED( hr ) )
                return hr;
        }

        return S_OK;
    }

    HRESULT StackFrame::GetThread(
       IDebugThread2** ppThread )
    {
        if ( ppThread == NULL )
            return E_INVALIDARG;

        return mThread->QueryInterface( __uuidof( IDebugThread2 ), (void**) ppThread );
    }

    //----------------------------------------------------------------------------

    void StackFrame::Init(
        Address pc,
        IRegisterSet* regSet,
        Thread* thread,
        Module* module )
    {
        _ASSERT( regSet != NULL );
        _ASSERT( thread != NULL );
        // there might be no module

        mPC = pc;
        mRegSet = regSet;
        mThread = thread;
        mModule = module;
    }

    HRESULT StackFrame::GetLineInfo( LineInfo& info )
    {
        HRESULT hr = S_OK;
        RefPtr<MagoST::ISession>    session;

        if ( mModule.Get() == NULL )
            return E_NOT_FOUND;

        if ( !mModule->GetSymbolSession( session ) )
            return E_NOT_FOUND;

        uint16_t    sec = 0;
        uint32_t    offset = 0;
        sec = session->GetSecOffsetFromVA( mPC, offset );
        if ( sec == 0 )
            return E_FAIL;

        MagoST::LineNumber line = { 0 };
        if ( !session->FindLine( sec, offset, line ) )
            return E_FAIL;

        info.LineBegin.dwLine = line.Number;
        //info.LineEnd.dwLine = line.NumberEnd;
        info.LineEnd.dwLine = line.Number;
        info.LineBegin.dwColumn = 0;
        info.LineEnd.dwColumn = 0;

        info.LineBegin.dwLine--;
        info.LineEnd.dwLine--;

        // if there's no column info, then these are 0
        if ( info.LineBegin.dwColumn > 0 )
            info.LineBegin.dwColumn--;
        if ( info.LineEnd.dwColumn > 0 )
            info.LineEnd.dwColumn--;

        MagoST::FileInfo    fileInfo = { 0 };
        hr = session->GetFileInfo( line.CompilandIndex, line.FileIndex, fileInfo );
        if ( FAILED( hr ) )
            return hr;

        hr = Utf8To16( fileInfo.Name, fileInfo.NameLength, info.Filename.m_str );
        if ( FAILED( hr ) )
            return hr;

        // TODO: from the compiland we're supposed to get the language
        info.LangName = L"D";
        info.LangGuid = GetDLanguageId();

        return hr;
    }

    HRESULT StackFrame::GetFunctionName( BSTR* funcName )
    {
        _ASSERT( funcName != NULL );
        HRESULT hr = S_OK;

        hr = GetFunctionNameWithSymbols( funcName );
        if ( FAILED( hr ) )
        {
            hr = GetFunctionNameWithAddress( funcName );
        }

        return hr;
    }

    HRESULT StackFrame::GetFunctionNameWithAddress( BSTR* funcName )
    {
        _ASSERT( funcName != NULL );
        wchar_t addrStr[ 8 + 1 ] = L"";

        _ASSERT( sizeof mPC == 4 );
        swprintf_s( addrStr, L"%08x", mPC );

        *funcName = SysAllocString( addrStr );
        if ( *funcName == NULL )
            return E_OUTOFMEMORY;

        return S_OK;
    }

    HRESULT StackFrame::GetFunctionNameWithSymbols( BSTR* funcName )
    {
        _ASSERT( funcName != NULL );
        HRESULT hr = S_OK;
        RefPtr<MagoST::ISession>    session;
        MagoST::SymInfoData         infoData = { 0 };
        MagoST::ISymbolInfo*        symInfo = NULL;

        if ( mModule.Get() == NULL )
            return E_NOT_FOUND;

        if ( !mModule->GetSymbolSession( session ) )
            return E_NOT_FOUND;

        hr = FindFunction();
        if ( FAILED( hr ) )
            return hr;

        hr = session->GetSymbolInfo( mFuncSH, infoData, symInfo );
        if ( FAILED( hr ) )
            return hr;

        PasString*  pstrName = NULL;
        if ( !symInfo->GetName( pstrName ) )
            return E_NOT_FOUND;

        hr = Utf8To16( pstrName->GetName(), pstrName->GetLength(), *funcName );
        if ( FAILED( hr ) )
            return hr;

        // for reference: you get the language by going to a lexical ancestor
        // that's a compiland, then you get a compiland detail from it

        return hr;
    }

    HRESULT StackFrame::FindFunction()
    {
        HRESULT hr = S_OK;
        RefPtr<MagoST::ISession>    session;
        MagoST::SymHandle           symHandle = { 0 };

        // already found
        if ( memcmp( &mFuncSH, &symHandle, sizeof mFuncSH ) != 0 )
            return S_OK;

        if ( mModule.Get() == NULL )
            return E_NOT_FOUND;

        if ( !mModule->GetSymbolSession( session ) )
            return E_NOT_FOUND;

        uint16_t    sec = 0;
        uint32_t    offset = 0;
        sec = session->GetSecOffsetFromVA( mPC, offset );
        if ( sec == 0 )
            return E_NOT_FOUND;

        // TODO: verify that it's a function or public symbol (or something else?)
        hr = session->FindOuterSymbolByAddr( MagoST::SymHeap_GlobalSymbols, sec, offset, symHandle );
        if ( FAILED( hr ) )
        {
            hr = session->FindOuterSymbolByAddr( MagoST::SymHeap_StaticSymbols, sec, offset, symHandle );
            if ( FAILED( hr ) )
            {
                hr = session->FindOuterSymbolByAddr( MagoST::SymHeap_PublicSymbols, sec, offset, symHandle );
                if ( FAILED( hr ) )
                    return hr;
            }
        }

        mFuncSH = symHandle;

        hr = session->FindInnermostSymbol( mFuncSH, sec, offset, mBlockSH );
        // it might be a public symbol, which doesn't have anything: blocks, args, or locals

        return S_OK;
    }
}
<|endoftext|>


<commit_before>/*
 * -----------------------------------------------------------------------------
 * This source file is part of OGRE
 * (Object-oriented Graphics Rendering Engine)
 * For the latest info, see http://www.ogre3d.org/
 *
 * Copyright (c) 2000-2013 Torus Knot Software Ltd
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 * -----------------------------------------------------------------------------
 */

#include "OgreMeshLodGenerator.h"
#include "OgrePixelCountLodStrategy.h"
#include "OgreLodWorkQueueWorker.h"
#include "OgreLodWorkQueueInjector.h"
#include "OgreLodWorkQueueInjectorListener.h"
#include "OgreLodInputProvider.h"
#include "OgreLodInputProviderMesh.h"
#include "OgreLodInputProviderBuffer.h"
#include "OgreLodOutputProvider.h"
#include "OgreLodOutputProviderMesh.h"
#include "OgreLodOutputProviderCompressedMesh.h"
#include "OgreLodOutputProviderBuffer.h"
#include "OgreLodOutputProviderCompressedBuffer.h"
#include "OgreLodCollapseCost.h"
#include "OgreLodCollapseCostCurvature.h"
#include "OgreLodCollapseCostProfiler.h"
#include "OgreLodCollapseCostOutside.h"
#include "OgreLodData.h"
#include "OgreLodCollapser.h"

namespace Ogre
{

	template<> MeshLodGenerator* Singleton<MeshLodGenerator>::msSingleton = 0;
	MeshLodGenerator* MeshLodGenerator::getSingletonPtr()
	{
		return msSingleton;
	}
	MeshLodGenerator& MeshLodGenerator::getSingleton()
	{
		assert( msSingleton );  return ( *msSingleton );
	}
void MeshLodGenerator::getAutoconfig( MeshPtr& inMesh, LodConfig& outLodConfig )
{
	outLodConfig.mesh = inMesh;
	outLodConfig.strategy = PixelCountLodStrategy::getSingletonPtr();
	LodLevel lodLevel;
	lodLevel.reductionMethod = LodLevel::VRM_COLLAPSE_COST;
	Real radius = inMesh->getBoundingSphereRadius();
	for (int i = 2; i < 6; i++) {
		Real i4 = (Real) (i * i * i * i);
		Real i5 = i4 * (Real) i;
		// Distance = pixel count
		// Constant: zoom of the Lod. This could be scaled based on resolution.
		//     Higher constant means first Lod is nearer to camera. Smaller constant means the first Lod is further away from camera.
		// i4: The stretching. Normally you want to have more Lods in the near, then in far away.
		//     i4 means distance is divided by 16=(2*2*2*2), 81, 256, 625=(5*5*5*5).
		//     if 16 would be smaller, the first Lod would be nearer. if 625 would be bigger, the last Lod would be further awaay.
		// if you increase 16 and decrease 625, first and Last Lod distance would be smaller.
		lodLevel.distance = 3388608.f / i4;

		// reductionValue = collapse cost
		// Radius: Edges are multiplied by the length, when calculating collapse cost. So as a base value we use radius, which should help in balancing collapse cost to any mesh size.
		// The constant and i5 are playing together. 1/(1/100k*i5)
		// You need to determine the quality of nearest Lod and the furthest away first.
		// I have chosen 1/(1/100k*(2^5)) = 3125 for nearest Lod and 1/(1/100k*(5^5)) = 32 for nearest Lod.
		// if you divide radius by a bigger number, it means smaller reduction. So radius/3125 is very small reduction for nearest Lod.
		// if you divide radius by a smaller number, it means bigger reduction. So radius/32 means aggressive reduction for furthest away lod.
		// current values: 3125, 411, 97, 32
		lodLevel.reductionValue = radius / 100000.f * i5;
		outLodConfig.levels.push_back(lodLevel);
	}
}

void MeshLodGenerator::generateAutoconfiguredLodLevels( MeshPtr& mesh )
{
	LodConfig lodConfig;
	getAutoconfig(mesh, lodConfig);
	generateLodLevels(lodConfig);
}

void MeshLodGenerator::_configureMeshLodUsage( const LodConfig& lodConfig )
{
	lodConfig.mesh->freeEdgeList();
	lodConfig.mesh->setLodStrategy(lodConfig.strategy);
	MeshLodUsage usage;
	size_t n = 0;
	lodConfig.mesh->_setLodInfo(lodConfig.levels.size() + 1); // add Lod levels
	for (size_t i = 0; i < lodConfig.levels.size(); i++) {
		// Record usages. First Lod usage is the mesh itself.

		// Skip lods, which have the same amount of vertices. No buffer generated for them.
		if (!lodConfig.levels[i].outSkipped) {

			usage.userValue = lodConfig.levels[i].distance;
			usage.value = lodConfig.mesh->getLodStrategy()->transformUserValue(usage.userValue);
			usage.edgeData = NULL;
			usage.manualMesh.setNull();
			usage.manualName = lodConfig.levels[i].manualMeshName;
			lodConfig.mesh->_setLodUsage(++n, usage);
		}
	}
	// Remove skipped Lod levels
	lodConfig.mesh->_setLodInfo(n + 1);
}

MeshLodGenerator::MeshLodGenerator()
{
	if(!LodWorkQueueWorker::getSingletonPtr()){
		mWQWorker = new LodWorkQueueWorker();
	} else {
		mWQWorker = NULL;
	}
	if(!LodWorkQueueInjector::getSingletonPtr()){
		mWQInjector = new LodWorkQueueInjector();
	} else {
		mWQWorker = NULL;
	}
}

MeshLodGenerator::~MeshLodGenerator()
{
	delete mWQWorker;
	delete mWQInjector;
}
void MeshLodGenerator::_resolveComponents( LodConfig& lodConfig, LodCollapseCostPtr& cost, LodDataPtr& data, LodInputProviderPtr& input, LodOutputProviderPtr& output, LodCollapserPtr& collapser )
{
	if(cost.isNull()) {
		cost = LodCollapseCostPtr(new LodCollapseCostCurvature);
		if(lodConfig.advanced.outsideWeight != 0){
			cost = LodCollapseCostPtr(new LodCollapseCostOutside(cost, lodConfig.advanced.outsideWeight, lodConfig.advanced.outsideWalkAngle));
		}
		if(!lodConfig.advanced.profile.empty()){
			cost = LodCollapseCostPtr(new LodCollapseCostProfiler(lodConfig.advanced.profile, cost));
		}

	}
	if(data.isNull()) {
		data = LodDataPtr(new LodData());
	}
	if(collapser.isNull()) {
		collapser = LodCollapserPtr(new LodCollapser());
	}
	if(lodConfig.advanced.useBackgroundQueue){
		if(input.isNull()) {
			input = LodInputProviderPtr(new LodInputProviderBuffer(lodConfig.mesh));
		}
		if(output.isNull()) {
			if(lodConfig.advanced.useCompression){
				output = LodOutputProviderPtr(new LodOutputProviderCompressedBuffer(lodConfig.mesh));
			} else {
				output = LodOutputProviderPtr(new LodOutputProviderBuffer(lodConfig.mesh));
			}
		}
	} else {
		if(input.isNull()) {
			input = LodInputProviderPtr(new LodInputProviderMesh(lodConfig.mesh));
		}
		if(output.isNull()) {
			if(lodConfig.advanced.useCompression){
				output = LodOutputProviderPtr(new LodOutputProviderCompressedMesh(lodConfig.mesh));
			} else {
				output = LodOutputProviderPtr(new LodOutputProviderMesh(lodConfig.mesh));
			}
		}
	}
}
void MeshLodGenerator::_process( LodConfig& lodConfig, LodCollapseCost* cost, LodData* data, LodInputProvider* input, LodOutputProvider* output, LodCollapser* collapser )
{
	input->initData(data);
	data->mUseVertexNormals = data->mUseVertexNormals && lodConfig.advanced.useVertexNormals;
	cost->initCollapseCosts(data);
	output->prepare(data);
	computeLods(lodConfig, data, cost, output, collapser);
	output->finalize(data);
	if(!lodConfig.advanced.useBackgroundQueue){
		// This will be processed in LodWorkQueueInjector if we use background queue.
		output->inject();
		_configureMeshLodUsage(lodConfig);
		//lodConfig.mesh->buildEdgeList();
	}
}
void MeshLodGenerator::generateLodLevels( LodConfig& lodConfig, LodCollapseCostPtr cost, LodDataPtr data, LodInputProviderPtr input, LodOutputProviderPtr output, LodCollapserPtr collapser)
{
	_resolveComponents(lodConfig, cost, data, input, output, collapser);
	if(lodConfig.advanced.useBackgroundQueue){
		LodWorkQueueWorker::getSingleton().addRequestToQueue(lodConfig, cost, data, input, output, collapser);
	} else {
		_process(lodConfig, cost.get(), data.get(), input.get(), output.get(), collapser.get());
	}

}

void MeshLodGenerator::computeLods(LodConfig& lodConfig, LodData* data, LodCollapseCost* cost, LodOutputProvider* output, LodCollapser* collapser)
{
	int lodID = 0;
	size_t lastBakeVertexCount = data->mVertexList.size();
	for (unsigned short curLod = 0; curLod < lodConfig.levels.size(); curLod++) {
		if(!lodConfig.levels[curLod].manualMeshName.empty()){
			// Manual Lod level
			lodConfig.levels[curLod].outSkipped = (curLod != 0 && lodConfig.levels[curLod].manualMeshName == lodConfig.levels[curLod - 1].manualMeshName);
			lodConfig.levels[curLod].outUniqueVertexCount = 0;
			if (!lodConfig.levels[curLod].outSkipped) {
				output->bakeManualLodLevel(data, lodConfig.levels[curLod].manualMeshName, lodID++);
			}
		} else {
			size_t vertexCountLimit;
			Real collapseCostLimit;
			calcLodVertexCount(lodConfig.levels[curLod], data->mVertexList.size(), vertexCountLimit, collapseCostLimit);
			collapser->collapse(data, cost, output, vertexCountLimit, collapseCostLimit);
			size_t vertexCount = data->mCollapseCostHeap.size();
			lodConfig.levels[curLod].outUniqueVertexCount = vertexCount;
			lodConfig.levels[curLod].outSkipped = (vertexCount == data->mVertexList.size());
			if (!lodConfig.levels[curLod].outSkipped) {
				lastBakeVertexCount = data->mVertexList.size();
				output->bakeLodLevel(data, lodID++);
			}
		}
	}
}
void MeshLodGenerator::calcLodVertexCount(const LodLevel& lodLevel, size_t uniqueVertexCount, size_t& outVertexCountLimit,Real& outCollapseCostLimit)
{
	switch (lodLevel.reductionMethod) {
	case LodLevel::VRM_PROPORTIONAL:
		outCollapseCostLimit = LodData::NEVER_COLLAPSE_COST;
		outVertexCountLimit = uniqueVertexCount - (size_t)((Real)uniqueVertexCount * lodLevel.reductionValue);
		break;
	case LodLevel::VRM_CONSTANT:
		outCollapseCostLimit = LodData::NEVER_COLLAPSE_COST;
		outVertexCountLimit = (size_t) lodLevel.reductionValue;
		if (outVertexCountLimit < uniqueVertexCount) {
			outVertexCountLimit = uniqueVertexCount - outVertexCountLimit;
		} else {
			outVertexCountLimit = 0;
		}
		break;
	case LodLevel::VRM_COLLAPSE_COST:
		outCollapseCostLimit = lodLevel.reductionValue;
		outVertexCountLimit = 0;
		break;
	default:
		OgreAssert(0, "");
		outCollapseCostLimit = LodData::NEVER_COLLAPSE_COST;
		outVertexCountLimit = uniqueVertexCount;
		break;
	}
}

}

<commit_msg>Fix constraint for skipping Lod Level<commit_after>/*
 * -----------------------------------------------------------------------------
 * This source file is part of OGRE
 * (Object-oriented Graphics Rendering Engine)
 * For the latest info, see http://www.ogre3d.org/
 *
 * Copyright (c) 2000-2013 Torus Knot Software Ltd
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 * -----------------------------------------------------------------------------
 */

#include "OgreMeshLodGenerator.h"
#include "OgrePixelCountLodStrategy.h"
#include "OgreLodWorkQueueWorker.h"
#include "OgreLodWorkQueueInjector.h"
#include "OgreLodWorkQueueInjectorListener.h"
#include "OgreLodInputProvider.h"
#include "OgreLodInputProviderMesh.h"
#include "OgreLodInputProviderBuffer.h"
#include "OgreLodOutputProvider.h"
#include "OgreLodOutputProviderMesh.h"
#include "OgreLodOutputProviderCompressedMesh.h"
#include "OgreLodOutputProviderBuffer.h"
#include "OgreLodOutputProviderCompressedBuffer.h"
#include "OgreLodCollapseCost.h"
#include "OgreLodCollapseCostCurvature.h"
#include "OgreLodCollapseCostProfiler.h"
#include "OgreLodCollapseCostOutside.h"
#include "OgreLodData.h"
#include "OgreLodCollapser.h"

namespace Ogre
{

	template<> MeshLodGenerator* Singleton<MeshLodGenerator>::msSingleton = 0;
	MeshLodGenerator* MeshLodGenerator::getSingletonPtr()
	{
		return msSingleton;
	}
	MeshLodGenerator& MeshLodGenerator::getSingleton()
	{
		assert( msSingleton );  return ( *msSingleton );
	}
void MeshLodGenerator::getAutoconfig( MeshPtr& inMesh, LodConfig& outLodConfig )
{
	outLodConfig.mesh = inMesh;
	outLodConfig.strategy = PixelCountLodStrategy::getSingletonPtr();
	LodLevel lodLevel;
	lodLevel.reductionMethod = LodLevel::VRM_COLLAPSE_COST;
	Real radius = inMesh->getBoundingSphereRadius();
	for (int i = 2; i < 6; i++) {
		Real i4 = (Real) (i * i * i * i);
		Real i5 = i4 * (Real) i;
		// Distance = pixel count
		// Constant: zoom of the Lod. This could be scaled based on resolution.
		//     Higher constant means first Lod is nearer to camera. Smaller constant means the first Lod is further away from camera.
		// i4: The stretching. Normally you want to have more Lods in the near, then in far away.
		//     i4 means distance is divided by 16=(2*2*2*2), 81, 256, 625=(5*5*5*5).
		//     if 16 would be smaller, the first Lod would be nearer. if 625 would be bigger, the last Lod would be further awaay.
		// if you increase 16 and decrease 625, first and Last Lod distance would be smaller.
		lodLevel.distance = 3388608.f / i4;

		// reductionValue = collapse cost
		// Radius: Edges are multiplied by the length, when calculating collapse cost. So as a base value we use radius, which should help in balancing collapse cost to any mesh size.
		// The constant and i5 are playing together. 1/(1/100k*i5)
		// You need to determine the quality of nearest Lod and the furthest away first.
		// I have chosen 1/(1/100k*(2^5)) = 3125 for nearest Lod and 1/(1/100k*(5^5)) = 32 for nearest Lod.
		// if you divide radius by a bigger number, it means smaller reduction. So radius/3125 is very small reduction for nearest Lod.
		// if you divide radius by a smaller number, it means bigger reduction. So radius/32 means aggressive reduction for furthest away lod.
		// current values: 3125, 411, 97, 32
		lodLevel.reductionValue = radius / 100000.f * i5;
		outLodConfig.levels.push_back(lodLevel);
	}
}

void MeshLodGenerator::generateAutoconfiguredLodLevels( MeshPtr& mesh )
{
	LodConfig lodConfig;
	getAutoconfig(mesh, lodConfig);
	generateLodLevels(lodConfig);
}

void MeshLodGenerator::_configureMeshLodUsage( const LodConfig& lodConfig )
{
	lodConfig.mesh->freeEdgeList();
	lodConfig.mesh->setLodStrategy(lodConfig.strategy);
	MeshLodUsage usage;
	size_t n = 0;
	lodConfig.mesh->_setLodInfo(lodConfig.levels.size() + 1); // add Lod levels
	for (size_t i = 0; i < lodConfig.levels.size(); i++) {
		// Record usages. First Lod usage is the mesh itself.

		// Skip lods, which have the same amount of vertices. No buffer generated for them.
		if (!lodConfig.levels[i].outSkipped) {

			usage.userValue = lodConfig.levels[i].distance;
			usage.value = lodConfig.mesh->getLodStrategy()->transformUserValue(usage.userValue);
			usage.edgeData = NULL;
			usage.manualMesh.setNull();
			usage.manualName = lodConfig.levels[i].manualMeshName;
			lodConfig.mesh->_setLodUsage(++n, usage);
		}
	}
	// Remove skipped Lod levels
	lodConfig.mesh->_setLodInfo(n + 1);
}

MeshLodGenerator::MeshLodGenerator()
{
	if(!LodWorkQueueWorker::getSingletonPtr()){
		mWQWorker = new LodWorkQueueWorker();
	} else {
		mWQWorker = NULL;
	}
	if(!LodWorkQueueInjector::getSingletonPtr()){
		mWQInjector = new LodWorkQueueInjector();
	} else {
		mWQWorker = NULL;
	}
}

MeshLodGenerator::~MeshLodGenerator()
{
	delete mWQWorker;
	delete mWQInjector;
}
void MeshLodGenerator::_resolveComponents( LodConfig& lodConfig, LodCollapseCostPtr& cost, LodDataPtr& data, LodInputProviderPtr& input, LodOutputProviderPtr& output, LodCollapserPtr& collapser )
{
	if(cost.isNull()) {
		cost = LodCollapseCostPtr(new LodCollapseCostCurvature);
		if(lodConfig.advanced.outsideWeight != 0){
			cost = LodCollapseCostPtr(new LodCollapseCostOutside(cost, lodConfig.advanced.outsideWeight, lodConfig.advanced.outsideWalkAngle));
		}
		if(!lodConfig.advanced.profile.empty()){
			cost = LodCollapseCostPtr(new LodCollapseCostProfiler(lodConfig.advanced.profile, cost));
		}

	}
	if(data.isNull()) {
		data = LodDataPtr(new LodData());
	}
	if(collapser.isNull()) {
		collapser = LodCollapserPtr(new LodCollapser());
	}
	if(lodConfig.advanced.useBackgroundQueue){
		if(input.isNull()) {
			input = LodInputProviderPtr(new LodInputProviderBuffer(lodConfig.mesh));
		}
		if(output.isNull()) {
			if(lodConfig.advanced.useCompression){
				output = LodOutputProviderPtr(new LodOutputProviderCompressedBuffer(lodConfig.mesh));
			} else {
				output = LodOutputProviderPtr(new LodOutputProviderBuffer(lodConfig.mesh));
			}
		}
	} else {
		if(input.isNull()) {
			input = LodInputProviderPtr(new LodInputProviderMesh(lodConfig.mesh));
		}
		if(output.isNull()) {
			if(lodConfig.advanced.useCompression){
				output = LodOutputProviderPtr(new LodOutputProviderCompressedMesh(lodConfig.mesh));
			} else {
				output = LodOutputProviderPtr(new LodOutputProviderMesh(lodConfig.mesh));
			}
		}
	}
}
void MeshLodGenerator::_process( LodConfig& lodConfig, LodCollapseCost* cost, LodData* data, LodInputProvider* input, LodOutputProvider* output, LodCollapser* collapser )
{
	input->initData(data);
	data->mUseVertexNormals = data->mUseVertexNormals && lodConfig.advanced.useVertexNormals;
	cost->initCollapseCosts(data);
	output->prepare(data);
	computeLods(lodConfig, data, cost, output, collapser);
	output->finalize(data);
	if(!lodConfig.advanced.useBackgroundQueue){
		// This will be processed in LodWorkQueueInjector if we use background queue.
		output->inject();
		_configureMeshLodUsage(lodConfig);
		//lodConfig.mesh->buildEdgeList();
	}
}
void MeshLodGenerator::generateLodLevels( LodConfig& lodConfig, LodCollapseCostPtr cost, LodDataPtr data, LodInputProviderPtr input, LodOutputProviderPtr output, LodCollapserPtr collapser)
{
	_resolveComponents(lodConfig, cost, data, input, output, collapser);
	if(lodConfig.advanced.useBackgroundQueue){
		LodWorkQueueWorker::getSingleton().addRequestToQueue(lodConfig, cost, data, input, output, collapser);
	} else {
		_process(lodConfig, cost.get(), data.get(), input.get(), output.get(), collapser.get());
	}

}

void MeshLodGenerator::computeLods(LodConfig& lodConfig, LodData* data, LodCollapseCost* cost, LodOutputProvider* output, LodCollapser* collapser)
{
	int lodID = 0;
	size_t lastBakeVertexCount = data->mVertexList.size();
	for (unsigned short curLod = 0; curLod < lodConfig.levels.size(); curLod++) {
		if(!lodConfig.levels[curLod].manualMeshName.empty()){
			// Manual Lod level
			lodConfig.levels[curLod].outSkipped = (curLod != 0 && lodConfig.levels[curLod].manualMeshName == lodConfig.levels[curLod - 1].manualMeshName);
			lodConfig.levels[curLod].outUniqueVertexCount = 0;
			lastBakeVertexCount = -1;
			if (!lodConfig.levels[curLod].outSkipped) {
				output->bakeManualLodLevel(data, lodConfig.levels[curLod].manualMeshName, lodID++);
			}
		} else {
			size_t vertexCountLimit;
			Real collapseCostLimit;
			calcLodVertexCount(lodConfig.levels[curLod], data->mVertexList.size(), vertexCountLimit, collapseCostLimit);
			collapser->collapse(data, cost, output, vertexCountLimit, collapseCostLimit);
			size_t vertexCount = data->mCollapseCostHeap.size();
			lodConfig.levels[curLod].outUniqueVertexCount = vertexCount;
			lodConfig.levels[curLod].outSkipped = (vertexCount == lastBakeVertexCount);
			if (!lodConfig.levels[curLod].outSkipped) {
				lastBakeVertexCount = vertexCount;
				output->bakeLodLevel(data, lodID++);
			}
		}
	}
}
void MeshLodGenerator::calcLodVertexCount(const LodLevel& lodLevel, size_t uniqueVertexCount, size_t& outVertexCountLimit,Real& outCollapseCostLimit)
{
	switch (lodLevel.reductionMethod) {
	case LodLevel::VRM_PROPORTIONAL:
		outCollapseCostLimit = LodData::NEVER_COLLAPSE_COST;
		outVertexCountLimit = uniqueVertexCount - (size_t)((Real)uniqueVertexCount * lodLevel.reductionValue);
		break;
	case LodLevel::VRM_CONSTANT:
		outCollapseCostLimit = LodData::NEVER_COLLAPSE_COST;
		outVertexCountLimit = (size_t) lodLevel.reductionValue;
		if (outVertexCountLimit < uniqueVertexCount) {
			outVertexCountLimit = uniqueVertexCount - outVertexCountLimit;
		} else {
			outVertexCountLimit = 0;
		}
		break;
	case LodLevel::VRM_COLLAPSE_COST:
		outCollapseCostLimit = lodLevel.reductionValue;
		outVertexCountLimit = 0;
		break;
	default:
		OgreAssert(0, "");
		outCollapseCostLimit = LodData::NEVER_COLLAPSE_COST;
		outVertexCountLimit = uniqueVertexCount;
		break;
	}
}

}

<|endoftext|>


<commit_before><commit_msg>Need to cast to WebCore::Widget explicitly since the method being called takes a void pointer!  Argh :(<commit_after><|endoftext|>


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

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "otbFineRegistration.h"

#include <iostream>
#include "otbCommandLineArgumentParser.h"

#include "otbImage.h"
#include "otbImageFileReader.h"
#include "otbStreamingImageFileWriter.h"
#include "otbFineRegistrationImageFilter.h"
#include "otbStandardWriterWatcher.h"
#include "otbVectorImage.h"
#include "otbImageList.h"
#include "otbImageListToVectorImageFilter.h"

#include "itkTimeProbe.h"
#include "itkFixedArray.h"
#include "itkNormalizedCorrelationImageToImageMetric.h"
#include "itkMeanReciprocalSquareDifferenceImageToImageMetric.h"
#include "itkMeanSquaresImageToImageMetric.h"
#include "itkMattesMutualInformationImageToImageMetric.h"
#include "itkDiscreteGaussianImageFilter.h"
#include "itkAbsImageFilter.h"
#include "itkVectorIndexSelectionCastImageFilter.h"
#include "itkBinaryThresholdImageFilter.h"

namespace otb
{

int FineRegistration::Describe(ApplicationDescriptor* descriptor)
{
  descriptor->SetName("FineRegistration");
  descriptor->SetDescription("Estimate disparity map between two images. Output image contain x offset, y offset and metric value.");
  descriptor->AddOption("Reference", "The reference image",
                        "ref", 1, true, ApplicationDescriptor::InputImage);
  descriptor->AddOption("Secondary", "The secondary image",
                        "sec", 1, true, ApplicationDescriptor::FileName);
  descriptor->AddOption("Output", "The output image",
                        "out", 1, true, ApplicationDescriptor::OutputImage);
  descriptor->AddOption("ExplorationRadius","Radius (in pixels) of the exploration window",
                        "er",2,true, ApplicationDescriptor::Integer);
  descriptor->AddOption("MetricRadius","Radius (in pixels) of the metric computation window",
                        "mr",2,true, ApplicationDescriptor::Integer);
  descriptor->AddOption("CoarseOffset","(optional) Coarse offset (in physical space) between the two images. Default is [0,0].",
                        "co",2,false, ApplicationDescriptor::Real);
  descriptor->AddOption("SubSamplingRate","(optional) Generate a result at a coarser resolution with a given sub-sampling rate in each direction (in pixels). Default is no sub-sampling",
                        "ssr",2,false, ApplicationDescriptor::Real);
  descriptor->AddOption("ReferenceGaussianSmoothing","(optional) Perform a gaussian smoothing of the reference image. Parameters are gaussian sigma (in pixels) in each direction. Default is no smoothing.",
                        "rgs",2,false, ApplicationDescriptor::Real);
  descriptor->AddOption("SecondaryGaussianSmoothing","(optional) Perform a gaussian smoothing of the secondary image. Parameters are gaussian sigma (in pixels) in each direction. Default is no smoothing.",
                        "sgs",2,false, ApplicationDescriptor::Real);
  descriptor->AddOption("Metric","(optional) Choose the metric used for block matching. Available metrics are cross-correlation (CC), cross-correlation with subtracted mean (CCSM), mean-square difference (MSD), mean reciprocal square difference (MRSD) and mutual information (MI). Default is cross-correlation",
                        "m",1,false, ApplicationDescriptor::String);
  descriptor->AddOption("SubPixelAccuracy","(optional) Metric extrema location will be refined up to the given accuracy. Default is 0.01",
                        "spa",1,false, ApplicationDescriptor::Real);
  descriptor->AddOption("ValidityMask","(optional) Threshold to obtain a validity mask. Params are lowerThan or greaterThan and a threshold",
                        "vm",2,false, ApplicationDescriptor::String);
  return EXIT_SUCCESS;
}

int FineRegistration::Execute(otb::ApplicationOptionsResult* parseResult)
{
  const unsigned int Dimension = 2;
  typedef double     PixelType;

  typedef itk::FixedArray<PixelType,Dimension>                                 DeformationValueType;
  typedef otb::Image< PixelType,  Dimension >                                  ImageType;
  typedef otb::VectorImage<PixelType,Dimension>                                VectorImageType;
  typedef otb::ImageList<ImageType>                                            ImageListType;
  typedef otb::ImageListToVectorImageFilter<ImageListType,VectorImageType>     IL2VIFilterType;
  typedef otb::Image<DeformationValueType,Dimension>                           FieldImageType;
  typedef otb::ImageFileReader< ImageType >                                    ReaderType;
  typedef otb::StreamingImageFileWriter< VectorImageType >                     WriterType;
  typedef otb::FineRegistrationImageFilter<ImageType,ImageType,FieldImageType> RegistrationFilterType;
  typedef itk::DiscreteGaussianImageFilter<ImageType,ImageType>                GaussianFilterType;
  typedef itk::VectorIndexSelectionCastImageFilter<FieldImageType,ImageType>   VectorImageToImageFilterType;
  typedef itk::AbsImageFilter<ImageType,ImageType>                             AbsFilterType;
  typedef itk::BinaryThresholdImageFilter<ImageType,ImageType>                 BinaryThresholdImageFilterType;

  // Read reference image
  ReaderType::Pointer freader = ReaderType::New();
  freader->SetFileName(parseResult->GetParameterString("Reference"));

  // Read secondary image
  ReaderType::Pointer mreader = ReaderType::New();
  mreader->SetFileName(parseResult->GetParameterString("Secondary"));

  // Retrieve main registration parameters
  RegistrationFilterType::SizeType radius, sradius;
  ImageType::OffsetType ssrate;
  sradius[0] = parseResult->GetParameterULong("ExplorationRadius",0);
  sradius[1] = parseResult->GetParameterULong("ExplorationRadius",1);
  radius[0] = parseResult->GetParameterULong("MetricRadius",0);
  radius[1] = parseResult->GetParameterULong("MetricRadius",1);

  double accuracy = 0.01;
  if(parseResult->IsOptionPresent("SubPixelAccuracy"))
    {
    accuracy = parseResult->GetParameterDouble("SubPixelAccuracy");
    }
  ssrate.Fill(1);
  if(parseResult->IsOptionPresent("SubSamplingRate"))
    {
    ssrate[0] = parseResult->GetParameterDouble("SubSamplingRate",0);
    ssrate[1] = parseResult->GetParameterDouble("SubSamplingRate",1);
    }
  RegistrationFilterType::SpacingType initialOffset;
  initialOffset.Fill(0);
  if(parseResult->IsOptionPresent("CoarseOffset"))
    {
    initialOffset[0] = parseResult->GetParameterDouble("CoarseOffset",0);
    initialOffset[1] = parseResult->GetParameterDouble("CoarseOffset",1);
    }

  // Display info
  std::cout<<"Reference image   : "<<freader->GetFileName()<<std::endl;
  std::cout<<"Secondary image   : "<<mreader->GetFileName()<<std::endl;

  std::cout<<"Exploration radius: "<<sradius<<" (pixels)"<<std::endl;
  std::cout<<"Metric radius     : "<<radius<<" (pixels)"<<std::endl;
  std::cout<<"Sub-sampling rate : "<<ssrate<<" (pixels)"<<std::endl;
  std::cout<<"Coarse offset     : "<<initialOffset<<" (physical unit)"<<std::endl;
  std::cout<<"Accuracy          : "<<accuracy<<" (physical unit)"<<std::endl;

  RegistrationFilterType::Pointer registration = RegistrationFilterType::New();
  registration->SetRadius(radius);
  registration->SetSearchRadius(sradius);
  registration->SetSubPixelAccuracy(accuracy);
  registration->SetGridStep(ssrate);
  registration->SetInitialOffset(initialOffset);

  GaussianFilterType::Pointer refGaussianFilter,secGaussianFilter;

  if(parseResult->IsOptionPresent("ReferenceGaussianSmoothing"))
    {
    refGaussianFilter = GaussianFilterType::New();
    refGaussianFilter->SetInput(freader->GetOutput());
    GaussianFilterType::ArrayType sigma;
    sigma[0] = parseResult->GetParameterDouble("ReferenceGaussianSmoothing",0);
    sigma[1] = parseResult->GetParameterDouble("ReferenceGaussianSmoothing",1);
    refGaussianFilter->SetVariance(sigma);
    refGaussianFilter->SetUseImageSpacingOff();
    std::cout<<"Reference image gaussian smoothing on."<<std::endl;
    std::cout<<"variance        : "<<sigma<<" (pixels)"<<std::endl;
    registration->SetFixedInput(refGaussianFilter->GetOutput());
    }
  else
    {
    std::cout<<"Reference image gaussian smoothing off."<<std::endl;
    registration->SetFixedInput(freader->GetOutput());
    }

  if(parseResult->IsOptionPresent("SecondaryGaussianSmoothing"))
      {
      secGaussianFilter = GaussianFilterType::New();
      secGaussianFilter->SetInput(mreader->GetOutput());
      GaussianFilterType::ArrayType sigma;
      sigma[0] = parseResult->GetParameterDouble("SecondaryGaussianSmoothing",0);
      sigma[1] = parseResult->GetParameterDouble("SecondaryGaussianSmoothing",1);
      secGaussianFilter->SetVariance(sigma);
      secGaussianFilter->SetUseImageSpacingOff();
      std::cout<<"Secondary image gaussian smoothing on."<<std::endl;
      std::cout<<"variance        : "<<sigma<<" (pixels)"<<std::endl;
      registration->SetMovingInput(secGaussianFilter->GetOutput());
      }
    else
      {
      std::cout<<"Secondary image gaussian smoothing off."<<std::endl;
      registration->SetMovingInput(mreader->GetOutput());
      }

  // Retrieve metric name
  std::string metricId = "CC";
  if(parseResult->IsOptionPresent("Metric"))
    {
    metricId = parseResult->GetParameterString("Metric");
    }

  if(metricId == "CC")
    {
    std::cout<<"Metric            : Cross-correlation"<<std::endl;
    typedef itk::NormalizedCorrelationImageToImageMetric<ImageType,ImageType> NCCType;
    NCCType::Pointer metricPtr = NCCType::New();
    metricPtr->SubtractMeanOff();
    registration->SetMetric(metricPtr);
    registration->MinimizeOn();
    }
  else if(metricId == "CCSM")
    {
    std::cout<<"Metric            : Cross-correlation (mean subtracted)"<<std::endl;
    typedef itk::NormalizedCorrelationImageToImageMetric<ImageType,ImageType> NCCType;
    NCCType::Pointer metricPtr = NCCType::New();
    metricPtr->SubtractMeanOn();
    registration->SetMetric(metricPtr);
    registration->MinimizeOn();
    }
  else if(metricId == "MSD")
    {
    std::cout<<"Metric            : Mean square difference"<<std::endl;
    typedef itk::MeanSquaresImageToImageMetric<ImageType,ImageType> MeanSquareType;
    MeanSquareType::Pointer metricPtr = MeanSquareType::New();
    registration->SetMetric(metricPtr);
    registration->MinimizeOn();
    }
  else if(metricId == "MRSD")
    {
    std::cout<<"Metric            : Mean reciprocal square difference"<<std::endl;
    typedef itk::MeanReciprocalSquareDifferenceImageToImageMetric<ImageType,ImageType> MRSDType;
    MRSDType::Pointer metricPtr = MRSDType::New();
    registration->SetMetric(metricPtr);
    registration->MinimizeOff();
    }
  else if(metricId == "MI")
    {
    std::cout<<"Metric            : Mutual information"<<std::endl;
    typedef itk::MattesMutualInformationImageToImageMetric<ImageType,ImageType> MIType;
    MIType::Pointer metricPtr = MIType::New();
    registration->SetMetric(metricPtr);
    registration->MinimizeOn();
    }
  else
    {
    std::cerr<<"Metric "<<metricId<<" not recognized."<<std::endl;
    std::cerr<<"Possible choices are: CC, CCMS, MSD, MRSD, MI"<<std::endl;
    return EXIT_FAILURE;
    }
  VectorImageToImageFilterType::Pointer xExtractor = VectorImageToImageFilterType::New();
  xExtractor->SetInput(registration->GetOutputDeformationField());
  xExtractor->SetIndex(0);

  VectorImageToImageFilterType::Pointer yExtractor = VectorImageToImageFilterType::New();
  yExtractor->SetInput(registration->GetOutputDeformationField());
  yExtractor->SetIndex(1);

  ImageListType::Pointer il = ImageListType::New();
  il->PushBack(xExtractor->GetOutput());
  il->PushBack(yExtractor->GetOutput());

  AbsFilterType::Pointer absFilter;

  // Invert correlation to get classical rendering
  if(metricId == "CC" || metricId == "CCSM")
    {
    absFilter = AbsFilterType::New();
    absFilter->SetInput(registration->GetOutput());
    il->PushBack(absFilter->GetOutput());
    }
  else
    {
    il->PushBack(registration->GetOutput());
    }

  BinaryThresholdImageFilterType::Pointer threshold;
  if(parseResult->IsOptionPresent("ValidityMask"))
    {
    threshold = BinaryThresholdImageFilterType::New();

    if(metricId == "CC" || metricId == "CCSM")
      {
      threshold->SetInput(absFilter->GetOutput());
      }
    else
      {
      threshold->SetInput(registration->GetOutput());
      }
    if(parseResult->GetParameterString("ValidityMask",0)=="greaterThan")
      {
      threshold->SetLowerThreshold(parseResult->GetParameterDouble("ValidityMask",1));
      }
    else if(parseResult->GetParameterString("ValidityMask",0)=="lowerThan")
      {
      threshold->SetUpperThreshold(parseResult->GetParameterDouble("ValidityMask",1));
      }
    else
      {
      std::cerr<<"Arguments of --ValidityMask option should begin with lowerThan or greaterThan"<<std::endl;
      return EXIT_FAILURE;
      }

    std::cout<<"A validity mask will be produced as the 4th band (valid pixels = 1.0, not valid = 0.0)."<<std::endl;
    std::cout<<"Pixels are considered valid if metric is "<<parseResult->GetParameterString("ValidityMask",0)<<" ";
    std::cout<<parseResult->GetParameterDouble("ValidityMask",1)<<std::endl;

    threshold->SetInsideValue(1.0);
    threshold->SetOutsideValue(0.);
    il->PushBack(threshold->GetOutput());
    }

  IL2VIFilterType::Pointer il2vi = IL2VIFilterType::New();
  il2vi->SetInput(il);

  WriterType::Pointer writer = WriterType::New();
  writer->SetFileName(parseResult->GetOutputImage());
  writer->SetInput(il2vi->GetOutput());

  std::cout<<std::endl;
  otb::StandardWriterWatcher watcher(writer,registration,"Fine Registration");

  writer->Update();

  return EXIT_SUCCESS;
}

}
<commit_msg>ENH : little change in appli qt<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "otbFineRegistration.h"

#include <iostream>
#include "otbCommandLineArgumentParser.h"

#include "otbImage.h"
#include "otbImageFileReader.h"
#include "otbStreamingImageFileWriter.h"
#include "otbFineRegistrationImageFilter.h"
#include "otbStandardWriterWatcher.h"
#include "otbVectorImage.h"
#include "otbImageList.h"
#include "otbImageListToVectorImageFilter.h"

#include "itkTimeProbe.h"
#include "itkFixedArray.h"
#include "itkNormalizedCorrelationImageToImageMetric.h"
#include "itkMeanReciprocalSquareDifferenceImageToImageMetric.h"
#include "itkMeanSquaresImageToImageMetric.h"
#include "itkMattesMutualInformationImageToImageMetric.h"
#include "itkDiscreteGaussianImageFilter.h"
#include "itkAbsImageFilter.h"
#include "itkVectorIndexSelectionCastImageFilter.h"
#include "itkBinaryThresholdImageFilter.h"

namespace otb
{

int FineRegistration::Describe(ApplicationDescriptor* descriptor)
{
  descriptor->SetName("FineRegistration");
  descriptor->SetDescription("Estimate disparity map between two images. Output image contain x offset, y offset and metric value.");
  descriptor->AddOption("Reference", "The reference image",
                        "ref", 1, true, ApplicationDescriptor::InputImage);
  descriptor->AddOption("Secondary", "The secondary image",
                        "sec", 1, true, ApplicationDescriptor::FileName);
  descriptor->AddOption("Output", "The output image",
                        "out", 1, true, ApplicationDescriptor::OutputImage);
  descriptor->AddOption("ExplorationRadius","Radius (in pixels) of the exploration window",
                        "er",2,true, ApplicationDescriptor::Integer);
  descriptor->AddOption("MetricRadius","Radius (in pixels) of the metric computation window",
                        "mr",2,true, ApplicationDescriptor::Integer);
  descriptor->AddOption("CoarseOffset","(optional) Coarse offset (in physical space) between the two images. Default is [0,0].",
                        "co",2,false, ApplicationDescriptor::Real);
  descriptor->AddOption("SubSamplingRate","(optional) Generate a result at a coarser resolution with a given sub-sampling rate in each direction (in pixels). Default is no sub-sampling",
                        "ssr",2,false, ApplicationDescriptor::Real);
  descriptor->AddOption("ReferenceGaussianSmoothing","(optional) Perform a gaussian smoothing of the reference image. Parameters are gaussian sigma (in pixels) in each direction. Default is no smoothing.",
                        "rgs",2,false, ApplicationDescriptor::Real);
  descriptor->AddOption("SecondaryGaussianSmoothing","(optional) Perform a gaussian smoothing of the secondary image. Parameters are gaussian sigma (in pixels) in each direction. Default is no smoothing.",
                        "sgs",2,false, ApplicationDescriptor::Real);
  descriptor->AddOption("Metric","(optional) Choose the metric used for block matching. Available metrics are cross-correlation (CC), cross-correlation with subtracted mean (CCSM), mean-square difference (MSD), mean reciprocal square difference (MRSD) and mutual information (MI). Default is cross-correlation",
                        "m",1,false, ApplicationDescriptor::String);
  descriptor->AddOption("SubPixelAccuracy","(optional) Metric extrema location will be refined up to the given accuracy. Default is 0.01",
                        "spa",1,false, ApplicationDescriptor::Real);
  descriptor->AddOption("ValidityMask","(optional) Threshold to obtain a validity mask. Params are lowerThan or greaterThan and a threshold",
                        "vm",2,false, ApplicationDescriptor::Real);
  return EXIT_SUCCESS;
}

int FineRegistration::Execute(otb::ApplicationOptionsResult* parseResult)
{
  const unsigned int Dimension = 2;
  typedef double     PixelType;

  typedef itk::FixedArray<PixelType,Dimension>                                 DeformationValueType;
  typedef otb::Image< PixelType,  Dimension >                                  ImageType;
  typedef otb::VectorImage<PixelType,Dimension>                                VectorImageType;
  typedef otb::ImageList<ImageType>                                            ImageListType;
  typedef otb::ImageListToVectorImageFilter<ImageListType,VectorImageType>     IL2VIFilterType;
  typedef otb::Image<DeformationValueType,Dimension>                           FieldImageType;
  typedef otb::ImageFileReader< ImageType >                                    ReaderType;
  typedef otb::StreamingImageFileWriter< VectorImageType >                     WriterType;
  typedef otb::FineRegistrationImageFilter<ImageType,ImageType,FieldImageType> RegistrationFilterType;
  typedef itk::DiscreteGaussianImageFilter<ImageType,ImageType>                GaussianFilterType;
  typedef itk::VectorIndexSelectionCastImageFilter<FieldImageType,ImageType>   VectorImageToImageFilterType;
  typedef itk::AbsImageFilter<ImageType,ImageType>                             AbsFilterType;
  typedef itk::BinaryThresholdImageFilter<ImageType,ImageType>                 BinaryThresholdImageFilterType;

  // Read reference image
  ReaderType::Pointer freader = ReaderType::New();
  freader->SetFileName(parseResult->GetParameterString("Reference"));

  // Read secondary image
  ReaderType::Pointer mreader = ReaderType::New();
  mreader->SetFileName(parseResult->GetParameterString("Secondary"));

  // Retrieve main registration parameters
  RegistrationFilterType::SizeType radius, sradius;
  ImageType::OffsetType ssrate;
  sradius[0] = parseResult->GetParameterULong("ExplorationRadius",0);
  sradius[1] = parseResult->GetParameterULong("ExplorationRadius",1);
  radius[0] = parseResult->GetParameterULong("MetricRadius",0);
  radius[1] = parseResult->GetParameterULong("MetricRadius",1);

  double accuracy = 0.01;
  if(parseResult->IsOptionPresent("SubPixelAccuracy"))
    {
    accuracy = parseResult->GetParameterDouble("SubPixelAccuracy");
    }
  ssrate.Fill(1);
  if(parseResult->IsOptionPresent("SubSamplingRate"))
    {
    ssrate[0] = parseResult->GetParameterDouble("SubSamplingRate",0);
    ssrate[1] = parseResult->GetParameterDouble("SubSamplingRate",1);
    }
  RegistrationFilterType::SpacingType initialOffset;
  initialOffset.Fill(0);
  if(parseResult->IsOptionPresent("CoarseOffset"))
    {
    initialOffset[0] = parseResult->GetParameterDouble("CoarseOffset",0);
    initialOffset[1] = parseResult->GetParameterDouble("CoarseOffset",1);
    }

  // Display info
  std::cout<<"Reference image   : "<<freader->GetFileName()<<std::endl;
  std::cout<<"Secondary image   : "<<mreader->GetFileName()<<std::endl;

  std::cout<<"Exploration radius: "<<sradius<<" (pixels)"<<std::endl;
  std::cout<<"Metric radius     : "<<radius<<" (pixels)"<<std::endl;
  std::cout<<"Sub-sampling rate : "<<ssrate<<" (pixels)"<<std::endl;
  std::cout<<"Coarse offset     : "<<initialOffset<<" (physical unit)"<<std::endl;
  std::cout<<"Accuracy          : "<<accuracy<<" (physical unit)"<<std::endl;

  RegistrationFilterType::Pointer registration = RegistrationFilterType::New();
  registration->SetRadius(radius);
  registration->SetSearchRadius(sradius);
  registration->SetSubPixelAccuracy(accuracy);
  registration->SetGridStep(ssrate);
  registration->SetInitialOffset(initialOffset);

  GaussianFilterType::Pointer refGaussianFilter,secGaussianFilter;

  if(parseResult->IsOptionPresent("ReferenceGaussianSmoothing"))
    {
    refGaussianFilter = GaussianFilterType::New();
    refGaussianFilter->SetInput(freader->GetOutput());
    GaussianFilterType::ArrayType sigma;
    sigma[0] = parseResult->GetParameterDouble("ReferenceGaussianSmoothing",0);
    sigma[1] = parseResult->GetParameterDouble("ReferenceGaussianSmoothing",1);
    refGaussianFilter->SetVariance(sigma);
    refGaussianFilter->SetUseImageSpacingOff();
    std::cout<<"Reference image gaussian smoothing on."<<std::endl;
    std::cout<<"variance        : "<<sigma<<" (pixels)"<<std::endl;
    registration->SetFixedInput(refGaussianFilter->GetOutput());
    }
  else
    {
    std::cout<<"Reference image gaussian smoothing off."<<std::endl;
    registration->SetFixedInput(freader->GetOutput());
    }

  if(parseResult->IsOptionPresent("SecondaryGaussianSmoothing"))
      {
      secGaussianFilter = GaussianFilterType::New();
      secGaussianFilter->SetInput(mreader->GetOutput());
      GaussianFilterType::ArrayType sigma;
      sigma[0] = parseResult->GetParameterDouble("SecondaryGaussianSmoothing",0);
      sigma[1] = parseResult->GetParameterDouble("SecondaryGaussianSmoothing",1);
      secGaussianFilter->SetVariance(sigma);
      secGaussianFilter->SetUseImageSpacingOff();
      std::cout<<"Secondary image gaussian smoothing on."<<std::endl;
      std::cout<<"variance        : "<<sigma<<" (pixels)"<<std::endl;
      registration->SetMovingInput(secGaussianFilter->GetOutput());
      }
    else
      {
      std::cout<<"Secondary image gaussian smoothing off."<<std::endl;
      registration->SetMovingInput(mreader->GetOutput());
      }

  // Retrieve metric name
  std::string metricId = "CC";
  if(parseResult->IsOptionPresent("Metric"))
    {
    metricId = parseResult->GetParameterString("Metric");
    }

  if(metricId == "CC")
    {
    std::cout<<"Metric            : Cross-correlation"<<std::endl;
    typedef itk::NormalizedCorrelationImageToImageMetric<ImageType,ImageType> NCCType;
    NCCType::Pointer metricPtr = NCCType::New();
    metricPtr->SubtractMeanOff();
    registration->SetMetric(metricPtr);
    registration->MinimizeOn();
    }
  else if(metricId == "CCSM")
    {
    std::cout<<"Metric            : Cross-correlation (mean subtracted)"<<std::endl;
    typedef itk::NormalizedCorrelationImageToImageMetric<ImageType,ImageType> NCCType;
    NCCType::Pointer metricPtr = NCCType::New();
    metricPtr->SubtractMeanOn();
    registration->SetMetric(metricPtr);
    registration->MinimizeOn();
    }
  else if(metricId == "MSD")
    {
    std::cout<<"Metric            : Mean square difference"<<std::endl;
    typedef itk::MeanSquaresImageToImageMetric<ImageType,ImageType> MeanSquareType;
    MeanSquareType::Pointer metricPtr = MeanSquareType::New();
    registration->SetMetric(metricPtr);
    registration->MinimizeOn();
    }
  else if(metricId == "MRSD")
    {
    std::cout<<"Metric            : Mean reciprocal square difference"<<std::endl;
    typedef itk::MeanReciprocalSquareDifferenceImageToImageMetric<ImageType,ImageType> MRSDType;
    MRSDType::Pointer metricPtr = MRSDType::New();
    registration->SetMetric(metricPtr);
    registration->MinimizeOff();
    }
  else if(metricId == "MI")
    {
    std::cout<<"Metric            : Mutual information"<<std::endl;
    typedef itk::MattesMutualInformationImageToImageMetric<ImageType,ImageType> MIType;
    MIType::Pointer metricPtr = MIType::New();
    registration->SetMetric(metricPtr);
    registration->MinimizeOn();
    }
  else
    {
    std::cerr<<"Metric "<<metricId<<" not recognized."<<std::endl;
    std::cerr<<"Possible choices are: CC, CCMS, MSD, MRSD, MI"<<std::endl;
    return EXIT_FAILURE;
    }
  VectorImageToImageFilterType::Pointer xExtractor = VectorImageToImageFilterType::New();
  xExtractor->SetInput(registration->GetOutputDeformationField());
  xExtractor->SetIndex(0);

  VectorImageToImageFilterType::Pointer yExtractor = VectorImageToImageFilterType::New();
  yExtractor->SetInput(registration->GetOutputDeformationField());
  yExtractor->SetIndex(1);

  ImageListType::Pointer il = ImageListType::New();
  il->PushBack(xExtractor->GetOutput());
  il->PushBack(yExtractor->GetOutput());

  AbsFilterType::Pointer absFilter;

  // Invert correlation to get classical rendering
  if(metricId == "CC" || metricId == "CCSM")
    {
    absFilter = AbsFilterType::New();
    absFilter->SetInput(registration->GetOutput());
    il->PushBack(absFilter->GetOutput());
    }
  else
    {
    il->PushBack(registration->GetOutput());
    }

  BinaryThresholdImageFilterType::Pointer threshold;
  if(parseResult->IsOptionPresent("ValidityMask"))
    {
    threshold = BinaryThresholdImageFilterType::New();

    if(metricId == "CC" || metricId == "CCSM")
      {
      threshold->SetInput(absFilter->GetOutput());
      }
    else
      {
      threshold->SetInput(registration->GetOutput());
      }
    if(parseResult->GetParameterString("ValidityMask",0)=="greaterThan")
      {
      threshold->SetLowerThreshold(parseResult->GetParameterDouble("ValidityMask",1));
      }
    else if(parseResult->GetParameterString("ValidityMask",0)=="lowerThan")
      {
      threshold->SetUpperThreshold(parseResult->GetParameterDouble("ValidityMask",1));
      }
    else
      {
      std::cerr<<"Arguments of --ValidityMask option should begin with lowerThan or greaterThan"<<std::endl;
      return EXIT_FAILURE;
      }

    std::cout<<"A validity mask will be produced as the 4th band (valid pixels = 1.0, not valid = 0.0)."<<std::endl;
    std::cout<<"Pixels are considered valid if metric is "<<parseResult->GetParameterString("ValidityMask",0)<<" ";
    std::cout<<parseResult->GetParameterDouble("ValidityMask",1)<<std::endl;

    threshold->SetInsideValue(1.0);
    threshold->SetOutsideValue(0.);
    il->PushBack(threshold->GetOutput());
    }

  IL2VIFilterType::Pointer il2vi = IL2VIFilterType::New();
  il2vi->SetInput(il);

  WriterType::Pointer writer = WriterType::New();
  writer->SetFileName(parseResult->GetOutputImage());
  writer->SetInput(il2vi->GetOutput());

  std::cout<<std::endl;
  otb::StandardWriterWatcher watcher(writer,registration,"Fine Registration");

  writer->Update();

  return EXIT_SUCCESS;
}

}
<|endoftext|>


<commit_before>#include <new>

#include "types.h"
#include "kernel.hh"
#include "cpputil.hh"
#include "spinlock.h"
#include "amd64.h"
#include "condvar.h"
#include "proc.hh"
#include "cpu.hh"
#include "elf.hh"

const std::nothrow_t std::nothrow;

void*
operator new(std::size_t nbytes)
{
  panic("global operator new");

  u64* x = (u64*) kmalloc(nbytes + sizeof(u64), "cpprt new");
  *x = nbytes;
  return x+1;
}

void
operator delete(void* p) noexcept
{
  panic("global operator delete");

  u64* x = (u64*) p;
  kmfree(x-1, x[-1] + sizeof(u64));
}

void*
operator new[](std::size_t nbytes)
{
  u64* x = (u64*) kmalloc(nbytes + sizeof(u64), "array");
  *x = nbytes;
  return x+1;
}

void
operator delete[](void* p) noexcept
{
  u64* x = (u64*) p;
  kmfree(x-1, x[-1] + sizeof(u64));
}

void *
operator new(std::size_t nbytes, void* buf) noexcept
{
  return buf;
}

void
operator delete(void* ptr, void*) noexcept
{
}

void
__cxa_pure_virtual(void)
{
  panic("__cxa_pure_virtual");
}

int
__cxa_guard_acquire(s64 *guard)
{
  volatile u8 *x = (u8*) guard;
  volatile u32 *l = (u32*) (x+4);

  pushcli();
  while (xchg32(l, 1) != 0)
    ; /* spin */

  if (*x) {
    xchg32(l, 0);
    popcli();
    return 0;
  }
  return 1;
}

void
__cxa_guard_release(s64 *guard)
{
  volatile u8 *x = (u8*) guard;
  volatile u32 *l = (u32*) (x+4);

  *x = 1;
  __sync_synchronize();
  xchg32(l, 0);
  popcli();
}

void
__cxa_guard_abort(s64 *guard)
{
  volatile u8 *x = (u8*) guard;
  volatile u32 *l = (u32*) (x+4);

  xchg32(l, 0);
  popcli();
}

int
__cxa_atexit(void (*f)(void*), void *p, void *d)
{
  return 0;
}

extern "C" void abort(void);
void
abort(void)
{
  panic("abort");
}

static void
cxx_terminate(void)
{
  panic("cxx terminate");
}

static void
cxx_unexpected(void)
{
  panic("cxx unexpected");
}

void *__dso_handle;

namespace std {
  std::ostream cout;

  template<>
  u128
  atomic<u128>::load(memory_order __m) const
  {
    __sync_synchronize();
    u128 v = _M_i;
    __sync_synchronize();

    return v;
  }

  template<>
  bool
  atomic<u128>::compare_exchange_weak(u128 &__i1, u128 i2, memory_order __m)
  {
    // XXX no __sync_val_compare_and_swap for u128
    u128 o = __i1;
    bool ok = __sync_bool_compare_and_swap(&_M_i, o, i2);
    if (!ok)
      __i1 = _M_i;
    return ok;
  }
};

namespace __cxxabiv1 {
  void (*__terminate_handler)() = cxx_terminate;
  void (*__unexpected_handler)() = cxx_unexpected;
};

static char malloc_buf[65536];
static std::atomic<size_t> malloc_idx;
static bool malloc_proc = false;

extern "C" void* malloc(size_t);
void*
malloc(size_t n)
{
  if (n > PGSIZE) {
    // libgcc_eh needs to allocate a large chunk of memory once
    size_t myoff = atomic_fetch_add(&malloc_idx, n);
    assert(myoff + n <= sizeof(malloc_buf));
    return &malloc_buf[myoff];
  }

  if (malloc_proc) {
    assert(n <= sizeof(myproc()->exception_buf));
    assert(cmpxch(&myproc()->exception_inuse, 0, 1));
    return myproc()->exception_buf;
  }

  u64* p = (u64*) kmalloc(n+8, "cpprt malloc");
  *p = n;
  return p+1;
}

extern "C" void free(void*);
void
free(void* vp)
{
  if (vp >= malloc_buf && vp < malloc_buf + sizeof(malloc_buf))
    return;

  if (vp == myproc()->exception_buf) {
    myproc()->exception_inuse = 0;
    return;
  }

  u64* p = (u64*) vp;
  kmfree(p-1, p[-1]+8);
}

extern "C" int dl_iterate_phdr(void);
int
dl_iterate_phdr(void)
{
  return -1;
}

extern "C" void __stack_chk_fail(void);
void
__stack_chk_fail(void)
{
  panic("stack_chk_fail");
}

extern "C" int pthread_once(int *oncectl, void (*f)(void));
int
pthread_once(int *oncectl, void (*f)(void))
{
  if (__sync_bool_compare_and_swap(oncectl, 0, 1))
    (*f)();

  return 0;
}

extern "C" int pthread_cancel(int tid);
int
pthread_cancel(int tid)
{
  /*
   * This function's job is to contain a non-zero opcode that
   * makes __gthread_active_p in gcc/gthr-posix95.h return 1.
   */
  return 0;
}

extern "C" int pthread_mutex_lock(int *mu);
int
pthread_mutex_lock(int *mu)
{
  while (!__sync_bool_compare_and_swap(mu, 0, 1))
    ; /* spin */
  return 0;
}

extern "C" int pthread_mutex_unlock(int *mu);
int
pthread_mutex_unlock(int *mu)
{
  *mu = 0;
  return 0;
}

extern "C" void* __cxa_get_globals(void);
void*
__cxa_get_globals(void)
{
  return myproc()->__cxa_eh_global;
}

extern "C" void* __cxa_get_globals_fast(void);
void*
__cxa_get_globals_fast(void)
{
  return myproc()->__cxa_eh_global;
}

extern "C" void __register_frame(u8*);
void
initcpprt(void)
{
#if EXCEPTIONS
  extern u8 __EH_FRAME_BEGIN__[];
  __register_frame(__EH_FRAME_BEGIN__);

  // Initialize lazy exception handling data structures
  try {
    throw 5;
  } catch (int& x) {
    assert(x == 5);
    malloc_proc = true;
    return;
  }

  panic("no catch");
#endif
}
<commit_msg>Fix comment; I misunderstood __gthread_active_p<commit_after>#include <new>

#include "types.h"
#include "kernel.hh"
#include "cpputil.hh"
#include "spinlock.h"
#include "amd64.h"
#include "condvar.h"
#include "proc.hh"
#include "cpu.hh"
#include "elf.hh"

const std::nothrow_t std::nothrow;

void*
operator new(std::size_t nbytes)
{
  panic("global operator new");

  u64* x = (u64*) kmalloc(nbytes + sizeof(u64), "cpprt new");
  *x = nbytes;
  return x+1;
}

void
operator delete(void* p) noexcept
{
  panic("global operator delete");

  u64* x = (u64*) p;
  kmfree(x-1, x[-1] + sizeof(u64));
}

void*
operator new[](std::size_t nbytes)
{
  u64* x = (u64*) kmalloc(nbytes + sizeof(u64), "array");
  *x = nbytes;
  return x+1;
}

void
operator delete[](void* p) noexcept
{
  u64* x = (u64*) p;
  kmfree(x-1, x[-1] + sizeof(u64));
}

void *
operator new(std::size_t nbytes, void* buf) noexcept
{
  return buf;
}

void
operator delete(void* ptr, void*) noexcept
{
}

void
__cxa_pure_virtual(void)
{
  panic("__cxa_pure_virtual");
}

int
__cxa_guard_acquire(s64 *guard)
{
  volatile u8 *x = (u8*) guard;
  volatile u32 *l = (u32*) (x+4);

  pushcli();
  while (xchg32(l, 1) != 0)
    ; /* spin */

  if (*x) {
    xchg32(l, 0);
    popcli();
    return 0;
  }
  return 1;
}

void
__cxa_guard_release(s64 *guard)
{
  volatile u8 *x = (u8*) guard;
  volatile u32 *l = (u32*) (x+4);

  *x = 1;
  __sync_synchronize();
  xchg32(l, 0);
  popcli();
}

void
__cxa_guard_abort(s64 *guard)
{
  volatile u8 *x = (u8*) guard;
  volatile u32 *l = (u32*) (x+4);

  xchg32(l, 0);
  popcli();
}

int
__cxa_atexit(void (*f)(void*), void *p, void *d)
{
  return 0;
}

extern "C" void abort(void);
void
abort(void)
{
  panic("abort");
}

static void
cxx_terminate(void)
{
  panic("cxx terminate");
}

static void
cxx_unexpected(void)
{
  panic("cxx unexpected");
}

void *__dso_handle;

namespace std {
  std::ostream cout;

  template<>
  u128
  atomic<u128>::load(memory_order __m) const
  {
    __sync_synchronize();
    u128 v = _M_i;
    __sync_synchronize();

    return v;
  }

  template<>
  bool
  atomic<u128>::compare_exchange_weak(u128 &__i1, u128 i2, memory_order __m)
  {
    // XXX no __sync_val_compare_and_swap for u128
    u128 o = __i1;
    bool ok = __sync_bool_compare_and_swap(&_M_i, o, i2);
    if (!ok)
      __i1 = _M_i;
    return ok;
  }
};

namespace __cxxabiv1 {
  void (*__terminate_handler)() = cxx_terminate;
  void (*__unexpected_handler)() = cxx_unexpected;
};

static char malloc_buf[65536];
static std::atomic<size_t> malloc_idx;
static bool malloc_proc = false;

extern "C" void* malloc(size_t);
void*
malloc(size_t n)
{
  if (n > PGSIZE) {
    // libgcc_eh needs to allocate a large chunk of memory once
    size_t myoff = atomic_fetch_add(&malloc_idx, n);
    assert(myoff + n <= sizeof(malloc_buf));
    return &malloc_buf[myoff];
  }

  if (malloc_proc) {
    assert(n <= sizeof(myproc()->exception_buf));
    assert(cmpxch(&myproc()->exception_inuse, 0, 1));
    return myproc()->exception_buf;
  }

  u64* p = (u64*) kmalloc(n+8, "cpprt malloc");
  *p = n;
  return p+1;
}

extern "C" void free(void*);
void
free(void* vp)
{
  if (vp >= malloc_buf && vp < malloc_buf + sizeof(malloc_buf))
    return;

  if (vp == myproc()->exception_buf) {
    myproc()->exception_inuse = 0;
    return;
  }

  u64* p = (u64*) vp;
  kmfree(p-1, p[-1]+8);
}

extern "C" int dl_iterate_phdr(void);
int
dl_iterate_phdr(void)
{
  return -1;
}

extern "C" void __stack_chk_fail(void);
void
__stack_chk_fail(void)
{
  panic("stack_chk_fail");
}

extern "C" int pthread_once(int *oncectl, void (*f)(void));
int
pthread_once(int *oncectl, void (*f)(void))
{
  if (__sync_bool_compare_and_swap(oncectl, 0, 1))
    (*f)();

  return 0;
}

extern "C" int pthread_cancel(int tid);
int
pthread_cancel(int tid)
{
  /*
   * This function's job is to make __gthread_active_p
   * in gcc/gthr-posix95.h return 1.
   */
  return 0;
}

extern "C" int pthread_mutex_lock(int *mu);
int
pthread_mutex_lock(int *mu)
{
  while (!__sync_bool_compare_and_swap(mu, 0, 1))
    ; /* spin */
  return 0;
}

extern "C" int pthread_mutex_unlock(int *mu);
int
pthread_mutex_unlock(int *mu)
{
  *mu = 0;
  return 0;
}

extern "C" void* __cxa_get_globals(void);
void*
__cxa_get_globals(void)
{
  return myproc()->__cxa_eh_global;
}

extern "C" void* __cxa_get_globals_fast(void);
void*
__cxa_get_globals_fast(void)
{
  return myproc()->__cxa_eh_global;
}

extern "C" void __register_frame(u8*);
void
initcpprt(void)
{
#if EXCEPTIONS
  extern u8 __EH_FRAME_BEGIN__[];
  __register_frame(__EH_FRAME_BEGIN__);

  // Initialize lazy exception handling data structures
  try {
    throw 5;
  } catch (int& x) {
    assert(x == 5);
    malloc_proc = true;
    return;
  }

  panic("no catch");
#endif
}
<|endoftext|>