<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/nest/p9_fbc_utils.C $      */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
///
/// @file p9_fbc_utils.C
/// @brief Fabric library functions/constants (FAPI2)
///
/// The functions in this file provide:
/// - Information about the instantaneous state of the fabric
/// - Means to restart the fabric after a checkstop condition
/// - Determination of the chip's base address in the real address map
///
/// @author Joe McGill <jmcgill@us.ibm.com>
/// @author Christy Graves <clgraves@us.ibm.com>
///

//
// *HWP HWP Owner: Joe McGill <jmcgill@us.ibm.com>
// *HWP FW Owner: Thi Tran <thi@us.ibm.com>
// *HWP Team: Nest
// *HWP Level: 2
// *HWP Consumed by: SBE,HB,FSP
//

//------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------
#include <p9_fbc_utils.H>
#include <p9_misc_scom_addresses.H>

//------------------------------------------------------------------------------
// Constant definitions
//------------------------------------------------------------------------------

// ADU PMisc Register field/bit definitions
const uint32_t ALTD_SND_MODE_DISABLE_CHECKSTOP_BIT = 19;
const uint32_t ALTD_SND_MODE_MANUAL_CLR_PB_STOP_BIT = 21;
const uint32_t ALTD_SND_MODE_PB_STOP_BIT = 22;

// FBC Mode Register field/bit definitions
const uint32_t PU_FBC_MODE_PB_INITIALIZED_BIT = 0;

// FBC base address determination constants
// system ID (large system)
const uint8_t FABRIC_ADDR_LS_SYSTEM_ID_START_BIT = 8;
const uint8_t FABRIC_ADDR_LS_SYSTEM_ID_END_BIT = 12;
// system ID (small system)
const uint8_t FABRIC_ADDR_SS_SYSTEM_ID_FLD0_START_BIT = 8;
const uint8_t FABRIC_ADDR_SS_SYSTEM_ID_FLD0_END_BIT = 12;
const uint8_t FABRIC_ADDR_SS_SYSTEM_ID_FLD0_SHIFT = 5;
const uint8_t FABRIC_ADDR_SS_SYSTEM_ID_FLD0_MASK = 0x1F;
const uint8_t FABRIC_ADDR_SS_SYSTEM_ID_FLD1_START_BIT = 15;
const uint8_t FABRIC_ADDR_SS_SYSTEM_ID_FLD1_END_BIT = 16;
const uint8_t FABRIC_ADDR_SS_SYSTEM_ID_FLD1_SHIFT = 3;
const uint8_t FABRIC_ADDR_SS_SYSTEM_ID_FLD1_MASK = 0x3;
const uint8_t FABRIC_ADDR_SS_SYSTEM_ID_FLD2_START_BIT = 19;
const uint8_t FABRIC_ADDR_SS_SYSTEM_ID_FLD2_END_BIT = 21;
const uint8_t FABRIC_ADDR_SS_SYSTEM_ID_FLD2_SHIFT = 0;
const uint8_t FABRIC_ADDR_SS_SYSTEM_ID_FLD2_MASK = 0x7;
// group ID (large system)
const uint8_t FABRIC_ADDR_LS_GROUP_ID_START_BIT = 15;
const uint8_t FABRIC_ADDR_LS_GROUP_ID_END_BIT = 18;
// group ID (small system)
const uint8_t FABRIC_ADDR_SS_GROUP_ID_START_BIT = 17;
const uint8_t FABRIC_ADDR_SS_GROUP_ID_END_BIT = 18;
// chip ID (large system)
const uint8_t FABRIC_ADDR_LS_CHIP_ID_START_BIT = 19;
const uint8_t FABRIC_ADDR_LS_CHIP_ID_END_BIT = 21;
// msel bit (large & small system)
const uint8_t FABRIC_ADDR_MSEL_BIT = 13;

//------------------------------------------------------------------------------
// Function definitions
//------------------------------------------------------------------------------

fapi2::ReturnCode p9_fbc_utils_get_fbc_state(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target,
    bool& o_is_initialized,
    bool& o_is_running)
{
    FAPI_DBG("Start");

    // TODO: HW328175
    // fapi2::buffer<uint64_t> l_fbc_mode_data;
    // FAPI_TRY(fapi2::getScom(i_target, PU_FBC_MODE_REG, l_fbc_mode_data),
    //          "Error reading FBC Mode Register");
    // // fabric is initialized if PB_INITIALIZED bit is one/set
    // o_is_initialized = l_fbc_mode_data.getBit<PU_FBC_MODE_PB_INITIALIZED_BIT>();

    // currently, sampling FBC init from PB Mode register is unreliable
    // as init can drop perodically at runtime (based on legacy sleep backoff)
    // until this issue is fixed, just return true to caller
    o_is_initialized = true;

    // read ADU PMisc Mode Register state
    fapi2::buffer<uint64_t> l_pmisc_mode_data;
    FAPI_TRY(fapi2::getScom(i_target, PU_SND_MODE_REG, l_pmisc_mode_data),
             "Error reading ADU PMisc Mode register");

    // fabric is running if FBC_STOP bit is zero/clear
    o_is_running = !(l_pmisc_mode_data.getBit<ALTD_SND_MODE_PB_STOP_BIT>());

fapi_try_exit:
    FAPI_DBG("End");
    return fapi2::current_err;
}

fapi2::ReturnCode p9_fbc_utils_override_fbc_stop(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target)
{
    FAPI_DBG("Start");

    // read ADU PMisc Mode Register state
    fapi2::buffer<uint64_t> l_pmisc_mode_data;
    FAPI_TRY(fapi2::getScom(i_target, PU_SND_MODE_REG, l_pmisc_mode_data),
             "Error reading ADU PMisc Mode register");

    // set bit to disable checkstop forwarding and write back
    l_pmisc_mode_data.setBit<ALTD_SND_MODE_DISABLE_CHECKSTOP_BIT>();
    FAPI_TRY(fapi2::putScom(i_target, PU_SND_MODE_REG, l_pmisc_mode_data),
             "Error writing ADU PMisc Mode register to disable checkstop forwarding to FBC");

    // set bit to manually clear stop control and write back
    l_pmisc_mode_data.setBit<ALTD_SND_MODE_MANUAL_CLR_PB_STOP_BIT>();
    FAPI_TRY(fapi2::putScom(i_target, PU_SND_MODE_REG, l_pmisc_mode_data),
             "Error writing ADU PMisc Mode register to manually clear FBC stop control");

fapi_try_exit:
    FAPI_DBG("End");
    return fapi2::current_err;
}

fapi2::ReturnCode p9_fbc_utils_get_chip_base_address(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target,
    uint64_t& o_base_address_nm,
    uint64_t& o_base_address_m)
{
    uint32_t l_fabric_system_id;
    uint8_t l_fabric_group_id;
    uint8_t l_fabric_chip_id;
    uint8_t l_fabric_addr_bar_mode;
    uint8_t l_msel;
    fapi2::buffer<uint64_t> l_base_address;
    const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> FAPI_SYSTEM;

    FAPI_DBG("Start");

    // retreive attributes which statically determine chip's position in memory map
    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PROC_FABRIC_SYSTEM_ID, i_target, l_fabric_system_id),
             "Error from FAPI_ATTR_GET (ATTR_FABRIC_SYSTEM_ID)");
    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PROC_FABRIC_GROUP_ID, i_target, l_fabric_group_id),
             "Error from FAPI_ATTR_GET (ATTR_FABRIC_GROUP_ID)");
    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PROC_FABRIC_CHIP_ID, i_target, l_fabric_chip_id),
             "Error from FAPI_ATTR_GET (ATTR_FABRIC_CHIP_ID)");

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PROC_FABRIC_ADDR_BAR_MODE, FAPI_SYSTEM, l_fabric_addr_bar_mode),
             "Error from FAPI_ATTR_GET (ATTR_PROC_FABRIC_ADDR_BAR_MODE)");

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_MEM_MIRROR_PLACEMENT_POLICY, FAPI_SYSTEM, l_msel),
             "Error from FAPI_ATTR_GET (ATTR_MEM_MIRROR_PLACEMENT_POLICY)");

    // apply system ID
    // occupies one field for large system map, split into three fields for small system map
    if (l_fabric_addr_bar_mode == fapi2::ENUM_ATTR_PROC_FABRIC_ADDR_BAR_MODE_LARGE_SYSTEM)
    {
        l_base_address.insertFromRight < FABRIC_ADDR_LS_SYSTEM_ID_START_BIT,
                                       (FABRIC_ADDR_LS_SYSTEM_ID_END_BIT - FABRIC_ADDR_LS_SYSTEM_ID_START_BIT + 1) > (l_fabric_system_id);
    }
    else
    {
        uint32_t l_fabric_system_id_fld = (l_fabric_system_id >> FABRIC_ADDR_SS_SYSTEM_ID_FLD0_SHIFT) &
                                          FABRIC_ADDR_SS_SYSTEM_ID_FLD0_MASK;
        l_base_address.insertFromRight < FABRIC_ADDR_SS_SYSTEM_ID_FLD0_START_BIT,
                                       (FABRIC_ADDR_SS_SYSTEM_ID_FLD0_END_BIT - FABRIC_ADDR_SS_SYSTEM_ID_FLD0_START_BIT + 1) > (l_fabric_system_id_fld);

        l_fabric_system_id_fld = (l_fabric_system_id >> FABRIC_ADDR_SS_SYSTEM_ID_FLD1_SHIFT) &
                                 FABRIC_ADDR_SS_SYSTEM_ID_FLD1_MASK;
        l_base_address.insertFromRight < FABRIC_ADDR_SS_SYSTEM_ID_FLD1_START_BIT,
                                       (FABRIC_ADDR_SS_SYSTEM_ID_FLD1_END_BIT - FABRIC_ADDR_SS_SYSTEM_ID_FLD1_START_BIT + 1) > (l_fabric_system_id_fld);

        l_fabric_system_id_fld = (l_fabric_system_id >> FABRIC_ADDR_SS_SYSTEM_ID_FLD2_SHIFT) &
                                 FABRIC_ADDR_SS_SYSTEM_ID_FLD2_MASK;
        l_base_address.insertFromRight < FABRIC_ADDR_SS_SYSTEM_ID_FLD2_START_BIT,
                                       (FABRIC_ADDR_SS_SYSTEM_ID_FLD2_END_BIT - FABRIC_ADDR_SS_SYSTEM_ID_FLD2_START_BIT + 1) > (l_fabric_system_id_fld);
    }

    // apply group ID
    if (l_fabric_addr_bar_mode == fapi2::ENUM_ATTR_PROC_FABRIC_ADDR_BAR_MODE_LARGE_SYSTEM)
    {
        l_base_address.insertFromRight < FABRIC_ADDR_LS_GROUP_ID_START_BIT,
                                       (FABRIC_ADDR_LS_GROUP_ID_END_BIT - FABRIC_ADDR_LS_GROUP_ID_START_BIT + 1) > (l_fabric_group_id);
    }
    else
    {
        l_base_address.insertFromRight < FABRIC_ADDR_SS_GROUP_ID_START_BIT,
                                       (FABRIC_ADDR_SS_GROUP_ID_END_BIT - FABRIC_ADDR_SS_GROUP_ID_START_BIT + 1) > (l_fabric_group_id);
    }

    // apply chip ID (relevant for large system map only)
    if (l_fabric_addr_bar_mode == fapi2::ENUM_ATTR_PROC_FABRIC_ADDR_BAR_MODE_LARGE_SYSTEM)
    {
        l_base_address.insertFromRight < FABRIC_ADDR_LS_CHIP_ID_START_BIT,
                                       (FABRIC_ADDR_LS_CHIP_ID_END_BIT - FABRIC_ADDR_LS_CHIP_ID_START_BIT + 1) > (l_fabric_chip_id);
    }

    // set output addresses based on application of msel
    if (l_msel == fapi2::ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_NORMAL)
    {
        // nm = 0b00, m = 0b10
        o_base_address_nm = l_base_address();
        l_base_address.setBit(FABRIC_ADDR_MSEL_BIT);
        o_base_address_m = l_base_address();
    }
    else
    {
        // m = 0b10, m = 0b00
        o_base_address_m = l_base_address();
        l_base_address.setBit(FABRIC_ADDR_MSEL_BIT);
        o_base_address_nm = l_base_address();
    }

fapi_try_exit:
    FAPI_DBG("End");
    return fapi2::current_err;
}
<commit_msg>L2 HWP -- p9_setup_bars<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/nest/p9_fbc_utils.C $      */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
///
/// @file p9_fbc_utils.C
/// @brief Fabric library functions/constants (FAPI2)
///
/// The functions in this file provide:
/// - Information about the instantaneous state of the fabric
/// - Means to restart the fabric after a checkstop condition
/// - Determination of the chip's base address in the real address map
///
/// @author Joe McGill <jmcgill@us.ibm.com>
/// @author Christy Graves <clgraves@us.ibm.com>
///

//
// *HWP HWP Owner: Joe McGill <jmcgill@us.ibm.com>
// *HWP FW Owner: Thi Tran <thi@us.ibm.com>
// *HWP Team: Nest
// *HWP Level: 2
// *HWP Consumed by: SBE,HB,FSP
//

//------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------
#include <p9_fbc_utils.H>
#include <p9_misc_scom_addresses.H>

//------------------------------------------------------------------------------
// Constant definitions
//------------------------------------------------------------------------------

// ADU PMisc Register field/bit definitions
const uint32_t ALTD_SND_MODE_DISABLE_CHECKSTOP_BIT = 19;
const uint32_t ALTD_SND_MODE_MANUAL_CLR_PB_STOP_BIT = 21;
const uint32_t ALTD_SND_MODE_PB_STOP_BIT = 22;

// FBC Mode Register field/bit definitions
const uint32_t PU_FBC_MODE_PB_INITIALIZED_BIT = 0;

// FBC base address determination constants
// system ID (large system)
const uint8_t FABRIC_ADDR_LS_SYSTEM_ID_START_BIT = 8;
const uint8_t FABRIC_ADDR_LS_SYSTEM_ID_END_BIT = 12;
// system ID (small system)
const uint8_t FABRIC_ADDR_SS_SYSTEM_ID_FLD0_START_BIT = 8;
const uint8_t FABRIC_ADDR_SS_SYSTEM_ID_FLD0_END_BIT = 12;
const uint8_t FABRIC_ADDR_SS_SYSTEM_ID_FLD0_SHIFT = 5;
const uint8_t FABRIC_ADDR_SS_SYSTEM_ID_FLD0_MASK = 0x1F;
const uint8_t FABRIC_ADDR_SS_SYSTEM_ID_FLD1_START_BIT = 15;
const uint8_t FABRIC_ADDR_SS_SYSTEM_ID_FLD1_END_BIT = 16;
const uint8_t FABRIC_ADDR_SS_SYSTEM_ID_FLD1_SHIFT = 3;
const uint8_t FABRIC_ADDR_SS_SYSTEM_ID_FLD1_MASK = 0x3;
const uint8_t FABRIC_ADDR_SS_SYSTEM_ID_FLD2_START_BIT = 19;
const uint8_t FABRIC_ADDR_SS_SYSTEM_ID_FLD2_END_BIT = 21;
const uint8_t FABRIC_ADDR_SS_SYSTEM_ID_FLD2_SHIFT = 0;
const uint8_t FABRIC_ADDR_SS_SYSTEM_ID_FLD2_MASK = 0x7;
// group ID (large system)
const uint8_t FABRIC_ADDR_LS_GROUP_ID_START_BIT = 15;
const uint8_t FABRIC_ADDR_LS_GROUP_ID_END_BIT = 18;
// group ID (small system)
const uint8_t FABRIC_ADDR_SS_GROUP_ID_START_BIT = 17;
const uint8_t FABRIC_ADDR_SS_GROUP_ID_END_BIT = 18;
// chip ID (large system)
const uint8_t FABRIC_ADDR_LS_CHIP_ID_START_BIT = 19;
const uint8_t FABRIC_ADDR_LS_CHIP_ID_END_BIT = 21;
// msel bits (large & small system)
const uint8_t FABRIC_ADDR_MSEL_START_BIT = 13;
const uint8_t FABRIC_ADDR_MSEL_END_BIT = 14;

//------------------------------------------------------------------------------
// Function definitions
//------------------------------------------------------------------------------

fapi2::ReturnCode p9_fbc_utils_get_fbc_state(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target,
    bool& o_is_initialized,
    bool& o_is_running)
{
    FAPI_DBG("Start");

    // TODO: HW328175
    // fapi2::buffer<uint64_t> l_fbc_mode_data;
    // FAPI_TRY(fapi2::getScom(i_target, PU_FBC_MODE_REG, l_fbc_mode_data),
    //          "Error reading FBC Mode Register");
    // // fabric is initialized if PB_INITIALIZED bit is one/set
    // o_is_initialized = l_fbc_mode_data.getBit<PU_FBC_MODE_PB_INITIALIZED_BIT>();

    // currently, sampling FBC init from PB Mode register is unreliable
    // as init can drop perodically at runtime (based on legacy sleep backoff)
    // until this issue is fixed, just return true to caller
    o_is_initialized = true;

    // read ADU PMisc Mode Register state
    fapi2::buffer<uint64_t> l_pmisc_mode_data;
    FAPI_TRY(fapi2::getScom(i_target, PU_SND_MODE_REG, l_pmisc_mode_data),
             "Error reading ADU PMisc Mode register");

    // fabric is running if FBC_STOP bit is zero/clear
    o_is_running = !(l_pmisc_mode_data.getBit<ALTD_SND_MODE_PB_STOP_BIT>());

fapi_try_exit:
    FAPI_DBG("End");
    return fapi2::current_err;
}

fapi2::ReturnCode p9_fbc_utils_override_fbc_stop(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target)
{
    FAPI_DBG("Start");

    // read ADU PMisc Mode Register state
    fapi2::buffer<uint64_t> l_pmisc_mode_data;
    FAPI_TRY(fapi2::getScom(i_target, PU_SND_MODE_REG, l_pmisc_mode_data),
             "Error reading ADU PMisc Mode register");

    // set bit to disable checkstop forwarding and write back
    l_pmisc_mode_data.setBit<ALTD_SND_MODE_DISABLE_CHECKSTOP_BIT>();
    FAPI_TRY(fapi2::putScom(i_target, PU_SND_MODE_REG, l_pmisc_mode_data),
             "Error writing ADU PMisc Mode register to disable checkstop forwarding to FBC");

    // set bit to manually clear stop control and write back
    l_pmisc_mode_data.setBit<ALTD_SND_MODE_MANUAL_CLR_PB_STOP_BIT>();
    FAPI_TRY(fapi2::putScom(i_target, PU_SND_MODE_REG, l_pmisc_mode_data),
             "Error writing ADU PMisc Mode register to manually clear FBC stop control");

fapi_try_exit:
    FAPI_DBG("End");
    return fapi2::current_err;
}

fapi2::ReturnCode p9_fbc_utils_get_chip_base_address(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target,
    uint64_t& o_base_address_nm0,
    uint64_t& o_base_address_nm1,
    uint64_t& o_base_address_m,
    uint64_t& o_base_address_mmio)
{
    uint32_t l_fabric_system_id;
    uint8_t l_fabric_group_id;
    uint8_t l_fabric_chip_id;
    uint8_t l_fabric_addr_bar_mode;
    uint8_t l_mirror_policy;
    fapi2::buffer<uint64_t> l_base_address;
    const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> FAPI_SYSTEM;

    FAPI_DBG("Start");

    // retreive attributes which statically determine chip's position in memory map
    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PROC_FABRIC_SYSTEM_ID, i_target, l_fabric_system_id),
             "Error from FAPI_ATTR_GET (ATTR_FABRIC_SYSTEM_ID)");
    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PROC_FABRIC_GROUP_ID, i_target, l_fabric_group_id),
             "Error from FAPI_ATTR_GET (ATTR_FABRIC_GROUP_ID)");
    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PROC_FABRIC_CHIP_ID, i_target, l_fabric_chip_id),
             "Error from FAPI_ATTR_GET (ATTR_FABRIC_CHIP_ID)");

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PROC_FABRIC_ADDR_BAR_MODE, FAPI_SYSTEM, l_fabric_addr_bar_mode),
             "Error from FAPI_ATTR_GET (ATTR_PROC_FABRIC_ADDR_BAR_MODE)");

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_MEM_MIRROR_PLACEMENT_POLICY, FAPI_SYSTEM, l_mirror_policy),
             "Error from FAPI_ATTR_GET (ATTR_MEM_MIRROR_PLACEMENT_POLICY)");

    // apply system ID
    // occupies one field for large system map, split into three fields for small system map
    if (l_fabric_addr_bar_mode == fapi2::ENUM_ATTR_PROC_FABRIC_ADDR_BAR_MODE_LARGE_SYSTEM)
    {
        l_base_address.insertFromRight < FABRIC_ADDR_LS_SYSTEM_ID_START_BIT,
                                       (FABRIC_ADDR_LS_SYSTEM_ID_END_BIT - FABRIC_ADDR_LS_SYSTEM_ID_START_BIT + 1) > (l_fabric_system_id);
    }
    else
    {
        uint32_t l_fabric_system_id_fld = (l_fabric_system_id >> FABRIC_ADDR_SS_SYSTEM_ID_FLD0_SHIFT) &
                                          FABRIC_ADDR_SS_SYSTEM_ID_FLD0_MASK;
        l_base_address.insertFromRight < FABRIC_ADDR_SS_SYSTEM_ID_FLD0_START_BIT,
                                       (FABRIC_ADDR_SS_SYSTEM_ID_FLD0_END_BIT - FABRIC_ADDR_SS_SYSTEM_ID_FLD0_START_BIT + 1) > (l_fabric_system_id_fld);

        l_fabric_system_id_fld = (l_fabric_system_id >> FABRIC_ADDR_SS_SYSTEM_ID_FLD1_SHIFT) &
                                 FABRIC_ADDR_SS_SYSTEM_ID_FLD1_MASK;
        l_base_address.insertFromRight < FABRIC_ADDR_SS_SYSTEM_ID_FLD1_START_BIT,
                                       (FABRIC_ADDR_SS_SYSTEM_ID_FLD1_END_BIT - FABRIC_ADDR_SS_SYSTEM_ID_FLD1_START_BIT + 1) > (l_fabric_system_id_fld);

        l_fabric_system_id_fld = (l_fabric_system_id >> FABRIC_ADDR_SS_SYSTEM_ID_FLD2_SHIFT) &
                                 FABRIC_ADDR_SS_SYSTEM_ID_FLD2_MASK;
        l_base_address.insertFromRight < FABRIC_ADDR_SS_SYSTEM_ID_FLD2_START_BIT,
                                       (FABRIC_ADDR_SS_SYSTEM_ID_FLD2_END_BIT - FABRIC_ADDR_SS_SYSTEM_ID_FLD2_START_BIT + 1) > (l_fabric_system_id_fld);
    }

    // apply group ID
    if (l_fabric_addr_bar_mode == fapi2::ENUM_ATTR_PROC_FABRIC_ADDR_BAR_MODE_LARGE_SYSTEM)
    {
        l_base_address.insertFromRight < FABRIC_ADDR_LS_GROUP_ID_START_BIT,
                                       (FABRIC_ADDR_LS_GROUP_ID_END_BIT - FABRIC_ADDR_LS_GROUP_ID_START_BIT + 1) > (l_fabric_group_id);
    }
    else
    {
        l_base_address.insertFromRight < FABRIC_ADDR_SS_GROUP_ID_START_BIT,
                                       (FABRIC_ADDR_SS_GROUP_ID_END_BIT - FABRIC_ADDR_SS_GROUP_ID_START_BIT + 1) > (l_fabric_group_id);
    }

    // apply chip ID (relevant for large system map only)
    if (l_fabric_addr_bar_mode == fapi2::ENUM_ATTR_PROC_FABRIC_ADDR_BAR_MODE_LARGE_SYSTEM)
    {
        l_base_address.insertFromRight < FABRIC_ADDR_LS_CHIP_ID_START_BIT,
                                       (FABRIC_ADDR_LS_CHIP_ID_END_BIT - FABRIC_ADDR_LS_CHIP_ID_START_BIT + 1) > (l_fabric_chip_id);
    }

    // set output addresses based on application of msel
    if (l_mirror_policy == fapi2::ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_NORMAL)
    {
        // nm = 0b00/01, m = 0b10, mmio = 0b11
        o_base_address_nm0 = l_base_address();               // 00
        l_base_address.setBit<FABRIC_ADDR_MSEL_END_BIT>();
        o_base_address_nm1 = l_base_address();               // 01
        l_base_address.setBit<FABRIC_ADDR_MSEL_START_BIT>();
        l_base_address.clearBit<FABRIC_ADDR_MSEL_END_BIT>();
        o_base_address_m = l_base_address();                 // 10
        l_base_address.setBit(FABRIC_ADDR_MSEL_END_BIT);
        o_base_address_mmio = l_base_address();              // 11
    }
    else
    {
        // nm = 0b01/10, m = 0b00, mmio = 0b11
        o_base_address_m = l_base_address();                 // 00
        l_base_address.setBit<FABRIC_ADDR_MSEL_END_BIT>();
        o_base_address_nm0 = l_base_address();               // 01
        l_base_address.setBit<FABRIC_ADDR_MSEL_START_BIT>();
        l_base_address.clearBit<FABRIC_ADDR_MSEL_END_BIT>();
        o_base_address_nm1 = l_base_address();               // 10
        l_base_address.setBit<FABRIC_ADDR_MSEL_END_BIT>();
        o_base_address_mmio = l_base_address();              // 11
    }

fapi_try_exit:
    FAPI_DBG("End");
    return fapi2::current_err;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2018 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include <cmath>
#include "SkBuffer.h"
#include "SkData.h"
#include "SkMath.h"
#include "SkPathPriv.h"
#include "SkPathRef.h"
#include "SkRRect.h"
#include "SkSafeMath.h"

enum SerializationOffsets {
    kType_SerializationShift = 28,       // requires 4 bits
    kDirection_SerializationShift = 26,  // requires 2 bits
    kFillType_SerializationShift = 8,    // requires 8 bits
    // low-8-bits are version
    kVersion_SerializationMask = 0xFF,
};

enum SerializationVersions {
    // kPathPrivFirstDirection_Version = 1,
    kPathPrivLastMoveToIndex_Version = 2,
    kPathPrivTypeEnumVersion = 3,
    kJustPublicData_Version = 4,

    kCurrent_Version = kJustPublicData_Version
};

enum SerializationType {
    kGeneral = 0,
    kRRect = 1
};

static unsigned extract_version(uint32_t packed) {
    return packed & kVersion_SerializationMask;
}

static SkPath::FillType extract_filltype(uint32_t packed) {
    return static_cast<SkPath::FillType>((packed >> kFillType_SerializationShift) & 0x3);
}

static SerializationType extract_serializationtype(uint32_t packed) {
    return static_cast<SerializationType>((packed >> kType_SerializationShift) & 0xF);
}

///////////////////////////////////////////////////////////////////////////////////////////////////

size_t SkPath::writeToMemoryAsRRect(void* storage) const {
    SkRect oval;
    SkRRect rrect;
    bool isCCW;
    unsigned start;
    if (fPathRef->isOval(&oval, &isCCW, &start)) {
        rrect.setOval(oval);
        // Convert to rrect start indices.
        start *= 2;
    } else if (!fPathRef->isRRect(&rrect, &isCCW, &start)) {
        return 0;
    }

    // packed header, rrect, start index.
    const size_t sizeNeeded = sizeof(int32_t) + SkRRect::kSizeInMemory + sizeof(int32_t);
    if (!storage) {
        return sizeNeeded;
    }

    int firstDir = isCCW ? SkPathPriv::kCCW_FirstDirection : SkPathPriv::kCW_FirstDirection;
    int32_t packed = (fFillType << kFillType_SerializationShift) |
                     (firstDir << kDirection_SerializationShift) |
                     (SerializationType::kRRect << kType_SerializationShift) |
                     kCurrent_Version;

    SkWBuffer buffer(storage);
    buffer.write32(packed);
    rrect.writeToBuffer(&buffer);
    buffer.write32(SkToS32(start));
    buffer.padToAlign4();
    SkASSERT(sizeNeeded == buffer.pos());
    return buffer.pos();
}

size_t SkPath::writeToMemory(void* storage) const {
    SkDEBUGCODE(this->validate();)

    if (size_t bytes = this->writeToMemoryAsRRect(storage)) {
        return bytes;
    }

    int32_t packed = (fFillType << kFillType_SerializationShift) |
                     (SerializationType::kGeneral << kType_SerializationShift) |
                     kCurrent_Version;

    int32_t pts = fPathRef->countPoints();
    int32_t cnx = fPathRef->countWeights();
    int32_t vbs = fPathRef->countVerbs();

    SkSafeMath safe;
    size_t size = 4 * sizeof(int32_t);
    size = safe.add(size, safe.mul(pts, sizeof(SkPoint)));
    size = safe.add(size, safe.mul(cnx, sizeof(SkScalar)));
    size = safe.add(size, safe.mul(vbs, sizeof(uint8_t)));
    size = safe.alignUp(size, 4);
    if (!safe) {
        return 0;
    }
    if (!storage) {
        return size;
    }

    SkWBuffer buffer(storage);
    buffer.write32(packed);
    buffer.write32(pts);
    buffer.write32(cnx);
    buffer.write32(vbs);
    buffer.write(fPathRef->points(), pts * sizeof(SkPoint));
    buffer.write(fPathRef->conicWeights(), cnx * sizeof(SkScalar));
    buffer.write(fPathRef->verbsMemBegin(), vbs * sizeof(uint8_t));
    buffer.padToAlign4();

    SkASSERT(buffer.pos() == size);
    return size;
}

sk_sp<SkData> SkPath::serialize() const {
    size_t size = this->writeToMemory(nullptr);
    sk_sp<SkData> data = SkData::MakeUninitialized(size);
    this->writeToMemory(data->writable_data());
    return data;
}

//////////////////////////////////////////////////////////////////////////////////////////////////
// reading

size_t SkPath::readFromMemory(const void* storage, size_t length) {
    SkRBuffer buffer(storage, length);
    uint32_t packed;
    if (!buffer.readU32(&packed)) {
        return 0;
    }
    unsigned version = extract_version(packed);
    if (version <= kPathPrivTypeEnumVersion) {
        return this->readFromMemory_LE3(storage, length);
    }
    if (version == kJustPublicData_Version) {
        return this->readFromMemory_EQ4(storage, length);
    }
    return 0;
}

size_t SkPath::readAsRRect(const void* storage, size_t length) {
    SkRBuffer buffer(storage, length);
    uint32_t packed;
    if (!buffer.readU32(&packed)) {
        return 0;
    }

    SkASSERT(extract_serializationtype(packed) == SerializationType::kRRect);

    uint8_t dir = (packed >> kDirection_SerializationShift) & 0x3;
    FillType fillType = extract_filltype(packed);

    Direction rrectDir;
    SkRRect rrect;
    int32_t start;
    switch (dir) {
        case SkPathPriv::kCW_FirstDirection:
            rrectDir = kCW_Direction;
            break;
        case SkPathPriv::kCCW_FirstDirection:
            rrectDir = kCCW_Direction;
            break;
        default:
            return 0;
    }
    if (!rrect.readFromBuffer(&buffer)) {
        return 0;
    }
    if (!buffer.readS32(&start) || start != SkTPin(start, 0, 7)) {
        return 0;
    }
    this->reset();
    this->addRRect(rrect, rrectDir, SkToUInt(start));
    this->setFillType(fillType);
    buffer.skipToAlign4();
    return buffer.pos();
}

size_t SkPath::readFromMemory_EQ4(const void* storage, size_t length) {
    SkRBuffer buffer(storage, length);
    uint32_t packed;
    if (!buffer.readU32(&packed)) {
        return 0;
    }

    SkASSERT(extract_version(packed) == 4);

    switch (extract_serializationtype(packed)) {
        case SerializationType::kRRect:
            return this->readAsRRect(storage, length);
        case SerializationType::kGeneral:
            break;  // fall through
        default:
            return 0;
    }

    int32_t pts, cnx, vbs;
    if (!buffer.readS32(&pts) || !buffer.readS32(&cnx) || !buffer.readS32(&vbs)) {
        return 0;
    }

    const SkPoint* points = buffer.skipCount<SkPoint>(pts);
    const SkScalar* conics = buffer.skipCount<SkScalar>(cnx);
    const uint8_t* verbs = buffer.skipCount<uint8_t>(vbs);
    buffer.skipToAlign4();
    if (!buffer.isValid()) {
        return 0;
    }
    SkASSERT(buffer.pos() <= length);

#define CHECK_POINTS_CONICS(p, c)       \
    do {                                \
        if (p && ((pts -= p) < 0)) {    \
            return 0;                   \
        }                               \
        if (c && ((cnx -= c) < 0)) {    \
            return 0;                   \
        }                               \
    } while (0)

    SkPath tmp;
    tmp.setFillType(extract_filltype(packed));
    tmp.incReserve(pts);
    for (int i = vbs - 1; i >= 0; --i) {
        switch (verbs[i]) {
            case kMove_Verb:
                CHECK_POINTS_CONICS(1, 0);
                tmp.moveTo(*points++);
                break;
            case kLine_Verb:
                CHECK_POINTS_CONICS(1, 0);
                tmp.lineTo(*points++);
                break;
            case kQuad_Verb:
                CHECK_POINTS_CONICS(2, 0);
                tmp.quadTo(points[0], points[1]);
                points += 2;
                break;
            case kConic_Verb:
                CHECK_POINTS_CONICS(2, 1);
                tmp.conicTo(points[0], points[1], *conics++);
                points += 2;
                break;
            case kCubic_Verb:
                CHECK_POINTS_CONICS(3, 0);
                tmp.cubicTo(points[0], points[1], points[2]);
                points += 3;
                break;
            case kClose_Verb:
                tmp.close();
                break;
            default:
                return 0;   // bad verb
        }
    }
#undef CHECK_POINTS_CONICS
    if (pts || cnx) {
        return 0;   // leftover points and/or conics
    }

    *this = std::move(tmp);
    return buffer.pos();
}

size_t SkPath::readFromMemory_LE3(const void* storage, size_t length) {
    SkRBuffer buffer(storage, length);

    int32_t packed;
    if (!buffer.readS32(&packed)) {
        return 0;
    }

    unsigned version = extract_version(packed);
    SkASSERT(version <= 3);

    FillType fillType = extract_filltype(packed);
    if (version >= kPathPrivTypeEnumVersion) {
        switch (extract_serializationtype(packed)) {
            case SerializationType::kRRect:
                return this->readAsRRect(storage, length);
            case SerializationType::kGeneral:
                // Fall through to general path deserialization
                break;
            default:
                return 0;
        }
    }
    if (version >= kPathPrivLastMoveToIndex_Version && !buffer.readS32(&fLastMoveToIndex)) {
        return 0;
    }

    // These are written into the serialized data but we no longer use them in the deserialized
    // path. If convexity is corrupted it may cause the GPU backend to make incorrect
    // rendering choices, possibly crashing. We set them to unknown so that they'll be recomputed if
    // requested.
    fConvexity = kUnknown_Convexity;
    fFirstDirection = SkPathPriv::kUnknown_FirstDirection;

    fFillType = fillType;
    fIsVolatile = 0;
    SkPathRef* pathRef = SkPathRef::CreateFromBuffer(&buffer);
    if (!pathRef) {
        return 0;
    }

    fPathRef.reset(pathRef);
    SkDEBUGCODE(this->validate();)
    buffer.skipToAlign4();
    return buffer.pos();
}

<commit_msg>date recent version bump for path serialization<commit_after>/*
 * Copyright 2018 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include <cmath>
#include "SkBuffer.h"
#include "SkData.h"
#include "SkMath.h"
#include "SkPathPriv.h"
#include "SkPathRef.h"
#include "SkRRect.h"
#include "SkSafeMath.h"

enum SerializationOffsets {
    kType_SerializationShift = 28,       // requires 4 bits
    kDirection_SerializationShift = 26,  // requires 2 bits
    kFillType_SerializationShift = 8,    // requires 8 bits
    // low-8-bits are version
    kVersion_SerializationMask = 0xFF,
};

enum SerializationVersions {
    // kPathPrivFirstDirection_Version = 1,
    kPathPrivLastMoveToIndex_Version = 2,
    kPathPrivTypeEnumVersion = 3,
    kJustPublicData_Version = 4,    // introduced Feb/2018

    kCurrent_Version = kJustPublicData_Version
};

enum SerializationType {
    kGeneral = 0,
    kRRect = 1
};

static unsigned extract_version(uint32_t packed) {
    return packed & kVersion_SerializationMask;
}

static SkPath::FillType extract_filltype(uint32_t packed) {
    return static_cast<SkPath::FillType>((packed >> kFillType_SerializationShift) & 0x3);
}

static SerializationType extract_serializationtype(uint32_t packed) {
    return static_cast<SerializationType>((packed >> kType_SerializationShift) & 0xF);
}

///////////////////////////////////////////////////////////////////////////////////////////////////

size_t SkPath::writeToMemoryAsRRect(void* storage) const {
    SkRect oval;
    SkRRect rrect;
    bool isCCW;
    unsigned start;
    if (fPathRef->isOval(&oval, &isCCW, &start)) {
        rrect.setOval(oval);
        // Convert to rrect start indices.
        start *= 2;
    } else if (!fPathRef->isRRect(&rrect, &isCCW, &start)) {
        return 0;
    }

    // packed header, rrect, start index.
    const size_t sizeNeeded = sizeof(int32_t) + SkRRect::kSizeInMemory + sizeof(int32_t);
    if (!storage) {
        return sizeNeeded;
    }

    int firstDir = isCCW ? SkPathPriv::kCCW_FirstDirection : SkPathPriv::kCW_FirstDirection;
    int32_t packed = (fFillType << kFillType_SerializationShift) |
                     (firstDir << kDirection_SerializationShift) |
                     (SerializationType::kRRect << kType_SerializationShift) |
                     kCurrent_Version;

    SkWBuffer buffer(storage);
    buffer.write32(packed);
    rrect.writeToBuffer(&buffer);
    buffer.write32(SkToS32(start));
    buffer.padToAlign4();
    SkASSERT(sizeNeeded == buffer.pos());
    return buffer.pos();
}

size_t SkPath::writeToMemory(void* storage) const {
    SkDEBUGCODE(this->validate();)

    if (size_t bytes = this->writeToMemoryAsRRect(storage)) {
        return bytes;
    }

    int32_t packed = (fFillType << kFillType_SerializationShift) |
                     (SerializationType::kGeneral << kType_SerializationShift) |
                     kCurrent_Version;

    int32_t pts = fPathRef->countPoints();
    int32_t cnx = fPathRef->countWeights();
    int32_t vbs = fPathRef->countVerbs();

    SkSafeMath safe;
    size_t size = 4 * sizeof(int32_t);
    size = safe.add(size, safe.mul(pts, sizeof(SkPoint)));
    size = safe.add(size, safe.mul(cnx, sizeof(SkScalar)));
    size = safe.add(size, safe.mul(vbs, sizeof(uint8_t)));
    size = safe.alignUp(size, 4);
    if (!safe) {
        return 0;
    }
    if (!storage) {
        return size;
    }

    SkWBuffer buffer(storage);
    buffer.write32(packed);
    buffer.write32(pts);
    buffer.write32(cnx);
    buffer.write32(vbs);
    buffer.write(fPathRef->points(), pts * sizeof(SkPoint));
    buffer.write(fPathRef->conicWeights(), cnx * sizeof(SkScalar));
    buffer.write(fPathRef->verbsMemBegin(), vbs * sizeof(uint8_t));
    buffer.padToAlign4();

    SkASSERT(buffer.pos() == size);
    return size;
}

sk_sp<SkData> SkPath::serialize() const {
    size_t size = this->writeToMemory(nullptr);
    sk_sp<SkData> data = SkData::MakeUninitialized(size);
    this->writeToMemory(data->writable_data());
    return data;
}

//////////////////////////////////////////////////////////////////////////////////////////////////
// reading

size_t SkPath::readFromMemory(const void* storage, size_t length) {
    SkRBuffer buffer(storage, length);
    uint32_t packed;
    if (!buffer.readU32(&packed)) {
        return 0;
    }
    unsigned version = extract_version(packed);
    if (version <= kPathPrivTypeEnumVersion) {
        return this->readFromMemory_LE3(storage, length);
    }
    if (version == kJustPublicData_Version) {
        return this->readFromMemory_EQ4(storage, length);
    }
    return 0;
}

size_t SkPath::readAsRRect(const void* storage, size_t length) {
    SkRBuffer buffer(storage, length);
    uint32_t packed;
    if (!buffer.readU32(&packed)) {
        return 0;
    }

    SkASSERT(extract_serializationtype(packed) == SerializationType::kRRect);

    uint8_t dir = (packed >> kDirection_SerializationShift) & 0x3;
    FillType fillType = extract_filltype(packed);

    Direction rrectDir;
    SkRRect rrect;
    int32_t start;
    switch (dir) {
        case SkPathPriv::kCW_FirstDirection:
            rrectDir = kCW_Direction;
            break;
        case SkPathPriv::kCCW_FirstDirection:
            rrectDir = kCCW_Direction;
            break;
        default:
            return 0;
    }
    if (!rrect.readFromBuffer(&buffer)) {
        return 0;
    }
    if (!buffer.readS32(&start) || start != SkTPin(start, 0, 7)) {
        return 0;
    }
    this->reset();
    this->addRRect(rrect, rrectDir, SkToUInt(start));
    this->setFillType(fillType);
    buffer.skipToAlign4();
    return buffer.pos();
}

size_t SkPath::readFromMemory_EQ4(const void* storage, size_t length) {
    SkRBuffer buffer(storage, length);
    uint32_t packed;
    if (!buffer.readU32(&packed)) {
        return 0;
    }

    SkASSERT(extract_version(packed) == 4);

    switch (extract_serializationtype(packed)) {
        case SerializationType::kRRect:
            return this->readAsRRect(storage, length);
        case SerializationType::kGeneral:
            break;  // fall through
        default:
            return 0;
    }

    int32_t pts, cnx, vbs;
    if (!buffer.readS32(&pts) || !buffer.readS32(&cnx) || !buffer.readS32(&vbs)) {
        return 0;
    }

    const SkPoint* points = buffer.skipCount<SkPoint>(pts);
    const SkScalar* conics = buffer.skipCount<SkScalar>(cnx);
    const uint8_t* verbs = buffer.skipCount<uint8_t>(vbs);
    buffer.skipToAlign4();
    if (!buffer.isValid()) {
        return 0;
    }
    SkASSERT(buffer.pos() <= length);

#define CHECK_POINTS_CONICS(p, c)       \
    do {                                \
        if (p && ((pts -= p) < 0)) {    \
            return 0;                   \
        }                               \
        if (c && ((cnx -= c) < 0)) {    \
            return 0;                   \
        }                               \
    } while (0)

    SkPath tmp;
    tmp.setFillType(extract_filltype(packed));
    tmp.incReserve(pts);
    for (int i = vbs - 1; i >= 0; --i) {
        switch (verbs[i]) {
            case kMove_Verb:
                CHECK_POINTS_CONICS(1, 0);
                tmp.moveTo(*points++);
                break;
            case kLine_Verb:
                CHECK_POINTS_CONICS(1, 0);
                tmp.lineTo(*points++);
                break;
            case kQuad_Verb:
                CHECK_POINTS_CONICS(2, 0);
                tmp.quadTo(points[0], points[1]);
                points += 2;
                break;
            case kConic_Verb:
                CHECK_POINTS_CONICS(2, 1);
                tmp.conicTo(points[0], points[1], *conics++);
                points += 2;
                break;
            case kCubic_Verb:
                CHECK_POINTS_CONICS(3, 0);
                tmp.cubicTo(points[0], points[1], points[2]);
                points += 3;
                break;
            case kClose_Verb:
                tmp.close();
                break;
            default:
                return 0;   // bad verb
        }
    }
#undef CHECK_POINTS_CONICS
    if (pts || cnx) {
        return 0;   // leftover points and/or conics
    }

    *this = std::move(tmp);
    return buffer.pos();
}

size_t SkPath::readFromMemory_LE3(const void* storage, size_t length) {
    SkRBuffer buffer(storage, length);

    int32_t packed;
    if (!buffer.readS32(&packed)) {
        return 0;
    }

    unsigned version = extract_version(packed);
    SkASSERT(version <= 3);

    FillType fillType = extract_filltype(packed);
    if (version >= kPathPrivTypeEnumVersion) {
        switch (extract_serializationtype(packed)) {
            case SerializationType::kRRect:
                return this->readAsRRect(storage, length);
            case SerializationType::kGeneral:
                // Fall through to general path deserialization
                break;
            default:
                return 0;
        }
    }
    if (version >= kPathPrivLastMoveToIndex_Version && !buffer.readS32(&fLastMoveToIndex)) {
        return 0;
    }

    // These are written into the serialized data but we no longer use them in the deserialized
    // path. If convexity is corrupted it may cause the GPU backend to make incorrect
    // rendering choices, possibly crashing. We set them to unknown so that they'll be recomputed if
    // requested.
    fConvexity = kUnknown_Convexity;
    fFirstDirection = SkPathPriv::kUnknown_FirstDirection;

    fFillType = fillType;
    fIsVolatile = 0;
    SkPathRef* pathRef = SkPathRef::CreateFromBuffer(&buffer);
    if (!pathRef) {
        return 0;
    }

    fPathRef.reset(pathRef);
    SkDEBUGCODE(this->validate();)
    buffer.skipToAlign4();
    return buffer.pos();
}

<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2012, Adrian M. Partl <apartl@aip.de>,
 *                      eScience team AIP Potsdam
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  See the NOTICE file distributed with this work for additional
 *  information regarding copyright ownership. You may obtain a copy
 *  of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

#include "custGetLine.h"
#include "asciiingest_error.h"
#include <iostream>
#include <string>
#include <assert.h>
#include <string.h>
#include <boost/format.hpp>

using namespace std;

int mdelimGetline(ifstream& inStream, string& outString, string& delim) {
    assert(delim.size() > 0);

    const char * delStr = delim.c_str();

    unsigned long lenDelim = delim.size()-1;

    int found = 0;

    if(AING_SECURE_GETLINE == 1) {
        if(delim.compare("/n") == 0) {
            AsciiIngest_error("mdelimGetline: You have defined '/n' as a delimiter. \nTo save you from freezing your machine due to this possible mistake, I will not continue. \nPlease assess if you really wanted to use '/n'. \nIf yes, recompile me by defining AING_SECURE_GETLINE = 0!\nSorry, but I have to be strict here...\n");
        } else if(delim.compare("/r") == 0) {
            AsciiIngest_error("mdelimGetline: You have defined '/r' as a delimiter. \nTo save you from freezing your machine due to this possible mistake, I will not continue. \nPlease assess if you really wanted to use '/r'. \nIf yes, recompile me by defining AING_SECURE_GETLINE = 0!\nSorry, but I have to be strict here...\n");
        } else if(delim.compare("/t") == 0) {
            AsciiIngest_error("mdelimGetline: You have defined '/t' as a delimiter. \nTo save you from freezing your machine due to this possible mistake, I will not continue. \nPlease assess if you really wanted to use '/t'. \nIf yes, recompile me by defining AING_SECURE_GETLINE = 0!\nSorry, but I have to be strict here...\n");
        } else if(delim.compare("/r/n") == 0) {
            AsciiIngest_error("mdelimGetline: You have defined '/r/n' as a delimiter. \nTo save you from freezing your machine due to this possible mistake, I will not continue. \nPlease assess if you really wanted to use '/r/n'. \nIf yes, recompile me by defining AING_SECURE_GETLINE = 0!\nSorry, but I have to be strict here...\n");
        }
    }

    outString = "";

    string buffer;
    char delimBuff[100];
    memset(delimBuff, '\0', sizeof(delimBuff));

    while(found == 0) {
        if(!getline(inStream, buffer, delim[0])) {
            return 0;
        }

        outString.append(buffer);

        inStream.read(delimBuff, lenDelim);
        if(!strcmp(delimBuff, &(delStr[1])) || inStream.eof() || lenDelim == 0) {
            found = 1;
            break;
        }

        outString.append( boost::str(boost::format("%c%s") % delim[0] % delimBuff) );
    }

    return 1;
}

unsigned long mdelimGetfield(char * charArray, string& outString, const char * delim, uint32_t lenDelim) {
    int found = 0;
    char * fieldEnd = charArray;

    while(found == 0) {
        fieldEnd = strchr(fieldEnd, delim[0]);

        //if this is a space, also parse for \ts
        if(delim[0] == 32) {
            char * tmp =charArray;
            tmp = strchr(tmp, 9);   //check for tabulator
            if(tmp < fieldEnd && tmp != NULL)
                fieldEnd = tmp;
        }

        if(lenDelim > 1 && !strcmp(fieldEnd, &(delim[1]))) {
            found = 1;
            break;
        } else if (lenDelim == 1) {
            found = 1;
        } else if (strlen(fieldEnd) == 0) {
            found = 1;
        }
    }

   if(fieldEnd - charArray == 0) {
        outString.assign("\0");
   } else {
        outString.assign(charArray, fieldEnd - charArray);
   }

    return outString.length();
}
<commit_msg>fixed a bug when field delimiters are not found in the data set<commit_after>/*
 *  Copyright (c) 2012, Adrian M. Partl <apartl@aip.de>,
 *                      eScience team AIP Potsdam
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  See the NOTICE file distributed with this work for additional
 *  information regarding copyright ownership. You may obtain a copy
 *  of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

#include "custGetLine.h"
#include "asciiingest_error.h"
#include <iostream>
#include <string>
#include <assert.h>
#include <string.h>
#include <boost/format.hpp>

using namespace std;

int mdelimGetline(ifstream& inStream, string& outString, string& delim) {
    assert(delim.size() > 0);

    const char * delStr = delim.c_str();

    unsigned long lenDelim = delim.size()-1;

    int found = 0;

    if(AING_SECURE_GETLINE == 1) {
        if(delim.compare("/n") == 0) {
            AsciiIngest_error("mdelimGetline: You have defined '/n' as a delimiter. \nTo save you from freezing your machine due to this possible mistake, I will not continue. \nPlease assess if you really wanted to use '/n'. \nIf yes, recompile me by defining AING_SECURE_GETLINE = 0!\nSorry, but I have to be strict here...\n");
        } else if(delim.compare("/r") == 0) {
            AsciiIngest_error("mdelimGetline: You have defined '/r' as a delimiter. \nTo save you from freezing your machine due to this possible mistake, I will not continue. \nPlease assess if you really wanted to use '/r'. \nIf yes, recompile me by defining AING_SECURE_GETLINE = 0!\nSorry, but I have to be strict here...\n");
        } else if(delim.compare("/t") == 0) {
            AsciiIngest_error("mdelimGetline: You have defined '/t' as a delimiter. \nTo save you from freezing your machine due to this possible mistake, I will not continue. \nPlease assess if you really wanted to use '/t'. \nIf yes, recompile me by defining AING_SECURE_GETLINE = 0!\nSorry, but I have to be strict here...\n");
        } else if(delim.compare("/r/n") == 0) {
            AsciiIngest_error("mdelimGetline: You have defined '/r/n' as a delimiter. \nTo save you from freezing your machine due to this possible mistake, I will not continue. \nPlease assess if you really wanted to use '/r/n'. \nIf yes, recompile me by defining AING_SECURE_GETLINE = 0!\nSorry, but I have to be strict here...\n");
        }
    }

    outString = "";

    string buffer;
    char delimBuff[100];
    memset(delimBuff, '\0', sizeof(delimBuff));

    while(found == 0) {
        if(!getline(inStream, buffer, delim[0])) {
            return 0;
        }

        outString.append(buffer);

        inStream.read(delimBuff, lenDelim);
        if(!strcmp(delimBuff, &(delStr[1])) || inStream.eof() || lenDelim == 0) {
            found = 1;
            break;
        }

        outString.append( boost::str(boost::format("%c%s") % delim[0] % delimBuff) );
    }

    return 1;
}

unsigned long mdelimGetfield(char * charArray, string& outString, const char * delim, uint32_t lenDelim) {
    int found = 0;
    char * fieldEnd = charArray;

    while(found == 0) {
        fieldEnd = strchr(fieldEnd, delim[0]);

        if(fieldEnd == NULL) {
            AsciiIngest_error("mdelimGetfield: I could not parse the data file since a given field delimiter could not be found! \nPlease check the format file for errors...\n");
        }

        //if this is a space, also parse for \ts
        if(delim[0] == 32) {
            char * tmp =charArray;
            tmp = strchr(tmp, 9);   //check for tabulator
            if(tmp < fieldEnd && tmp != NULL)
                fieldEnd = tmp;
        }

        if(lenDelim > 1 && !strcmp(fieldEnd, &(delim[1]))) {
            found = 1;
            break;
        } else if (lenDelim == 1) {
            found = 1;
        } else if (strlen(fieldEnd) == 0) {
            found = 1;
        }
    }

   if(fieldEnd - charArray == 0) {
        outString.assign("\0");
   } else {
        outString.assign(charArray, fieldEnd - charArray);
   }

    return outString.length();
}
<|endoftext|>


<commit_before>//
//	Copyright (c) 2014 David Wicks, sansumbrella.com
//	All rights reserved.
//
//	Particle Sphere sample application, GPU integration.
//
//	Author: David Wicks
//	License: BSD Simplified
//

#include "cinder/app/App.h"
#include "cinder/app/RendererGl.h"
#include "cinder/Rand.h"
#include "cinder/gl/gl.h"
#include "cinder/Utilities.h"
#include "cinder/gl/Ssbo.h"

using namespace ci;
using namespace ci::app;
using namespace std;

// Particle type holds information for rendering and simulation.
// Used to buffer initial simulation values.
// Using std140 in ssbo requires we have members on 4 byte alignment.
#pragma pack( push, 1 )
//__declspec( align( 4 ) )
struct Particle
{
	vec3	pos;
	float   pad1;
	vec3	ppos;
	float   pad2;
	vec3	home;
	float   pad3;
	vec4    color;
	float	damping;
	vec3    pad4;
};
#pragma pack( pop )

// Home many particles to create. (600k default)
const int NUM_PARTICLES = static_cast<int>( 600e3 );

/**
	Simple particle simulation with Verlet integration and mouse interaction.
	A sphere of particles is deformed by mouse interaction.
	Simulation is run using transform feedback on the GPU.
	particleUpdate.vs defines the simulation update step.
	Designed to have the same behavior as ParticleSphereCPU.

	This sample is the same as ParticleSphereGPU.  The only difference is
	that it uses a compute shader instead of transform feedback.
 */
class ParticleSphereCSApp : public App {
  public:
	void setup() override;
	void update() override;
	void draw() override;

  private:
	ivec3 getMaxComputeWorkGroupCount();
	ivec3 getMaxComputeWorkGroupSize();

	enum { WORK_GROUP_SIZE = 128, };
	typedef  SsboT<Particle> ParticleSsbo;
	typedef ParticleSsbo::Ref ParticleSsboRef;
	gl::GlslProgRef mRenderProg;
	gl::GlslProgRef mUpdateProg;

	// Buffers holding raw particle data on GPU.
	ParticleSsboRef mParticleBuffer;
	gl::VboRef mIdsVbo;
	gl::VaoRef mAttributes;

	// Mouse state suitable for passing as uniforms to update program
	bool			mMouseDown = false;
	float			mMouseForce = 0.0f;
	vec3			mMousePos = vec3( 0 );
};

void ParticleSphereCSApp::setup()
{
	// Create initial particle layout.
	vector<Particle> particles;
	particles.assign( NUM_PARTICLES, Particle() );
	const float azimuth = 256.0f * static_cast<float>( M_PI ) / particles.size();
	const float inclination = static_cast<float>( M_PI ) / particles.size();
	const float radius = 180.0f;
	vec3 center = vec3( getWindowCenter() + vec2( 0.0f, 40.0f ), 0.0f );
	for( unsigned int i = 0; i < particles.size(); ++i )
	{	// assign starting values to particles.
		float x = radius * math<float>::sin( inclination * i ) * math<float>::cos( azimuth * i );
		float y = radius * math<float>::cos( inclination * i );
		float z = radius * math<float>::sin( inclination * i ) * math<float>::sin( azimuth * i );

		auto &p = particles.at( i );
		p.pos = center + vec3( x, y, z );
		p.home = p.pos;
		p.ppos = p.home + Rand::randVec3() * 10.0f; // random initial velocity
		p.damping = Rand::randFloat( 0.965f, 0.985f );
		Color c( CM_HSV, lmap<float>( static_cast<float>(i), 0.0f, static_cast<float>( particles.size() ), 0.0f, 0.66f ), 1.0f, 1.0f );
		p.color = vec4( c.r, c.g, c.b, 1.0f );
	}

	ivec3 count = getMaxComputeWorkGroupCount();
	CI_ASSERT( count.x >= ( NUM_PARTICLES / WORK_GROUP_SIZE ) );

	// Create particle buffers on GPU and copy data into the first buffer.
	// Mark as static since we only write from the CPU once.
	mParticleBuffer = ParticleSsbo::create( particles, GL_STATIC_DRAW );
	gl::ScopedBuffer scopedParticleSsbo( mParticleBuffer );
	mParticleBuffer->bindBase( 0 );

	// Create a default color shader.
	try {
		mRenderProg = gl::GlslProg::create( gl::GlslProg::Format().vertex( loadAsset( "particleRender.vs.glsl" ) )
			.fragment( loadAsset( "particleRender.fs.glsl" ) )
			.attribLocation( "particleId", 0 ) );
	}
	catch( gl::GlslProgCompileExc e ) {
		ci::app::console() << e.what() << std::endl;
		quit();
	}

	std::vector<GLuint> ids( NUM_PARTICLES );
	GLuint currId = 0;
	std::generate( ids.begin(), ids.end(), [&currId]() -> GLuint { return currId++; } );

	mIdsVbo = gl::Vbo::create<GLuint>( GL_ARRAY_BUFFER, ids, GL_STATIC_DRAW );
    mAttributes = gl::Vao::create();
	gl::ScopedVao vao( mAttributes );
	gl::ScopedBuffer scopedIds( mIdsVbo );
	gl::enableVertexAttribArray( 0 );
	gl::vertexAttribIPointer( 0, 1, GL_UNSIGNED_INT, sizeof( GLuint ), 0 );

	try {
		//// Load our update program.
		mUpdateProg = gl::GlslProg::
			create( gl::GlslProg::Format().compute( loadAsset( "particleUpdate.cs.glsl" ) ) );
	}
	catch( gl::GlslProgCompileExc e ) {
		ci::app::console() << e.what() << std::endl;
		quit();
	}

	// Listen to mouse events so we can send data as uniforms.
	getWindow()->getSignalMouseDown().connect( [this]( MouseEvent event )
											  {
												  mMouseDown = true;
												  mMouseForce = 500.0f;
												  mMousePos = vec3( event.getX(), event.getY(), 0.0f );
											  } );
	getWindow()->getSignalMouseDrag().connect( [this]( MouseEvent event )
											  {
												  mMousePos = vec3( event.getX(), event.getY(), 0.0f );
											  } );
	getWindow()->getSignalMouseUp().connect( [this]( MouseEvent event )
											{
												mMouseForce = 0.0f;
												mMouseDown = false;
											} );
}

void ParticleSphereCSApp::update()
{
	// Update particles on the GPU
	gl::ScopedGlslProg prog( mUpdateProg );

	mUpdateProg->uniform( "uMouseForce", mMouseForce );
	mUpdateProg->uniform( "uMousePos", mMousePos );
	gl::ScopedBuffer scopedParticleSsbo( mParticleBuffer );

	glDispatchCompute( NUM_PARTICLES / WORK_GROUP_SIZE, 1, 1 );
	glMemoryBarrier( GL_SHADER_STORAGE_BARRIER_BIT );

	// Update mouse force.
	if( mMouseDown ) {
		mMouseForce = 150.0f;
	}
}

void ParticleSphereCSApp::draw()
{
	gl::clear( Color( 0, 0, 0 ) );
	gl::setMatricesWindowPersp( getWindowSize() );
	gl::enableDepthRead();
	gl::enableDepthWrite();

	gl::ScopedGlslProg render( mRenderProg );
	gl::ScopedBuffer scopedParticleSsbo( mParticleBuffer );
	gl::ScopedVao vao( mAttributes );

	gl::context()->setDefaultShaderVars();

	gl::drawArrays( GL_POINTS, 0, NUM_PARTICLES );

	gl::setMatricesWindow( app::getWindowSize() );
	gl::drawString( toString( static_cast<int>( getAverageFps() ) ) + " fps", vec2( 32.0f, 52.0f ) );
}

ivec3 ParticleSphereCSApp::getMaxComputeWorkGroupCount()
{
	ivec3 count;
	glGetIntegeri_v( GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0, &count.x );
	glGetIntegeri_v( GL_MAX_COMPUTE_WORK_GROUP_COUNT, 1, &count.y );
	glGetIntegeri_v( GL_MAX_COMPUTE_WORK_GROUP_COUNT, 2, &count.z );
	return count;
}

ivec3 ParticleSphereCSApp::getMaxComputeWorkGroupSize()
{
	ivec3 size;
	glGetIntegeri_v( GL_MAX_COMPUTE_WORK_GROUP_SIZE, 0, &size.x );
	glGetIntegeri_v( GL_MAX_COMPUTE_WORK_GROUP_SIZE, 1, &size.y );
	glGetIntegeri_v( GL_MAX_COMPUTE_WORK_GROUP_SIZE, 2, &size.z );
	return size;
}

CINDER_APP( ParticleSphereCSApp, RendererGl, []( App::Settings *settings ) {
	settings->setWindowSize( 1280, 720 );
	settings->setMultiTouchEnabled( false );
} )
<commit_msg>Fixed ParticleSphereCS for Ssbo changes.<commit_after>//
//	Copyright (c) 2014 David Wicks, sansumbrella.com
//	All rights reserved.
//
//	Particle Sphere sample application, GPU integration.
//
//	Author: David Wicks
//	License: BSD Simplified
//

#include "cinder/app/App.h"
#include "cinder/app/RendererGl.h"
#include "cinder/Rand.h"
#include "cinder/gl/gl.h"
#include "cinder/Utilities.h"
#include "cinder/gl/Ssbo.h"

using namespace ci;
using namespace ci::app;
using namespace std;

// Particle type holds information for rendering and simulation.
// Used to buffer initial simulation values.
// Using std140 in ssbo requires we have members on 4 byte alignment.
#pragma pack( push, 1 )
//__declspec( align( 4 ) )
struct Particle
{
	vec3	pos;
	float   pad1;
	vec3	ppos;
	float   pad2;
	vec3	home;
	float   pad3;
	vec4    color;
	float	damping;
	vec3    pad4;
};
#pragma pack( pop )

// Home many particles to create. (600k default)
const int NUM_PARTICLES = static_cast<int>( 600e3 );

/**
	Simple particle simulation with Verlet integration and mouse interaction.
	A sphere of particles is deformed by mouse interaction.
	Simulation is run using transform feedback on the GPU.
	particleUpdate.vs defines the simulation update step.
	Designed to have the same behavior as ParticleSphereCPU.

	This sample is the same as ParticleSphereGPU.  The only difference is
	that it uses a compute shader instead of transform feedback.
 */
class ParticleSphereCSApp : public App {
  public:
	void setup() override;
	void update() override;
	void draw() override;

  private:
	ivec3 getMaxComputeWorkGroupCount();
	ivec3 getMaxComputeWorkGroupSize();

	enum { WORK_GROUP_SIZE = 128, };
	typedef  gl::SsboT<Particle> ParticleSsbo;
	typedef ParticleSsbo::Ref ParticleSsboRef;
	gl::GlslProgRef mRenderProg;
	gl::GlslProgRef mUpdateProg;

	// Buffers holding raw particle data on GPU.
	ParticleSsboRef mParticleBuffer;
	gl::VboRef mIdsVbo;
	gl::VaoRef mAttributes;

	// Mouse state suitable for passing as uniforms to update program
	bool			mMouseDown = false;
	float			mMouseForce = 0.0f;
	vec3			mMousePos = vec3( 0 );
};

void ParticleSphereCSApp::setup()
{
	// Create initial particle layout.
	vector<Particle> particles;
	particles.assign( NUM_PARTICLES, Particle() );
	const float azimuth = 256.0f * static_cast<float>( M_PI ) / particles.size();
	const float inclination = static_cast<float>( M_PI ) / particles.size();
	const float radius = 180.0f;
	vec3 center = vec3( getWindowCenter() + vec2( 0.0f, 40.0f ), 0.0f );
	for( unsigned int i = 0; i < particles.size(); ++i )
	{	// assign starting values to particles.
		float x = radius * math<float>::sin( inclination * i ) * math<float>::cos( azimuth * i );
		float y = radius * math<float>::cos( inclination * i );
		float z = radius * math<float>::sin( inclination * i ) * math<float>::sin( azimuth * i );

		auto &p = particles.at( i );
		p.pos = center + vec3( x, y, z );
		p.home = p.pos;
		p.ppos = p.home + Rand::randVec3() * 10.0f; // random initial velocity
		p.damping = Rand::randFloat( 0.965f, 0.985f );
		Color c( CM_HSV, lmap<float>( static_cast<float>(i), 0.0f, static_cast<float>( particles.size() ), 0.0f, 0.66f ), 1.0f, 1.0f );
		p.color = vec4( c.r, c.g, c.b, 1.0f );
	}

	ivec3 count = getMaxComputeWorkGroupCount();
	CI_ASSERT( count.x >= ( NUM_PARTICLES / WORK_GROUP_SIZE ) );

	// Create particle buffers on GPU and copy data into the first buffer.
	// Mark as static since we only write from the CPU once.
	mParticleBuffer = ParticleSsbo::create( particles, GL_STATIC_DRAW );
	gl::ScopedBuffer scopedParticleSsbo( mParticleBuffer );
	mParticleBuffer->bindBase( 0 );

	// Create a default color shader.
	try {
		mRenderProg = gl::GlslProg::create( gl::GlslProg::Format().vertex( loadAsset( "particleRender.vs.glsl" ) )
			.fragment( loadAsset( "particleRender.fs.glsl" ) )
			.attribLocation( "particleId", 0 ) );
	}
	catch( gl::GlslProgCompileExc e ) {
		ci::app::console() << e.what() << std::endl;
		quit();
	}

	std::vector<GLuint> ids( NUM_PARTICLES );
	GLuint currId = 0;
	std::generate( ids.begin(), ids.end(), [&currId]() -> GLuint { return currId++; } );

	mIdsVbo = gl::Vbo::create<GLuint>( GL_ARRAY_BUFFER, ids, GL_STATIC_DRAW );
    mAttributes = gl::Vao::create();
	gl::ScopedVao vao( mAttributes );
	gl::ScopedBuffer scopedIds( mIdsVbo );
	gl::enableVertexAttribArray( 0 );
	gl::vertexAttribIPointer( 0, 1, GL_UNSIGNED_INT, sizeof( GLuint ), 0 );

	try {
		//// Load our update program.
		mUpdateProg = gl::GlslProg::
			create( gl::GlslProg::Format().compute( loadAsset( "particleUpdate.cs.glsl" ) ) );
	}
	catch( gl::GlslProgCompileExc e ) {
		ci::app::console() << e.what() << std::endl;
		quit();
	}

	// Listen to mouse events so we can send data as uniforms.
	getWindow()->getSignalMouseDown().connect( [this]( MouseEvent event )
											  {
												  mMouseDown = true;
												  mMouseForce = 500.0f;
												  mMousePos = vec3( event.getX(), event.getY(), 0.0f );
											  } );
	getWindow()->getSignalMouseDrag().connect( [this]( MouseEvent event )
											  {
												  mMousePos = vec3( event.getX(), event.getY(), 0.0f );
											  } );
	getWindow()->getSignalMouseUp().connect( [this]( MouseEvent event )
											{
												mMouseForce = 0.0f;
												mMouseDown = false;
											} );
}

void ParticleSphereCSApp::update()
{
	// Update particles on the GPU
	gl::ScopedGlslProg prog( mUpdateProg );

	mUpdateProg->uniform( "uMouseForce", mMouseForce );
	mUpdateProg->uniform( "uMousePos", mMousePos );
	gl::ScopedBuffer scopedParticleSsbo( mParticleBuffer );

	glDispatchCompute( NUM_PARTICLES / WORK_GROUP_SIZE, 1, 1 );
	glMemoryBarrier( GL_SHADER_STORAGE_BARRIER_BIT );

	// Update mouse force.
	if( mMouseDown ) {
		mMouseForce = 150.0f;
	}
}

void ParticleSphereCSApp::draw()
{
	gl::clear( Color( 0, 0, 0 ) );
	gl::setMatricesWindowPersp( getWindowSize() );
	gl::enableDepthRead();
	gl::enableDepthWrite();

	gl::ScopedGlslProg render( mRenderProg );
	gl::ScopedBuffer scopedParticleSsbo( mParticleBuffer );
	gl::ScopedVao vao( mAttributes );

	gl::context()->setDefaultShaderVars();

	gl::drawArrays( GL_POINTS, 0, NUM_PARTICLES );

	gl::setMatricesWindow( app::getWindowSize() );
	gl::drawString( toString( static_cast<int>( getAverageFps() ) ) + " fps", vec2( 32.0f, 52.0f ) );
}

ivec3 ParticleSphereCSApp::getMaxComputeWorkGroupCount()
{
	ivec3 count;
	glGetIntegeri_v( GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0, &count.x );
	glGetIntegeri_v( GL_MAX_COMPUTE_WORK_GROUP_COUNT, 1, &count.y );
	glGetIntegeri_v( GL_MAX_COMPUTE_WORK_GROUP_COUNT, 2, &count.z );
	return count;
}

ivec3 ParticleSphereCSApp::getMaxComputeWorkGroupSize()
{
	ivec3 size;
	glGetIntegeri_v( GL_MAX_COMPUTE_WORK_GROUP_SIZE, 0, &size.x );
	glGetIntegeri_v( GL_MAX_COMPUTE_WORK_GROUP_SIZE, 1, &size.y );
	glGetIntegeri_v( GL_MAX_COMPUTE_WORK_GROUP_SIZE, 2, &size.z );
	return size;
}

CINDER_APP( ParticleSphereCSApp, RendererGl, []( App::Settings *settings ) {
	settings->setWindowSize( 1280, 720 );
	settings->setMultiTouchEnabled( false );
} )
<|endoftext|>


<commit_before>#ifndef PROTON_INTERNAL_CONFIG_HPP
#define PROTON_INTERNAL_CONFIG_HPP

/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 */

/// @cond INTERNAL

/// @file
///
/// Configuration macros.  They can be set via -D compiler options or
/// in code.
///
/// On a C++11 compliant compiler, all C++11 features are enabled by
/// default.  Otherwise they can be enabled or disabled separately
/// with -D on the compile line.

#ifndef PN_CPP_HAS_CPP11
#if defined(__cplusplus) && __cplusplus >= 201103
#define PN_CPP_HAS_CPP11 1
#else
#define PN_CPP_HAS_CPP11 0
#endif
#endif

#ifndef PN_CPP_HAS_LONG_LONG_TYPE
#define PN_CPP_HAS_LONG_LONG_TYPE PN_CPP_HAS_CPP11
#endif

#ifndef PN_CPP_HAS_NULLPTR
#define PN_CPP_HAS_NULLPTR PN_CPP_HAS_CPP11
#endif

#ifndef PN_CPP_HAS_RVALUE_REFERENCES
#define PN_CPP_HAS_RVALUE_REFERENCES PN_CPP_HAS_CPP11
#endif

#ifndef PN_CPP_HAS_OVERRIDE
#define PN_CPP_HAS_OVERRIDE PN_CPP_HAS_CPP11
#endif

#if PN_CPP_HAS_OVERRIDE
#define PN_CPP_OVERRIDE override
#else
#define PN_CPP_OVERRIDE
#endif

#ifndef PN_CPP_HAS_EXPLICIT_CONVERSIONS
#define PN_CPP_HAS_EXPLICIT_CONVERSIONS PN_CPP_HAS_CPP11
#endif

#ifndef PN_CPP_HAS_DEFAULTED_FUNCTIONS
#define PN_CPP_HAS_DEFAULTED_FUNCTIONS PN_CPP_HAS_CPP11
#endif

#ifndef PN_CPP_HAS_DEFAULTED_MOVE_INITIALIZERS
#define PN_CPP_HAS_DEFAULTED_MOVE_INITIALIZERS PN_CPP_HAS_CPP11
#endif

#ifndef PN_CPP_HAS_DELETED_FUNCTIONS
#define PN_CPP_HAS_DELETED_FUNCTIONS PN_CPP_HAS_CPP11
#endif

#ifndef PN_CPP_HAS_THREAD_LOCAL
#define PN_CPP_HAS_THREAD_LOCAL PN_CPP_HAS_CPP11
#endif

#ifndef PN_CPP_HAS_VARIADIC_TEMPLATES
#define PN_CPP_HAS_VARIADIC_TEMPLATES PN_CPP_HAS_CPP11
#endif

#ifndef PN_CPP_HAS_LAMBDAS
#define PN_CPP_HAS_LAMBDAS PN_CPP_HAS_CPP11
#endif

// Library features

#ifndef PN_CPP_HAS_HEADER_RANDOM
#define PN_CPP_HAS_HEADER_RANDOM PN_CPP_HAS_CPP11
#endif

#ifndef PN_CPP_HAS_STD_UNIQUE_PTR
#define PN_CPP_HAS_STD_UNIQUE_PTR PN_CPP_HAS_CPP11
#endif

#ifndef PN_CPP_HAS_STD_MUTEX
#define PN_CPP_HAS_STD_MUTEX PN_CPP_HAS_CPP11
#endif

#ifndef PN_CPP_HAS_STD_ATOMIC
#define PN_CPP_HAS_STD_ATOMIC PN_CPP_HAS_CPP11
#endif

#ifndef PN_CPP_HAS_STD_THREAD
#define PN_CPP_HAS_STD_THREAD PN_CPP_HAS_CPP11
#endif

#endif // PROTON_INTERNAL_CONFIG_HPP

/// @endcond
<commit_msg>PROTON-522: Apache Qpid Proton on Mac/OSX<commit_after>#ifndef PROTON_INTERNAL_CONFIG_HPP
#define PROTON_INTERNAL_CONFIG_HPP

/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 */

/// @cond INTERNAL

/// @file
///
/// Configuration macros.  They can be set via -D compiler options or
/// in code.
///
/// On a C++11 compliant compiler, all C++11 features are enabled by
/// default.  Otherwise they can be enabled or disabled separately
/// with -D on the compile line.

/// The Apple clang compiler doesn't really support PN_CPP_HAS_THREAD_LOCAL
/// before Xcode 8 even though it claims to be C++11 compatible
#if defined(__clang__) && defined(__apple_build_version__) && ((__clang_major__ * 100) + __clang_minor__) >= 301
#if __has_feature(cxx_thread_local)
#define PN_CPP_HAS_THREAD_LOCAL 1
#else
#define PN_CPP_HAS_THREAD_LOCAL 0
#endif
#endif

#ifndef PN_CPP_HAS_CPP11
#if defined(__cplusplus) && __cplusplus >= 201103
#define PN_CPP_HAS_CPP11 1
#else
#define PN_CPP_HAS_CPP11 0
#endif
#endif

#ifndef PN_CPP_HAS_LONG_LONG_TYPE
#define PN_CPP_HAS_LONG_LONG_TYPE PN_CPP_HAS_CPP11
#endif

#ifndef PN_CPP_HAS_NULLPTR
#define PN_CPP_HAS_NULLPTR PN_CPP_HAS_CPP11
#endif

#ifndef PN_CPP_HAS_RVALUE_REFERENCES
#define PN_CPP_HAS_RVALUE_REFERENCES PN_CPP_HAS_CPP11
#endif

#ifndef PN_CPP_HAS_OVERRIDE
#define PN_CPP_HAS_OVERRIDE PN_CPP_HAS_CPP11
#endif

#if PN_CPP_HAS_OVERRIDE
#define PN_CPP_OVERRIDE override
#else
#define PN_CPP_OVERRIDE
#endif

#ifndef PN_CPP_HAS_EXPLICIT_CONVERSIONS
#define PN_CPP_HAS_EXPLICIT_CONVERSIONS PN_CPP_HAS_CPP11
#endif

#ifndef PN_CPP_HAS_DEFAULTED_FUNCTIONS
#define PN_CPP_HAS_DEFAULTED_FUNCTIONS PN_CPP_HAS_CPP11
#endif

#ifndef PN_CPP_HAS_DEFAULTED_MOVE_INITIALIZERS
#define PN_CPP_HAS_DEFAULTED_MOVE_INITIALIZERS PN_CPP_HAS_CPP11
#endif

#ifndef PN_CPP_HAS_DELETED_FUNCTIONS
#define PN_CPP_HAS_DELETED_FUNCTIONS PN_CPP_HAS_CPP11
#endif

#ifndef PN_CPP_HAS_THREAD_LOCAL
#define PN_CPP_HAS_THREAD_LOCAL PN_CPP_HAS_CPP11
#endif

#ifndef PN_CPP_HAS_VARIADIC_TEMPLATES
#define PN_CPP_HAS_VARIADIC_TEMPLATES PN_CPP_HAS_CPP11
#endif

#ifndef PN_CPP_HAS_LAMBDAS
#define PN_CPP_HAS_LAMBDAS PN_CPP_HAS_CPP11
#endif

// Library features

#ifndef PN_CPP_HAS_HEADER_RANDOM
#define PN_CPP_HAS_HEADER_RANDOM PN_CPP_HAS_CPP11
#endif

#ifndef PN_CPP_HAS_STD_UNIQUE_PTR
#define PN_CPP_HAS_STD_UNIQUE_PTR PN_CPP_HAS_CPP11
#endif

#ifndef PN_CPP_HAS_STD_MUTEX
#define PN_CPP_HAS_STD_MUTEX PN_CPP_HAS_CPP11
#endif

#ifndef PN_CPP_HAS_STD_ATOMIC
#define PN_CPP_HAS_STD_ATOMIC PN_CPP_HAS_CPP11
#endif

#ifndef PN_CPP_HAS_STD_THREAD
#define PN_CPP_HAS_STD_THREAD PN_CPP_HAS_CPP11
#endif

#endif // PROTON_INTERNAL_CONFIG_HPP

/// @endcond
<|endoftext|>


<commit_before>/*************************************************************************/
/*  openxr_interaction_profile_editor.cpp                                */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
/*                                                                       */
/* 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 "openxr_interaction_profile_editor.h"
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
#include "scene/gui/label.h"
#include "scene/gui/line_edit.h"
#include "scene/gui/panel_container.h"
#include "scene/gui/separator.h"
#include "scene/gui/text_edit.h"

///////////////////////////////////////////////////////////////////////////
// Interaction profile editor base

void OpenXRInteractionProfileEditorBase::_bind_methods() {
	ClassDB::bind_method(D_METHOD("_add_binding", "action", "path"), &OpenXRInteractionProfileEditorBase::_add_binding);
	ClassDB::bind_method(D_METHOD("_remove_binding", "action", "path"), &OpenXRInteractionProfileEditorBase::_remove_binding);
	ClassDB::bind_method(D_METHOD("_update_interaction_profile"), &OpenXRInteractionProfileEditorBase::_update_interaction_profile);
}

void OpenXRInteractionProfileEditorBase::_notification(int p_what) {
	switch (p_what) {
		case NOTIFICATION_ENTER_TREE: {
			_update_interaction_profile();
		} break;

		case NOTIFICATION_THEME_CHANGED: {
			_theme_changed();
		} break;
	}
}

void OpenXRInteractionProfileEditorBase::_add_binding(const String p_action, const String p_path) {
	ERR_FAIL_COND(action_map.is_null());
	ERR_FAIL_COND(interaction_profile.is_null());

	Ref<OpenXRAction> action = action_map->get_action(p_action);
	ERR_FAIL_COND(action.is_null());

	Ref<OpenXRIPBinding> binding = interaction_profile->get_binding_for_action(action);
	if (binding.is_null()) {
		// create a new binding
		binding.instantiate();
		binding->set_action(action);
		interaction_profile->add_binding(binding);
	}

	binding->add_path(p_path);

	// Update our toplevel paths
	action->set_toplevel_paths(action_map->get_top_level_paths(action));

	call_deferred("_update_interaction_profile");
}

void OpenXRInteractionProfileEditorBase::_remove_binding(const String p_action, const String p_path) {
	ERR_FAIL_COND(action_map.is_null());
	ERR_FAIL_COND(interaction_profile.is_null());

	Ref<OpenXRAction> action = action_map->get_action(p_action);
	ERR_FAIL_COND(action.is_null());

	Ref<OpenXRIPBinding> binding = interaction_profile->get_binding_for_action(action);
	if (binding.is_valid()) {
		binding->remove_path(p_path);

		if (binding->get_path_count() == 0) {
			interaction_profile->remove_binding(binding);
		}

		// Update our toplevel paths
		action->set_toplevel_paths(action_map->get_top_level_paths(action));

		call_deferred("_update_interaction_profile");
	}
}

OpenXRInteractionProfileEditorBase::OpenXRInteractionProfileEditorBase(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRInteractionProfile> p_interaction_profile) {
	action_map = p_action_map;
	interaction_profile = p_interaction_profile;
	String profile_path = interaction_profile->get_interaction_profile_path();
	String profile_name = profile_path;

	profile_def = OpenXRDefs::get_profile(profile_path);
	if (profile_def != nullptr) {
		profile_name = profile_def->display_name;
	}

	set_name(profile_name);
	set_h_size_flags(SIZE_EXPAND_FILL);
	set_v_size_flags(SIZE_EXPAND_FILL);
}

///////////////////////////////////////////////////////////////////////////
// Default interaction profile editor

void OpenXRInteractionProfileEditor::select_action_for(const String p_io_path) {
	selecting_for_io_path = p_io_path;
	select_action_dialog->open();
}

void OpenXRInteractionProfileEditor::action_selected(const String p_action) {
	_add_binding(p_action, selecting_for_io_path);
	selecting_for_io_path = "";
}

void OpenXRInteractionProfileEditor::_add_io_path(VBoxContainer *p_container, const OpenXRDefs::IOPath *p_io_path) {
	HBoxContainer *path_hb = memnew(HBoxContainer);
	path_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
	p_container->add_child(path_hb);

	Label *path_label = memnew(Label);
	path_label->set_text(p_io_path->display_name);
	path_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
	path_hb->add_child(path_label);

	Label *type_label = memnew(Label);
	switch (p_io_path->action_type) {
		case OpenXRAction::OPENXR_ACTION_BOOL: {
			type_label->set_text(TTR("Boolean"));
		} break;
		case OpenXRAction::OPENXR_ACTION_FLOAT: {
			type_label->set_text(TTR("Float"));
		} break;
		case OpenXRAction::OPENXR_ACTION_VECTOR2: {
			type_label->set_text(TTR("Vector2"));
		} break;
		case OpenXRAction::OPENXR_ACTION_POSE: {
			type_label->set_text(TTR("Pose"));
		} break;
		case OpenXRAction::OPENXR_ACTION_HAPTIC: {
			type_label->set_text(TTR("Haptic"));
		} break;
		default: {
			type_label->set_text(TTR("Unknown"));
		} break;
	}
	type_label->set_custom_minimum_size(Size2(50.0, 0.0));
	path_hb->add_child(type_label);

	Button *path_add = memnew(Button);
	path_add->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
	path_add->set_flat(true);
	Vector<Variant> add_binds;
	add_binds.push_back(String(p_io_path->openxr_path));
	path_add->connect("pressed", callable_mp(this, &OpenXRInteractionProfileEditor::select_action_for), add_binds);
	path_hb->add_child(path_add);

	if (interaction_profile.is_valid()) {
		String io_path = String(p_io_path->openxr_path);
		Array bindings = interaction_profile->get_bindings();
		for (int i = 0; i < bindings.size(); i++) {
			Ref<OpenXRIPBinding> binding = bindings[i];
			if (binding->has_path(io_path)) {
				Ref<OpenXRAction> action = binding->get_action();

				HBoxContainer *action_hb = memnew(HBoxContainer);
				action_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
				p_container->add_child(action_hb);

				Control *indent_node = memnew(Control);
				indent_node->set_custom_minimum_size(Size2(10.0, 0.0));
				action_hb->add_child(indent_node);

				Label *action_label = memnew(Label);
				action_label->set_text(action->get_name_with_set() + ": " + action->get_localized_name());
				action_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
				action_hb->add_child(action_label);

				Button *action_rem = memnew(Button);
				action_rem->set_flat(true);
				action_rem->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
				Vector<Variant> remove_binds;
				remove_binds.push_back(action->get_name_with_set());
				remove_binds.push_back(String(p_io_path->openxr_path));
				action_rem->connect("pressed", callable_mp((OpenXRInteractionProfileEditorBase *)this, &OpenXRInteractionProfileEditorBase::_remove_binding), remove_binds);
				action_hb->add_child(action_rem);
			}
		}
	}
}

void OpenXRInteractionProfileEditor::_update_interaction_profile() {
	// out with the old...
	while (main_hb->get_child_count() > 0) {
		memdelete(main_hb->get_child(0));
	}

	// in with the new...

	// Determine toplevel paths
	Vector<const OpenXRDefs::TopLevelPath *> top_level_paths;
	for (int i = 0; i < profile_def->io_path_count; i++) {
		const OpenXRDefs::IOPath *io_path = &profile_def->io_paths[i];

		if (!top_level_paths.has(io_path->top_level_path)) {
			top_level_paths.push_back(io_path->top_level_path);
		}
	}

	for (int i = 0; i < top_level_paths.size(); i++) {
		PanelContainer *panel = memnew(PanelContainer);
		panel->set_v_size_flags(Control::SIZE_EXPAND_FILL);
		main_hb->add_child(panel);
		panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("TabContainer")));

		VBoxContainer *container = memnew(VBoxContainer);
		panel->add_child(container);

		Label *label = memnew(Label);
		label->set_text(top_level_paths[i]->display_name);
		container->add_child(label);

		for (int j = 0; j < profile_def->io_path_count; j++) {
			const OpenXRDefs::IOPath *io_path = &profile_def->io_paths[j];
			if (io_path->top_level_path == top_level_paths[i]) {
				_add_io_path(container, io_path);
			}
		}
	}
}

void OpenXRInteractionProfileEditor::_theme_changed() {
	for (int i = 0; i < main_hb->get_child_count(); i++) {
		Control *panel = static_cast<Control *>(main_hb->get_child(i));
		if (panel) {
			panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("TabContainer")));
		}
	}
}

OpenXRInteractionProfileEditor::OpenXRInteractionProfileEditor(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRInteractionProfile> p_interaction_profile) :
		OpenXRInteractionProfileEditorBase(p_action_map, p_interaction_profile) {
	// TODO background of scrollbox should be darker with our VBoxContainers we're adding in _update_interaction_profile the normal color

	main_hb = memnew(HBoxContainer);
	add_child(main_hb);

	select_action_dialog = memnew(OpenXRSelectActionDialog(p_action_map));
	select_action_dialog->connect("action_selected", callable_mp(this, &OpenXRInteractionProfileEditor::action_selected));
	add_child(select_action_dialog);

	_update_interaction_profile();
}
<commit_msg>catch null profile_def causing crash on startup<commit_after>/*************************************************************************/
/*  openxr_interaction_profile_editor.cpp                                */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
/*                                                                       */
/* 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 "openxr_interaction_profile_editor.h"
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
#include "scene/gui/label.h"
#include "scene/gui/line_edit.h"
#include "scene/gui/panel_container.h"
#include "scene/gui/separator.h"
#include "scene/gui/text_edit.h"

///////////////////////////////////////////////////////////////////////////
// Interaction profile editor base

void OpenXRInteractionProfileEditorBase::_bind_methods() {
	ClassDB::bind_method(D_METHOD("_add_binding", "action", "path"), &OpenXRInteractionProfileEditorBase::_add_binding);
	ClassDB::bind_method(D_METHOD("_remove_binding", "action", "path"), &OpenXRInteractionProfileEditorBase::_remove_binding);
	ClassDB::bind_method(D_METHOD("_update_interaction_profile"), &OpenXRInteractionProfileEditorBase::_update_interaction_profile);
}

void OpenXRInteractionProfileEditorBase::_notification(int p_what) {
	switch (p_what) {
		case NOTIFICATION_ENTER_TREE: {
			_update_interaction_profile();
		} break;

		case NOTIFICATION_THEME_CHANGED: {
			_theme_changed();
		} break;
	}
}

void OpenXRInteractionProfileEditorBase::_add_binding(const String p_action, const String p_path) {
	ERR_FAIL_COND(action_map.is_null());
	ERR_FAIL_COND(interaction_profile.is_null());

	Ref<OpenXRAction> action = action_map->get_action(p_action);
	ERR_FAIL_COND(action.is_null());

	Ref<OpenXRIPBinding> binding = interaction_profile->get_binding_for_action(action);
	if (binding.is_null()) {
		// create a new binding
		binding.instantiate();
		binding->set_action(action);
		interaction_profile->add_binding(binding);
	}

	binding->add_path(p_path);

	// Update our toplevel paths
	action->set_toplevel_paths(action_map->get_top_level_paths(action));

	call_deferred("_update_interaction_profile");
}

void OpenXRInteractionProfileEditorBase::_remove_binding(const String p_action, const String p_path) {
	ERR_FAIL_COND(action_map.is_null());
	ERR_FAIL_COND(interaction_profile.is_null());

	Ref<OpenXRAction> action = action_map->get_action(p_action);
	ERR_FAIL_COND(action.is_null());

	Ref<OpenXRIPBinding> binding = interaction_profile->get_binding_for_action(action);
	if (binding.is_valid()) {
		binding->remove_path(p_path);

		if (binding->get_path_count() == 0) {
			interaction_profile->remove_binding(binding);
		}

		// Update our toplevel paths
		action->set_toplevel_paths(action_map->get_top_level_paths(action));

		call_deferred("_update_interaction_profile");
	}
}

OpenXRInteractionProfileEditorBase::OpenXRInteractionProfileEditorBase(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRInteractionProfile> p_interaction_profile) {
	action_map = p_action_map;
	interaction_profile = p_interaction_profile;
	String profile_path = interaction_profile->get_interaction_profile_path();
	String profile_name = profile_path;

	profile_def = OpenXRDefs::get_profile(profile_path);
	if (profile_def != nullptr) {
		profile_name = profile_def->display_name;
	}

	set_name(profile_name);
	set_h_size_flags(SIZE_EXPAND_FILL);
	set_v_size_flags(SIZE_EXPAND_FILL);
}

///////////////////////////////////////////////////////////////////////////
// Default interaction profile editor

void OpenXRInteractionProfileEditor::select_action_for(const String p_io_path) {
	selecting_for_io_path = p_io_path;
	select_action_dialog->open();
}

void OpenXRInteractionProfileEditor::action_selected(const String p_action) {
	_add_binding(p_action, selecting_for_io_path);
	selecting_for_io_path = "";
}

void OpenXRInteractionProfileEditor::_add_io_path(VBoxContainer *p_container, const OpenXRDefs::IOPath *p_io_path) {
	HBoxContainer *path_hb = memnew(HBoxContainer);
	path_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
	p_container->add_child(path_hb);

	Label *path_label = memnew(Label);
	path_label->set_text(p_io_path->display_name);
	path_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
	path_hb->add_child(path_label);

	Label *type_label = memnew(Label);
	switch (p_io_path->action_type) {
		case OpenXRAction::OPENXR_ACTION_BOOL: {
			type_label->set_text(TTR("Boolean"));
		} break;
		case OpenXRAction::OPENXR_ACTION_FLOAT: {
			type_label->set_text(TTR("Float"));
		} break;
		case OpenXRAction::OPENXR_ACTION_VECTOR2: {
			type_label->set_text(TTR("Vector2"));
		} break;
		case OpenXRAction::OPENXR_ACTION_POSE: {
			type_label->set_text(TTR("Pose"));
		} break;
		case OpenXRAction::OPENXR_ACTION_HAPTIC: {
			type_label->set_text(TTR("Haptic"));
		} break;
		default: {
			type_label->set_text(TTR("Unknown"));
		} break;
	}
	type_label->set_custom_minimum_size(Size2(50.0, 0.0));
	path_hb->add_child(type_label);

	Button *path_add = memnew(Button);
	path_add->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
	path_add->set_flat(true);
	Vector<Variant> add_binds;
	add_binds.push_back(String(p_io_path->openxr_path));
	path_add->connect("pressed", callable_mp(this, &OpenXRInteractionProfileEditor::select_action_for), add_binds);
	path_hb->add_child(path_add);

	if (interaction_profile.is_valid()) {
		String io_path = String(p_io_path->openxr_path);
		Array bindings = interaction_profile->get_bindings();
		for (int i = 0; i < bindings.size(); i++) {
			Ref<OpenXRIPBinding> binding = bindings[i];
			if (binding->has_path(io_path)) {
				Ref<OpenXRAction> action = binding->get_action();

				HBoxContainer *action_hb = memnew(HBoxContainer);
				action_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
				p_container->add_child(action_hb);

				Control *indent_node = memnew(Control);
				indent_node->set_custom_minimum_size(Size2(10.0, 0.0));
				action_hb->add_child(indent_node);

				Label *action_label = memnew(Label);
				action_label->set_text(action->get_name_with_set() + ": " + action->get_localized_name());
				action_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
				action_hb->add_child(action_label);

				Button *action_rem = memnew(Button);
				action_rem->set_flat(true);
				action_rem->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
				Vector<Variant> remove_binds;
				remove_binds.push_back(action->get_name_with_set());
				remove_binds.push_back(String(p_io_path->openxr_path));
				action_rem->connect("pressed", callable_mp((OpenXRInteractionProfileEditorBase *)this, &OpenXRInteractionProfileEditorBase::_remove_binding), remove_binds);
				action_hb->add_child(action_rem);
			}
		}
	}
}

void OpenXRInteractionProfileEditor::_update_interaction_profile() {
	ERR_FAIL_NULL(profile_def);

	// out with the old...
	while (main_hb->get_child_count() > 0) {
		memdelete(main_hb->get_child(0));
	}

	// in with the new...

	// Determine toplevel paths
	Vector<const OpenXRDefs::TopLevelPath *> top_level_paths;
	for (int i = 0; i < profile_def->io_path_count; i++) {
		const OpenXRDefs::IOPath *io_path = &profile_def->io_paths[i];

		if (!top_level_paths.has(io_path->top_level_path)) {
			top_level_paths.push_back(io_path->top_level_path);
		}
	}

	for (int i = 0; i < top_level_paths.size(); i++) {
		PanelContainer *panel = memnew(PanelContainer);
		panel->set_v_size_flags(Control::SIZE_EXPAND_FILL);
		main_hb->add_child(panel);
		panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("TabContainer")));

		VBoxContainer *container = memnew(VBoxContainer);
		panel->add_child(container);

		Label *label = memnew(Label);
		label->set_text(top_level_paths[i]->display_name);
		container->add_child(label);

		for (int j = 0; j < profile_def->io_path_count; j++) {
			const OpenXRDefs::IOPath *io_path = &profile_def->io_paths[j];
			if (io_path->top_level_path == top_level_paths[i]) {
				_add_io_path(container, io_path);
			}
		}
	}
}

void OpenXRInteractionProfileEditor::_theme_changed() {
	for (int i = 0; i < main_hb->get_child_count(); i++) {
		Control *panel = static_cast<Control *>(main_hb->get_child(i));
		if (panel) {
			panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("TabContainer")));
		}
	}
}

OpenXRInteractionProfileEditor::OpenXRInteractionProfileEditor(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRInteractionProfile> p_interaction_profile) :
		OpenXRInteractionProfileEditorBase(p_action_map, p_interaction_profile) {
	// TODO background of scrollbox should be darker with our VBoxContainers we're adding in _update_interaction_profile the normal color

	main_hb = memnew(HBoxContainer);
	add_child(main_hb);

	select_action_dialog = memnew(OpenXRSelectActionDialog(p_action_map));
	select_action_dialog->connect("action_selected", callable_mp(this, &OpenXRInteractionProfileEditor::action_selected));
	add_child(select_action_dialog);

	_update_interaction_profile();
}
<|endoftext|>


<commit_before>
#include "dispatcher.h"

namespace sdl
{

////////////////////////////////////////

dispatcher::dispatcher( void )
{
}

////////////////////////////////////////

dispatcher::~dispatcher( void )
{
}

////////////////////////////////////////

int dispatcher::execute( void )
{
	_exit_code = 0;

	bool done = false;
	while ( !done )
	{
		SDL_Event event;
		if ( SDL_WaitEvent( &event ) == 0 )
			throw std::runtime_error( SDL_GetError() );

		switch ( event.type )
		{
			case SDL_QUIT:
				done = true;
				break;
		}
	}

	return _exit_code;
}

////////////////////////////////////////

void dispatcher::exit( int code )
{
	_exit_code = code;

	SDL_Event event;
	event.type = SDL_QUIT;
	if ( SDL_PushEvent( &event) == 0 )
		throw std::runtime_error( SDL_GetError() );
}

////////////////////////////////////////

void dispatcher::add_window( const std::shared_ptr<window> &w )
{
	_windows[w->id()] = w;
}

////////////////////////////////////////

}

<commit_msg>Handle window resizing events.<commit_after>
#include "dispatcher.h"

namespace sdl
{

////////////////////////////////////////

dispatcher::dispatcher( void )
{
}

////////////////////////////////////////

dispatcher::~dispatcher( void )
{
}

////////////////////////////////////////

int dispatcher::execute( void )
{
	_exit_code = 0;

	bool done = false;
	while ( !done )
	{
		SDL_Event event;
		if ( SDL_WaitEvent( &event ) == 0 )
			throw std::runtime_error( SDL_GetError() );

		switch ( event.type )
		{
			case SDL_QUIT:
				done = true;
				break;

			case SDL_WINDOWEVENT:
				switch ( event.window.event )
				{
					case SDL_WINDOWEVENT_RESIZED:
						_windows[event.window.windowID]->resized( event.window.data1, event.window.data2 );
						break;
				}
		}
	}

	return _exit_code;
}

////////////////////////////////////////

void dispatcher::exit( int code )
{
	_exit_code = code;

	SDL_Event event;
	event.type = SDL_QUIT;
	if ( SDL_PushEvent( &event) == 0 )
		throw std::runtime_error( SDL_GetError() );
}

////////////////////////////////////////

void dispatcher::add_window( const std::shared_ptr<window> &w )
{
	_windows[w->id()] = w;
}

////////////////////////////////////////

}

<|endoftext|>