<commit_before>/***************************************************************************
 *   Copyright (c) 2011 Juergen Riegel <FreeCAD@juergen-riegel.net>        *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 of the License, or (at your option) any later version.      *
 *                                                                         *
 *   This library  is distributed in the hope that it will be useful,      *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/

#include "PreCompiled.h"

#ifndef _PreComp_
#endif

#include "ViewProvider.h"
#include "Workbench.h"
#include <Mod/PartDesign/App/Body.h>
#include <Mod/Part/App/PropertyTopoShape.h>
#include <Gui/Command.h>
#include <Gui/Control.h>
#include <Gui/Application.h>
#include <Base/Exception.h>

using namespace PartDesignGui;

PROPERTY_SOURCE(PartDesignGui::ViewProvider,PartGui::ViewProviderPart)

ViewProvider::ViewProvider()
{
    oldWb = "";
    oldTip = NULL;
}

ViewProvider::~ViewProvider()
{
}

bool ViewProvider::doubleClicked(void)
{
    if (PartDesignGui::ActivePartObject != NULL) {
        // Drop into insert mode so that the user doesn't see all the geometry that comes later in the tree
        // Also, this way the user won't be tempted to use future geometry as external references for the sketch
        oldTip = ActivePartObject->Tip.getValue();
        if (oldTip != this->pcObject)
            Gui::Command::doCommand(Gui::Command::Gui,"FreeCADGui.runCommand('PartDesign_MoveTip')");
        else
            oldTip = NULL;
    } else {
        oldTip = NULL;
    }

    try {
        std::string Msg("Edit ");
        Msg += this->pcObject->Label.getValue();
        Gui::Command::openCommand(Msg.c_str());
        Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().setEdit('%s',0)",this->pcObject->getNameInDocument());
    }
    catch (const Base::Exception&) {
        Gui::Command::abortCommand();
    }
    return true;
}

void ViewProvider::unsetEdit(int ModNum)
{
    // return to the WB we were in before editing the PartDesign feature
    Gui::Command::assureWorkbench(oldWb.c_str());

    if (ModNum == ViewProvider::Default) {
        // when pressing ESC make sure to close the dialog
        Gui::Control().closeDialog();
        if ((PartDesignGui::ActivePartObject != NULL) && (oldTip != NULL)) {
            Gui::Selection().clearSelection();
            Gui::Selection().addSelection(oldTip->getDocument()->getName(), oldTip->getNameInDocument());
            Gui::Command::doCommand(Gui::Command::Gui,"FreeCADGui.runCommand('PartDesign_MoveTip')");
        }
        oldTip = NULL;
    }
    else {
        PartGui::ViewProviderPart::unsetEdit(ModNum);
        oldTip = NULL;
    }
}

void ViewProvider::updateData(const App::Property* prop)
{
    if (prop->getTypeId() == Part::PropertyPartShape::getClassTypeId() &&
        strcmp(prop->getName(),"AddShape") == 0) {
        return;
    }
    if (prop->getTypeId() == Part::PropertyPartShape::getClassTypeId() &&
        strcmp(prop->getName(),"SubShape") == 0) {
        return;
    }
    inherited::updateData(prop);
}

bool ViewProvider::onDelete(const std::vector<std::string> &)
{
    // Body feature housekeeping
    Part::BodyBase* body = Part::BodyBase::findBodyOf(getObject());
    if (body != NULL) {
        body->removeFeature(getObject());
        // Make the new Tip and the previous solid feature visible again
        App::DocumentObject* tip = body->Tip.getValue();
        App::DocumentObject* prev = body->getPrevSolidFeature();
        if (tip != NULL) {
            Gui::Application::Instance->getViewProvider(tip)->show();
            if ((tip != prev) && (prev != NULL))
                Gui::Application::Instance->getViewProvider(prev)->show();
        }
    }

    return true;
}
<commit_msg>Fix bug in workbench<commit_after>/***************************************************************************
 *   Copyright (c) 2011 Juergen Riegel <FreeCAD@juergen-riegel.net>        *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 of the License, or (at your option) any later version.      *
 *                                                                         *
 *   This library  is distributed in the hope that it will be useful,      *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/

#include "PreCompiled.h"

#ifndef _PreComp_
#endif

#include "ViewProvider.h"
#include "Workbench.h"
#include <Mod/PartDesign/App/Body.h>
#include <Mod/Part/App/PropertyTopoShape.h>
#include <Gui/Command.h>
#include <Gui/Control.h>
#include <Gui/Application.h>
#include <Base/Exception.h>

using namespace PartDesignGui;

PROPERTY_SOURCE(PartDesignGui::ViewProvider,PartGui::ViewProviderPart)

ViewProvider::ViewProvider()
{
    oldWb = "";
    oldTip = NULL;
}

ViewProvider::~ViewProvider()
{
}

bool ViewProvider::doubleClicked(void)
{
    if (PartDesignGui::ActivePartObject != NULL) {
        // Drop into insert mode so that the user doesn't see all the geometry that comes later in the tree
        // Also, this way the user won't be tempted to use future geometry as external references for the sketch
        oldTip = ActivePartObject->Tip.getValue();
        if (oldTip != this->pcObject)
            Gui::Command::doCommand(Gui::Command::Gui,"FreeCADGui.runCommand('PartDesign_MoveTip')");
        else
            oldTip = NULL;
    } else {
        oldTip = NULL;
    }

    try {
        std::string Msg("Edit ");
        Msg += this->pcObject->Label.getValue();
        Gui::Command::openCommand(Msg.c_str());
        Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().setEdit('%s',0)",this->pcObject->getNameInDocument());
    }
    catch (const Base::Exception&) {
        Gui::Command::abortCommand();
    }
    return true;
}

void ViewProvider::unsetEdit(int ModNum)
{
    // return to the WB we were in before editing the PartDesign feature
    if (!oldWb.empty())
        Gui::Command::assureWorkbench(oldWb.c_str());

    if (ModNum == ViewProvider::Default) {
        // when pressing ESC make sure to close the dialog
        Gui::Control().closeDialog();
        if ((PartDesignGui::ActivePartObject != NULL) && (oldTip != NULL)) {
            Gui::Selection().clearSelection();
            Gui::Selection().addSelection(oldTip->getDocument()->getName(), oldTip->getNameInDocument());
            Gui::Command::doCommand(Gui::Command::Gui,"FreeCADGui.runCommand('PartDesign_MoveTip')");
        }
        oldTip = NULL;
    }
    else {
        PartGui::ViewProviderPart::unsetEdit(ModNum);
        oldTip = NULL;
    }
}

void ViewProvider::updateData(const App::Property* prop)
{
    if (prop->getTypeId() == Part::PropertyPartShape::getClassTypeId() &&
        strcmp(prop->getName(),"AddShape") == 0) {
        return;
    }
    if (prop->getTypeId() == Part::PropertyPartShape::getClassTypeId() &&
        strcmp(prop->getName(),"SubShape") == 0) {
        return;
    }
    inherited::updateData(prop);
}

bool ViewProvider::onDelete(const std::vector<std::string> &)
{
    // Body feature housekeeping
    Part::BodyBase* body = Part::BodyBase::findBodyOf(getObject());
    if (body != NULL) {
        body->removeFeature(getObject());
        // Make the new Tip and the previous solid feature visible again
        App::DocumentObject* tip = body->Tip.getValue();
        App::DocumentObject* prev = body->getPrevSolidFeature();
        if (tip != NULL) {
            Gui::Application::Instance->getViewProvider(tip)->show();
            if ((tip != prev) && (prev != NULL))
                Gui::Application::Instance->getViewProvider(prev)->show();
        }
    }

    return true;
}
<|endoftext|>


<commit_before>/*
 *  ******************************************************************************
 *  *
 *  *
 *  * This program and the accompanying materials are made available under the
 *  * terms of the Apache License, Version 2.0 which is available at
 *  * https://www.apache.org/licenses/LICENSE-2.0.
 *  *
 *  * See the NOTICE file distributed with this work for additional
 *  * information regarding copyright ownership.
 *  * 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.
 *  *
 *  * SPDX-License-Identifier: Apache-2.0
 *  *****************************************************************************
 */

//
// @author raver119@gmail.com
//

#include <system/op_boilerplate.h>

#if NOT_EXCLUDED(OP_sparse_to_dense)
#include <helpers/ShapeUtils.h>
#include <helpers/StringUtils.h>
#include <ops/declarable/helpers/sparse_to_dense.h>

namespace sd {
namespace ops {
namespace helpers {
template <typename X, typename I>
static void fill_(const void *vvalues, const void *vindices, void *voutput, const sd::LongType *zShapeInfo,
                  uint8_t rank, uint64_t length) {
  auto values = reinterpret_cast<const X *>(vvalues);
  auto indices = reinterpret_cast<const I *>(vindices);
  auto output = reinterpret_cast<X *>(voutput);

  int coords[SD_MAX_RANK];
  uint64_t pos = 0;
  for (uint64_t e = 0L; e < length; e++) {
    // indices come in blocks
    for (uint8_t p = 0; p < rank; p++) {
      coords[p] = indices[pos++];
    }

    // fill output at given coords with sparse value
    output[shape::getOffset(zShapeInfo, coords)] = values[e];
  }
}

void compat_sparse_to_dense(const NDArray &values, const NDArray &indices, NDArray *def, NDArray &output) {
  // make sure host buffer is updated
  values.syncToHost();
  indices.syncToHost();
  output.syncToHost();

  auto rank = output.rankOf();

  if (output.isS()) {
    // string case is not so trivial, since elements might, and probably will, have different sizes
    auto numValues = values.lengthOf();
    auto numElements = output.lengthOf();

    // first of all we calculate final buffer sizes and offsets
    auto defaultLength = def == nullptr ? 0 : StringUtils::byteLength(*def);
    auto valuesLength = StringUtils::byteLength(values);
    auto bufferLength = defaultLength * (output.lengthOf() - numValues) + valuesLength;
    auto headerLength = ShapeUtils::stringBufferHeaderRequirements(numElements);

    // now we make sure our output buffer can hold results
    output.dataBuffer()->expand(bufferLength + headerLength);

    std::vector<sd::LongType> outputCoords(rank);
    std::vector<sd::LongType> valueCoords(rank);

    auto offsetsBuffer = output.bufferAsT<sd::LongType>();
    auto dataBuffer = reinterpret_cast<uint8_t *>(offsetsBuffer + output.lengthOf());

    offsetsBuffer[0] = 0;

    // getting initial value coords
    for (int e = 0; e < rank; e++) valueCoords[e] = indices.e<sd::LongType>(e);

    // write results individually
    for (sd::LongType e = 0; e < numElements; e++) {
      auto vIndex = shape::coords2index(output.shapeInfo(), valueCoords.data());
      auto cLength = 0L;
      std::string str;
      if (vIndex == e) {
        // we're writing down sparse value here
        str = values.e<std::string>(e);
      } else {
        // we're writing down default value if it exists
        if (def != nullptr)
          str = def->e<std::string>(0);
        else
          str = "";
      }

      // TODO: make it unicode compliant
      memcpy(&dataBuffer[offsetsBuffer[e]], str.c_str(), str.length());

      // writing down offset
      offsetsBuffer[e + 1] = cLength;
    }
  } else {
    // numeric case is trivial, since all elements have equal sizes

    // write out default values, if they are present
    if (def != nullptr) {
      output.assign(def);

      // make sure output is synced back
      output.syncToHost();
    }

    // write out values
    BUILD_DOUBLE_SELECTOR(
        values.dataType(), indices.dataType(), fill_,
        (values.buffer(), indices.buffer(), output.buffer(), output.shapeInfo(), rank, values.lengthOf()),
        SD_COMMON_TYPES, SD_INDEXING_TYPES);
  }
  // copy back to device, if there's any
  output.syncToDevice();
}
}  // namespace helpers
}  // namespace ops
}  // namespace sd

#endif<commit_msg>Update sparse_to_dense.cpp<commit_after>/*
 *  ******************************************************************************
 *  *
 *  *
 *  * This program and the accompanying materials are made available under the
 *  * terms of the Apache License, Version 2.0 which is available at
 *  * https://www.apache.org/licenses/LICENSE-2.0.
 *  *
 *  * See the NOTICE file distributed with this work for additional
 *  * information regarding copyright ownership.
 *  * 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.
 *  *
 *  * SPDX-License-Identifier: Apache-2.0
 *  *****************************************************************************
 */

//
// @author raver119@gmail.com
//

#include <system/op_boilerplate.h>

#if NOT_EXCLUDED(OP_compat_sparse_to_dense)
#include <helpers/ShapeUtils.h>
#include <helpers/StringUtils.h>
#include <ops/declarable/helpers/sparse_to_dense.h>

namespace sd {
namespace ops {
namespace helpers {
template <typename X, typename I>
static void fill_(const void *vvalues, const void *vindices, void *voutput, const sd::LongType *zShapeInfo,
                  uint8_t rank, uint64_t length) {
  auto values = reinterpret_cast<const X *>(vvalues);
  auto indices = reinterpret_cast<const I *>(vindices);
  auto output = reinterpret_cast<X *>(voutput);

  int coords[SD_MAX_RANK];
  uint64_t pos = 0;
  for (uint64_t e = 0L; e < length; e++) {
    // indices come in blocks
    for (uint8_t p = 0; p < rank; p++) {
      coords[p] = indices[pos++];
    }

    // fill output at given coords with sparse value
    output[shape::getOffset(zShapeInfo, coords)] = values[e];
  }
}

void compat_sparse_to_dense(const NDArray &values, const NDArray &indices, NDArray *def, NDArray &output) {
  // make sure host buffer is updated
  values.syncToHost();
  indices.syncToHost();
  output.syncToHost();

  auto rank = output.rankOf();

  if (output.isS()) {
    // string case is not so trivial, since elements might, and probably will, have different sizes
    auto numValues = values.lengthOf();
    auto numElements = output.lengthOf();

    // first of all we calculate final buffer sizes and offsets
    auto defaultLength = def == nullptr ? 0 : StringUtils::byteLength(*def);
    auto valuesLength = StringUtils::byteLength(values);
    auto bufferLength = defaultLength * (output.lengthOf() - numValues) + valuesLength;
    auto headerLength = ShapeUtils::stringBufferHeaderRequirements(numElements);

    // now we make sure our output buffer can hold results
    output.dataBuffer()->expand(bufferLength + headerLength);

    std::vector<sd::LongType> outputCoords(rank);
    std::vector<sd::LongType> valueCoords(rank);

    auto offsetsBuffer = output.bufferAsT<sd::LongType>();
    auto dataBuffer = reinterpret_cast<uint8_t *>(offsetsBuffer + output.lengthOf());

    offsetsBuffer[0] = 0;

    // getting initial value coords
    for (int e = 0; e < rank; e++) valueCoords[e] = indices.e<sd::LongType>(e);

    // write results individually
    for (sd::LongType e = 0; e < numElements; e++) {
      auto vIndex = shape::coords2index(output.shapeInfo(), valueCoords.data());
      auto cLength = 0L;
      std::string str;
      if (vIndex == e) {
        // we're writing down sparse value here
        str = values.e<std::string>(e);
      } else {
        // we're writing down default value if it exists
        if (def != nullptr)
          str = def->e<std::string>(0);
        else
          str = "";
      }

      // TODO: make it unicode compliant
      memcpy(&dataBuffer[offsetsBuffer[e]], str.c_str(), str.length());

      // writing down offset
      offsetsBuffer[e + 1] = cLength;
    }
  } else {
    // numeric case is trivial, since all elements have equal sizes

    // write out default values, if they are present
    if (def != nullptr) {
      output.assign(def);

      // make sure output is synced back
      output.syncToHost();
    }

    // write out values
    BUILD_DOUBLE_SELECTOR(
        values.dataType(), indices.dataType(), fill_,
        (values.buffer(), indices.buffer(), output.buffer(), output.shapeInfo(), rank, values.lengthOf()),
        SD_COMMON_TYPES, SD_INDEXING_TYPES);
  }
  // copy back to device, if there's any
  output.syncToDevice();
}
}  // namespace helpers
}  // namespace ops
}  // namespace sd

#endif<|endoftext|>


<commit_before>/******************************************************************************
 * Copyright 2018 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

/**
 * @file
 **/

#include "modules/planning/common/trajectory/discretized_trajectory.h"

#include <iostream>
#include <string>

#include "gtest/gtest.h"

#include "modules/common/util/file.h"

namespace apollo {
namespace planning {

TEST(simple, DiscretizedTrajectory) {
  const std::string path_of_standard_trajectory =
      "modules/planning/testdata/trajectory_data/standard_trajectory.pb.txt";
  ADCTrajectory trajectory;
  EXPECT_TRUE(
      common::util::GetProtoFromFile(path_of_standard_trajectory, &trajectory));
  DiscretizedTrajectory discretized_trajectory(trajectory);
  EXPECT_DOUBLE_EQ(discretized_trajectory.GetTemporalLength(),
                   7.9999999999999885);
  EXPECT_DOUBLE_EQ(discretized_trajectory.GetSpatialLength(),
                   44.752319202675167);
  auto p1 = discretized_trajectory.Evaluate(4.0);
  EXPECT_DOUBLE_EQ(p1.path_point().x(), 587263.01182131236);
  EXPECT_DOUBLE_EQ(p1.path_point().y(), 4140966.5720794979);
  EXPECT_DOUBLE_EQ(p1.relative_time(), 4.0);
  EXPECT_DOUBLE_EQ(p1.v(), 5.4412586837131443);
}

}  // namespace planning
}  // namespace apollo
<commit_msg>Planning: added discretized_trajectory_test.cc<commit_after>/******************************************************************************
 * Copyright 2018 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

/**
 * @file
 **/

#include "modules/planning/common/trajectory/discretized_trajectory.h"

#include <iostream>
#include <string>

#include "gtest/gtest.h"

#include "modules/common/util/file.h"

namespace apollo {
namespace planning {

TEST(basic_test, DiscretizedTrajectory) {
  const std::string path_of_standard_trajectory =
      "modules/planning/testdata/trajectory_data/standard_trajectory.pb.txt";
  ADCTrajectory trajectory;
  EXPECT_TRUE(
      common::util::GetProtoFromFile(path_of_standard_trajectory, &trajectory));
  DiscretizedTrajectory discretized_trajectory(trajectory);
  EXPECT_DOUBLE_EQ(discretized_trajectory.GetTemporalLength(),
                   7.9999999999999885);
  EXPECT_DOUBLE_EQ(discretized_trajectory.GetSpatialLength(),
                   44.752319202675167);
  auto p1 = discretized_trajectory.Evaluate(4.0);
  EXPECT_DOUBLE_EQ(p1.path_point().x(), 587263.01182131236);
  EXPECT_DOUBLE_EQ(p1.path_point().y(), 4140966.5720794979);
  EXPECT_DOUBLE_EQ(p1.relative_time(), 4.0);
  EXPECT_DOUBLE_EQ(p1.v(), 5.4412586837131443);
}

}  // namespace planning
}  // namespace apollo
<|endoftext|>


<commit_before>#include "videosourcefactory.h"
#include "include_catch.h"

gg::Device device = gg::DeckLinkSDI4K;
gg::ColourSpace colour, other_colour;

int main(int argc, char * argv[])
{
    bool args_ok = true;
    if (argc < 2)
        args_ok = false;
    else
    {
        if (strcmp(argv[1], "BGRA") == 0)
        {
            colour = gg::BGRA;
            other_colour = gg::I420;
        }
        else if (strcmp(argv[1], "I420") == 0)
        {
            colour = gg::I420;
            other_colour = gg::BGRA;
        }
        else
            args_ok = false;
    }
    if (not args_ok)
    {
        printf("Synopsis: %s BGRA|I420\n", argv[0]);
        return EXIT_FAILURE;
    }
    return Catch::Session().run();
}

TEST_CASE( "get_device returns connection", "[VideoSourceFactory]" )
{
    gg::VideoSourceFactory & factory =  gg::VideoSourceFactory::get_instance();
    IVideoSource * source = nullptr;
    source = factory.get_device(device, colour);
    REQUIRE_FALSE( source == nullptr );
    REQUIRE( source->get_colour() == colour );

    gg::VideoFrame frame(colour, false);
    REQUIRE( frame.cols() == 0 );
    REQUIRE( frame.rows() == 0 );
    REQUIRE( source->get_frame(frame) );
    REQUIRE( frame.cols() > 0 );
    REQUIRE( frame.rows() > 0 );
}

TEST_CASE( "get_device returns singleton", "[VideoSourceFactory]" )
{
    gg::VideoSourceFactory & factory =  gg::VideoSourceFactory::get_instance();
    IVideoSource * source = factory.get_device(device, colour);
    IVideoSource * source_ = factory.get_device(device, colour);
    REQUIRE_FALSE( source == nullptr );
    REQUIRE( source == source_ );
}

TEST_CASE( "get_device does not create duplicate", "[VideoSourceFactory]" )
{
    gg::VideoSourceFactory & factory = gg::VideoSourceFactory::get_instance();
    IVideoSource * source = factory.get_device(device, colour);
    IVideoSource * source_duplicate = nullptr;
    REQUIRE_THROWS_AS(
        source_duplicate = factory.get_device(device, other_colour),
        gg::DeviceAlreadyConnected
    );
    REQUIRE( source_duplicate == nullptr );
}

TEST_CASE( "free_device garbage-collects device", "[VideoSourceFactory]" )
{
    gg::VideoSourceFactory & factory = gg::VideoSourceFactory::get_instance();
    IVideoSource * source = factory.get_device(device, colour);
    REQUIRE_FALSE( source == nullptr );
    gg::VideoFrame frame(colour, false);
    REQUIRE( frame.cols() == 0 );
    REQUIRE( frame.rows() == 0 );
    REQUIRE( source->get_frame(frame) );
    REQUIRE( frame.cols() > 0 );
    REQUIRE( frame.rows() > 0 );
    factory.free_device(device);
    source = nullptr;
    source = factory.get_device(device, other_colour);
    REQUIRE_FALSE( source == nullptr );
}
<commit_msg>Issue #5: video source factory tests for Blackmagic use UYVY instead of I420 now<commit_after>#include "videosourcefactory.h"
#include "include_catch.h"

gg::Device device = gg::DeckLinkSDI4K;
gg::ColourSpace colour, other_colour;

int main(int argc, char * argv[])
{
    bool args_ok = true;
    if (argc < 2)
        args_ok = false;
    else
    {
        if (strcmp(argv[1], "BGRA") == 0)
        {
            colour = gg::BGRA;
            other_colour = gg::UYVY;
        }
        else if (strcmp(argv[1], "UYVY") == 0)
        {
            colour = gg::UYVY;
            other_colour = gg::BGRA;
        }
        else
            args_ok = false;
    }
    if (not args_ok)
    {
        printf("Synopsis: %s BGRA|UYVY\n", argv[0]);
        return EXIT_FAILURE;
    }
    return Catch::Session().run();
}

TEST_CASE( "get_device returns connection", "[VideoSourceFactory]" )
{
    gg::VideoSourceFactory & factory =  gg::VideoSourceFactory::get_instance();
    IVideoSource * source = nullptr;
    source = factory.get_device(device, colour);
    REQUIRE_FALSE( source == nullptr );
    REQUIRE( source->get_colour() == colour );

    gg::VideoFrame frame(colour, false);
    REQUIRE( frame.cols() == 0 );
    REQUIRE( frame.rows() == 0 );
    REQUIRE( source->get_frame(frame) );
    REQUIRE( frame.cols() > 0 );
    REQUIRE( frame.rows() > 0 );
}

TEST_CASE( "get_device returns singleton", "[VideoSourceFactory]" )
{
    gg::VideoSourceFactory & factory =  gg::VideoSourceFactory::get_instance();
    IVideoSource * source = factory.get_device(device, colour);
    IVideoSource * source_ = factory.get_device(device, colour);
    REQUIRE_FALSE( source == nullptr );
    REQUIRE( source == source_ );
}

TEST_CASE( "get_device does not create duplicate", "[VideoSourceFactory]" )
{
    gg::VideoSourceFactory & factory = gg::VideoSourceFactory::get_instance();
    IVideoSource * source = factory.get_device(device, colour);
    IVideoSource * source_duplicate = nullptr;
    REQUIRE_THROWS_AS(
        source_duplicate = factory.get_device(device, other_colour),
        gg::DeviceAlreadyConnected
    );
    REQUIRE( source_duplicate == nullptr );
}

TEST_CASE( "free_device garbage-collects device", "[VideoSourceFactory]" )
{
    gg::VideoSourceFactory & factory = gg::VideoSourceFactory::get_instance();
    IVideoSource * source = factory.get_device(device, colour);
    REQUIRE_FALSE( source == nullptr );
    gg::VideoFrame frame(colour, false);
    REQUIRE( frame.cols() == 0 );
    REQUIRE( frame.rows() == 0 );
    REQUIRE( source->get_frame(frame) );
    REQUIRE( frame.cols() > 0 );
    REQUIRE( frame.rows() > 0 );
    factory.free_device(device);
    source = nullptr;
    source = factory.get_device(device, other_colour);
    REQUIRE_FALSE( source == nullptr );
}
<|endoftext|>


<commit_before>#include "worker.h"
#include "simchcg.h"
#include "rexp.h"

#include <glibmm/timer.h>
#include <iostream>
#include <cassert>

Worker::Worker(int width, int height, double mu,int delay) :
  width_{width}, height_{height}, mu_{mu},
  pop_a_{new pop_t(width*height)},
  pop_b_{new pop_t(width*height)},
  rand{create_random_seed()},
  delay_{delay}
{

}

void Worker::stop() {
    go_ = false;
    do_next_generation();
}

const double mutation[128] = {
  2.0, 1.5, 1.2, 1.2, 1.2, 1.1, 1.1, 1.1, 1.1, 1.1, 1.1, 0.999, 0.999, 0.99, 0.99, 0.99,
  0.95, 0.95, 0.95, 0.9, 0.9, 0.9, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
  1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
  1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
  1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
  1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
  1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
  1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0
};

void Worker::do_work(SimCHCG* caller)
{
    static_assert(num_alleles < 256, "Too many colors.");
    go_ = true;
    next_generation_ = false;
    gen_ = 0;
    sleep(delay_);

    while(go_) {
        Glib::Threads::RWLock::ReaderLock lock{data_lock_};

        //boost::timer::auto_cpu_timer measure_speed(std::cerr,  "do_work: " "%ws wall, %us user + %ss system = %ts CPU (%p%)\n");
        const pop_t &a = *pop_a_.get();
        pop_t &b = *pop_b_.get();
        b = a;
        int m = static_cast<int>(rand_exp(rand,mu_));
        for(int y=0;y<height_;++y) {
            for(int x=0;x<width_;++x) {
                int pos = x+y*width_;
                if(a[pos].is_null()) {
                    continue; // cell is null
                }

                double w, weight = rand_exp(rand, a[pos].fitness);
                if(x > 0 && (w = rand_exp(rand, a[(x-1)+y*width_].fitness)) < weight ) {
                    weight = w;
                    b[pos] = a[(x-1)+y*width_];
                }
                if(y > 0 && (w = rand_exp(rand, a[x+(y-1)*width_].fitness)) < weight ) {
                    weight = w;
                    b[pos] = a[x+(y-1)*width_];
                }
                if(x < width_-1 && (w = rand_exp(rand, a[(x+1)+y*width_].fitness)) < weight ) {
                    weight = w;
                    b[pos] = a[(x+1)+y*width_];
                }
                if(y < height_-1 && (w = rand_exp(rand, a[x+(y+1)*width_].fitness)) < weight ) {
                    weight = w;
                    b[pos] = a[x+(y+1)*width_];
                }
                if(m > 0) {
                    m -= 1;
                    continue;
                }
                m = static_cast<int>(rand_exp(rand,mu_));
                uint64_t r = rand.get_uint64();
                b[pos].fitness *= mutation[r >> 57]; // use top 7 bits for phenotype
                r &= 0x00FFFFFFFFFFFFFF;
                // Get the color of the parent
                uint64_t color = b[pos].type & 0xFF;
                // Mutate color so that it does not match the parent
                color = (color + r % (num_alleles-1)) % num_alleles;
                // Store the allele color in the bottom 8 bits.
                b[pos].type = (b[pos].type & 0xFFFFFFFFFFFFFF00) | color;
            }
        }
        // Every so often rescale fitnesses to prevent underflow/overflow
        if((1+gen_) % 10000 == 0) {
            auto it = std::max_element(b.begin(),b.end());
            double m = it->fitness;
            if(m > 1e6) {
                for(auto &aa : b) {
                    uint64_t x = aa.type;
                    aa.fitness = aa.fitness/m;
                    aa.type = (aa.type & 0xFFFFFFFFFFFFFF00) | (x & 0xFF);
                }
            }
        }
        lock.release();
        swap_buffers();

        caller->notify_queue_draw();
        Glib::Threads::Mutex::Lock slock{sync_mutex_};
        while(!next_generation_) {
            sync_.wait(sync_mutex_);
        }
        next_generation_ = false;
    }
}

std::pair<pop_t,unsigned long long> Worker::get_data() {
    Glib::Threads::RWLock::ReaderLock lock{data_lock_};
    return {*pop_a_.get(),gen_};
}

void Worker::swap_buffers() {
    Glib::Threads::RWLock::WriterLock lock{data_lock_};
    gen_ += 1;
    std::swap(pop_a_,pop_b_);
    apply_toggles();
    char buf[128];
    std::sprintf(buf, "%0.2fs: Generation %llu done.\n", timer_.elapsed(),gen_);
    std::cout << buf;
    std::cout.flush();
}

void Worker::do_next_generation() {
    Glib::Threads::Mutex::Lock lock{sync_mutex_};
    next_generation_ = true;
    sync_.signal();
}

void Worker::do_clear_nulls() {
    Glib::Threads::Mutex::Lock lock{toggle_mutex_};
    clear_all_nulls_ = true;
}

void Worker::toggle_cell(int x, int y, bool on) {
    Glib::Threads::Mutex::Lock lock{toggle_mutex_};
    assert(0 <= x < width_ && 0 <= y < height_);
    toggle_map_[{x,y}] = on;
}

const std::pair<int,int> erase_area_[] = {
    {-1,0},{0,-1},{1,0},{0,1},
    {-1,-1},{1,-1},{1,1},{-1,1}
};

void Worker::apply_toggles() {
    Glib::Threads::Mutex::Lock lock{toggle_mutex_};
    pop_t &a = *pop_a_.get();

    if(clear_all_nulls_) {
        toggle_map_.clear();
        for(auto && pos : null_cells_) {
            int x = pos.first;
            int y = pos.second;
            a[x+y*width_].toggle_off();
        }
        null_cells_.clear();
        clear_all_nulls_ = false;
        return;
    }
    for(auto && cell : toggle_map_) {
    	int x = cell.first.first;
    	int y = cell.first.second;
    	assert(0 <= x && x < width_ && 0 <= y && y < height_);
    	if(cell.second) {
            null_cells_.insert(cell.first);
    		a[x+y*width_].toggle_on();
    	} else if(null_cells_.erase(cell.first) > 0) {
    		a[x+y*width_].toggle_off();
    	} else {
            for(auto && off : erase_area_) {
                if(null_cells_.erase({cell.first.first+off.first,cell.first.second+off.second}) > 0) {
                    a[(x+off.first)+(y+off.second)*width_].toggle_off();
                    break;
                }
            }
        }
    }
    toggle_map_.clear();
}
<commit_msg>minor changes<commit_after>#include "worker.h"
#include "simchcg.h"
#include "rexp.h"

#include <glibmm/timer.h>
#include <iostream>
#include <cassert>

Worker::Worker(int width, int height, double mu,int delay) :
  width_{width}, height_{height}, mu_{mu},
  pop_a_{new pop_t(width*height)},
  pop_b_{new pop_t(width*height)},
  rand{create_random_seed()},
  delay_{delay}
{

}

void Worker::stop() {
    go_ = false;
    do_next_generation();
}

const double mutation[128] = {
  2.0, 1.5, 1.2, 1.2, 1.2, 1.1, 1.1, 1.1, 1.1, 1.1, 1.1, 0.999, 0.999, 0.99, 0.99, 0.99,
  0.95, 0.95, 0.95, 0.9, 0.9, 0.9, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
  1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
  1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
  1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
  1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
  1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
  1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0
};

void Worker::do_work(SimCHCG* caller)
{
    static_assert(num_alleles < 256, "Too many colors.");
    go_ = true;
    next_generation_ = false;
    gen_ = 0;
    sleep(delay_);

    while(go_) {
        Glib::Threads::RWLock::ReaderLock lock{data_lock_};

        //boost::timer::auto_cpu_timer measure_speed(std::cerr,  "do_work: " "%ws wall, %us user + %ss system = %ts CPU (%p%)\n");
        const pop_t &a = *pop_a_.get();
        pop_t &b = *pop_b_.get();
        b = a;
        int m = static_cast<int>(rand_exp(rand,mu_));
        for(int y=0;y<height_;++y) {
            for(int x=0;x<width_;++x) {
                int pos = x+y*width_;
                if(a[pos].is_null()) {
                    continue; // cell is null
                }

                double w, weight = rand_exp(rand, a[pos].fitness);
                if(x > 0 && (w = rand_exp(rand, a[(x-1)+y*width_].fitness)) < weight ) {
                    weight = w;
                    b[pos] = a[(x-1)+y*width_];
                }
                if(y > 0 && (w = rand_exp(rand, a[x+(y-1)*width_].fitness)) < weight ) {
                    weight = w;
                    b[pos] = a[x+(y-1)*width_];
                }
                if(x < width_-1 && (w = rand_exp(rand, a[(x+1)+y*width_].fitness)) < weight ) {
                    weight = w;
                    b[pos] = a[(x+1)+y*width_];
                }
                if(y < height_-1 && (w = rand_exp(rand, a[x+(y+1)*width_].fitness)) < weight ) {
                    weight = w;
                    b[pos] = a[x+(y+1)*width_];
                }
                if(m > 0) {
                    m -= 1;
                    continue;
                }
                m = static_cast<int>(rand_exp(rand,mu_));
                static_assert(sizeof(mutation)/sizeof(double) == 128);
                uint64_t r = rand.get_uint64();
                b[pos].fitness *= mutation[r >> 57]; // use top 7 bits for phenotype
                r &= 0x01FFFFFFFFFFFFFF;
                // Get the color of the parent
                uint64_t color = b[pos].type & 0xFF;
                // Mutate color so that it does not match the parent
                color = (color + r % (num_alleles-1)) % num_alleles;
                // Store the allele color in the bottom 8 bits.
                b[pos].type = (b[pos].type & 0xFFFFFFFFFFFFFF00) | color;
            }
        }
        // Every so often rescale fitnesses to prevent underflow/overflow
        if((1+gen_) % 10000 == 0) {
            auto it = std::max_element(b.begin(),b.end());
            double m = it->fitness;
            if(m > 1e6) {
                for(auto &aa : b) {
                    uint64_t color = aa.type & 0xFF;
                    aa.fitness = aa.fitness/m;
                    aa.type = (aa.type & 0xFFFFFFFFFFFFFF00) | color;
                }
            }
        }
        lock.release();
        swap_buffers();

        caller->notify_queue_draw();
        Glib::Threads::Mutex::Lock slock{sync_mutex_};
        while(!next_generation_) {
            sync_.wait(sync_mutex_);
        }
        next_generation_ = false;
    }
}

std::pair<pop_t,unsigned long long> Worker::get_data() {
    Glib::Threads::RWLock::ReaderLock lock{data_lock_};
    return {*pop_a_.get(),gen_};
}

void Worker::swap_buffers() {
    Glib::Threads::RWLock::WriterLock lock{data_lock_};
    gen_ += 1;
    std::swap(pop_a_,pop_b_);
    apply_toggles();
    char buf[128];
    std::sprintf(buf, "%0.2fs: Generation %llu done.\n", timer_.elapsed(),gen_);
    std::cout << buf;
    std::cout.flush();
}

void Worker::do_next_generation() {
    Glib::Threads::Mutex::Lock lock{sync_mutex_};
    next_generation_ = true;
    sync_.signal();
}

void Worker::do_clear_nulls() {
    Glib::Threads::Mutex::Lock lock{toggle_mutex_};
    clear_all_nulls_ = true;
}

void Worker::toggle_cell(int x, int y, bool on) {
    Glib::Threads::Mutex::Lock lock{toggle_mutex_};
    assert(0 <= x < width_ && 0 <= y < height_);
    toggle_map_[{x,y}] = on;
}

const std::pair<int,int> erase_area_[] = {
    {-1,0},{0,-1},{1,0},{0,1},
    {-1,-1},{1,-1},{1,1},{-1,1}
};

void Worker::apply_toggles() {
    Glib::Threads::Mutex::Lock lock{toggle_mutex_};
    pop_t &a = *pop_a_.get();

    if(clear_all_nulls_) {
        toggle_map_.clear();
        for(auto && pos : null_cells_) {
            int x = pos.first;
            int y = pos.second;
            a[x+y*width_].toggle_off();
        }
        null_cells_.clear();
        clear_all_nulls_ = false;
        return;
    }
    for(auto && cell : toggle_map_) {
    	int x = cell.first.first;
    	int y = cell.first.second;
    	assert(0 <= x && x < width_ && 0 <= y && y < height_);
    	if(cell.second) {
            null_cells_.insert(cell.first);
    		a[x+y*width_].toggle_on();
    	} else if(null_cells_.erase(cell.first) > 0) {
    		a[x+y*width_].toggle_off();
    	} else {
            for(auto && off : erase_area_) {
                if(null_cells_.erase({cell.first.first+off.first,cell.first.second+off.second}) > 0) {
                    a[(x+off.first)+(y+off.second)*width_].toggle_off();
                    break;
                }
            }
        }
    }
    toggle_map_.clear();
}
<|endoftext|>


<commit_before>/* BEGIN_COMMON_COPYRIGHT_HEADER
 * (c)LGPL2+
 *
 * LXQt - a lightweight, Qt based, desktop toolset
 * https://lxqt.org
 *
 * Copyright: 2012 Razor team
 * Authors:
 *   Johannes Zellner <webmaster@nebulon.de>
 *
 * This program or library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA
 *
 * END_COMMON_COPYRIGHT_HEADER */

#include "alsaengine.h"

#include "alsadevice.h"

#include <QMetaType>
#include <QSocketNotifier>
#include <QtDebug>

AlsaEngine *AlsaEngine::m_instance = nullptr;

static int alsa_elem_event_callback(snd_mixer_elem_t *elem, unsigned int /*mask*/)
{
    AlsaEngine *engine = AlsaEngine::instance();
    if (engine)
        engine->updateDevice(engine->getDeviceByAlsaElem(elem));

    return 0;
}

static int alsa_mixer_event_callback(snd_mixer_t * /*mixer*/, unsigned int /*mask*/, snd_mixer_elem_t * /*elem*/)
{
    return 0;
}

AlsaEngine::AlsaEngine(QObject *parent) :
    AudioEngine(parent)
{
    discoverDevices();
    m_instance = this;
}

AlsaEngine *AlsaEngine::instance()
{
    return m_instance;
}

int AlsaEngine::volumeMax(AudioDevice *device) const
{
    AlsaDevice * alsa_dev = qobject_cast<AlsaDevice *>(device);
    Q_ASSERT(alsa_dev);
    return alsa_dev->volumeMax();
}

AlsaDevice *AlsaEngine::getDeviceByAlsaElem(snd_mixer_elem_t *elem) const
{
    for (AudioDevice *device : qAsConst(m_sinks)) {
        AlsaDevice *dev = qobject_cast<AlsaDevice*>(device);
        if (!dev || !dev->element())
            continue;

        if (dev->element() == elem)
            return dev;
    }

    return nullptr;
}

void AlsaEngine::commitDeviceVolume(AudioDevice *device)
{
    AlsaDevice *dev = qobject_cast<AlsaDevice*>(device);
    if (!dev || !dev->element())
        return;

    long value = dev->volumeMin() + qRound(static_cast<double>(dev->volume()) / 100.0 * (dev->volumeMax() - dev->volumeMin()));
    snd_mixer_selem_set_playback_volume_all(dev->element(), value);
}

void AlsaEngine::setMute(AudioDevice *device, bool state)
{
    AlsaDevice *dev = qobject_cast<AlsaDevice*>(device);
    if (!dev || !dev->element())
        return;

    if (snd_mixer_selem_has_playback_switch(dev->element()))
        snd_mixer_selem_set_playback_switch_all(dev->element(), (int)!state);
    else if (state)
        dev->setVolume(0);
}

void AlsaEngine::updateDevice(AlsaDevice *device)
{
    if (!device)
        return;

    long value;
    snd_mixer_selem_get_playback_volume(device->element(), (snd_mixer_selem_channel_id_t)0, &value);
    // qDebug() << "updateDevice:" << device->name() << value;
    device->setVolumeNoCommit(qRound((static_cast<double>(value - device->volumeMin()) * 100.0) / (device->volumeMax() - device->volumeMin())));

    if (snd_mixer_selem_has_playback_switch(device->element())) {
        int mute;
        snd_mixer_selem_get_playback_switch(device->element(), (snd_mixer_selem_channel_id_t)0, &mute);
        device->setMuteNoCommit(!(bool)mute);
    }
}

void AlsaEngine::driveAlsaEventHandling(int fd)
{
    snd_mixer_handle_events(m_mixerMap.value(fd));
}

void AlsaEngine::discoverDevices()
{
    int error;
    int cardNum = -1;
    const int BUFF_SIZE = 64;

    while (1) {
        if ((error = snd_card_next(&cardNum)) < 0) {
            qWarning("Can't get the next card number: %s\n", snd_strerror(error));
            break;
        }

        if (cardNum < 0)
            break;

        char str[BUFF_SIZE];
        const size_t n = snprintf(str, sizeof(str), "hw:%i", cardNum);
        if (BUFF_SIZE <= n) {
            qWarning("AlsaEngine::discoverDevices: Buffer too small\n");
            continue;
        }

        snd_ctl_t *cardHandle;
        if ((error = snd_ctl_open(&cardHandle, str, 0)) < 0) {
            qWarning("Can't open card %i: %s\n", cardNum, snd_strerror(error));
            continue;
        }

        snd_ctl_card_info_t *cardInfo;
        snd_ctl_card_info_alloca(&cardInfo);

        QString cardName = QString::fromLatin1(snd_ctl_card_info_get_name(cardInfo));
        if (cardName.isEmpty())
            cardName = QString::fromLatin1(str);

        if ((error = snd_ctl_card_info(cardHandle, cardInfo)) < 0) {
            qWarning("Can't get info for card %i: %s\n", cardNum, snd_strerror(error));
        } else {
            // setup mixer and iterate over channels
            snd_mixer_t *mixer = nullptr;
            snd_mixer_open(&mixer, 0);
            snd_mixer_attach(mixer, str);
            snd_mixer_selem_register(mixer, nullptr, nullptr);
            snd_mixer_load(mixer);

            // setup event handler for mixer
            snd_mixer_set_callback(mixer, alsa_mixer_event_callback);

            // setup eventloop handling
            struct pollfd pfd;
            if (snd_mixer_poll_descriptors(mixer, &pfd, 1)) {
                QSocketNotifier *notifier = new QSocketNotifier(pfd.fd, QSocketNotifier::Read, this);
                connect(notifier, SIGNAL(activated(int)), this, SLOT(driveAlsaEventHandling(int)));
                m_mixerMap.insert(pfd.fd, mixer);
            }

            snd_mixer_elem_t *mixerElem = nullptr;
            mixerElem = snd_mixer_first_elem(mixer);

            while (mixerElem) {
                // check if we have a Sink or Source
                if (snd_mixer_selem_has_playback_volume(mixerElem)) {
                    AlsaDevice *dev = new AlsaDevice(Sink, this, this);
                    dev->setName(QString::fromLatin1(snd_mixer_selem_get_name(mixerElem)));
                    dev->setIndex(cardNum);
                    dev->setDescription(cardName + QStringLiteral(" - ") + dev->name());

                    // set alsa specific members
                    dev->setCardName(QString::fromLatin1(str));
                    dev->setMixer(mixer);
                    dev->setElement(mixerElem);

                    // get & store the range
                    long min, max;
                    snd_mixer_selem_get_playback_volume_range(mixerElem, &min, &max);
                    dev->setVolumeMinMax(min, max);

                    updateDevice(dev);

                    // register event callback
                    snd_mixer_elem_set_callback(mixerElem, alsa_elem_event_callback);

                    m_sinks.append(dev);
                }

                mixerElem = snd_mixer_elem_next(mixerElem);
            }
        }

        snd_ctl_close(cardHandle);
    }

    snd_config_update_free_global();
}
<commit_msg>Use bool literals<commit_after>/* BEGIN_COMMON_COPYRIGHT_HEADER
 * (c)LGPL2+
 *
 * LXQt - a lightweight, Qt based, desktop toolset
 * https://lxqt.org
 *
 * Copyright: 2012 Razor team
 * Authors:
 *   Johannes Zellner <webmaster@nebulon.de>
 *
 * This program or library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA
 *
 * END_COMMON_COPYRIGHT_HEADER */

#include "alsaengine.h"

#include "alsadevice.h"

#include <QMetaType>
#include <QSocketNotifier>
#include <QtDebug>

AlsaEngine *AlsaEngine::m_instance = nullptr;

static int alsa_elem_event_callback(snd_mixer_elem_t *elem, unsigned int /*mask*/)
{
    AlsaEngine *engine = AlsaEngine::instance();
    if (engine)
        engine->updateDevice(engine->getDeviceByAlsaElem(elem));

    return 0;
}

static int alsa_mixer_event_callback(snd_mixer_t * /*mixer*/, unsigned int /*mask*/, snd_mixer_elem_t * /*elem*/)
{
    return 0;
}

AlsaEngine::AlsaEngine(QObject *parent) :
    AudioEngine(parent)
{
    discoverDevices();
    m_instance = this;
}

AlsaEngine *AlsaEngine::instance()
{
    return m_instance;
}

int AlsaEngine::volumeMax(AudioDevice *device) const
{
    AlsaDevice * alsa_dev = qobject_cast<AlsaDevice *>(device);
    Q_ASSERT(alsa_dev);
    return alsa_dev->volumeMax();
}

AlsaDevice *AlsaEngine::getDeviceByAlsaElem(snd_mixer_elem_t *elem) const
{
    for (AudioDevice *device : qAsConst(m_sinks)) {
        AlsaDevice *dev = qobject_cast<AlsaDevice*>(device);
        if (!dev || !dev->element())
            continue;

        if (dev->element() == elem)
            return dev;
    }

    return nullptr;
}

void AlsaEngine::commitDeviceVolume(AudioDevice *device)
{
    AlsaDevice *dev = qobject_cast<AlsaDevice*>(device);
    if (!dev || !dev->element())
        return;

    long value = dev->volumeMin() + qRound(static_cast<double>(dev->volume()) / 100.0 * (dev->volumeMax() - dev->volumeMin()));
    snd_mixer_selem_set_playback_volume_all(dev->element(), value);
}

void AlsaEngine::setMute(AudioDevice *device, bool state)
{
    AlsaDevice *dev = qobject_cast<AlsaDevice*>(device);
    if (!dev || !dev->element())
        return;

    if (snd_mixer_selem_has_playback_switch(dev->element()))
        snd_mixer_selem_set_playback_switch_all(dev->element(), (int)!state);
    else if (state)
        dev->setVolume(0);
}

void AlsaEngine::updateDevice(AlsaDevice *device)
{
    if (!device)
        return;

    long value;
    snd_mixer_selem_get_playback_volume(device->element(), (snd_mixer_selem_channel_id_t)0, &value);
    // qDebug() << "updateDevice:" << device->name() << value;
    device->setVolumeNoCommit(qRound((static_cast<double>(value - device->volumeMin()) * 100.0) / (device->volumeMax() - device->volumeMin())));

    if (snd_mixer_selem_has_playback_switch(device->element())) {
        int mute;
        snd_mixer_selem_get_playback_switch(device->element(), (snd_mixer_selem_channel_id_t)0, &mute);
        device->setMuteNoCommit(!(bool)mute);
    }
}

void AlsaEngine::driveAlsaEventHandling(int fd)
{
    snd_mixer_handle_events(m_mixerMap.value(fd));
}

void AlsaEngine::discoverDevices()
{
    int error;
    int cardNum = -1;
    const int BUFF_SIZE = 64;

    while (true) {
        if ((error = snd_card_next(&cardNum)) < 0) {
            qWarning("Can't get the next card number: %s\n", snd_strerror(error));
            break;
        }

        if (cardNum < 0)
            break;

        char str[BUFF_SIZE];
        const size_t n = snprintf(str, sizeof(str), "hw:%i", cardNum);
        if (BUFF_SIZE <= n) {
            qWarning("AlsaEngine::discoverDevices: Buffer too small\n");
            continue;
        }

        snd_ctl_t *cardHandle;
        if ((error = snd_ctl_open(&cardHandle, str, 0)) < 0) {
            qWarning("Can't open card %i: %s\n", cardNum, snd_strerror(error));
            continue;
        }

        snd_ctl_card_info_t *cardInfo;
        snd_ctl_card_info_alloca(&cardInfo);

        QString cardName = QString::fromLatin1(snd_ctl_card_info_get_name(cardInfo));
        if (cardName.isEmpty())
            cardName = QString::fromLatin1(str);

        if ((error = snd_ctl_card_info(cardHandle, cardInfo)) < 0) {
            qWarning("Can't get info for card %i: %s\n", cardNum, snd_strerror(error));
        } else {
            // setup mixer and iterate over channels
            snd_mixer_t *mixer = nullptr;
            snd_mixer_open(&mixer, 0);
            snd_mixer_attach(mixer, str);
            snd_mixer_selem_register(mixer, nullptr, nullptr);
            snd_mixer_load(mixer);

            // setup event handler for mixer
            snd_mixer_set_callback(mixer, alsa_mixer_event_callback);

            // setup eventloop handling
            struct pollfd pfd;
            if (snd_mixer_poll_descriptors(mixer, &pfd, 1)) {
                QSocketNotifier *notifier = new QSocketNotifier(pfd.fd, QSocketNotifier::Read, this);
                connect(notifier, SIGNAL(activated(int)), this, SLOT(driveAlsaEventHandling(int)));
                m_mixerMap.insert(pfd.fd, mixer);
            }

            snd_mixer_elem_t *mixerElem = nullptr;
            mixerElem = snd_mixer_first_elem(mixer);

            while (mixerElem) {
                // check if we have a Sink or Source
                if (snd_mixer_selem_has_playback_volume(mixerElem)) {
                    AlsaDevice *dev = new AlsaDevice(Sink, this, this);
                    dev->setName(QString::fromLatin1(snd_mixer_selem_get_name(mixerElem)));
                    dev->setIndex(cardNum);
                    dev->setDescription(cardName + QStringLiteral(" - ") + dev->name());

                    // set alsa specific members
                    dev->setCardName(QString::fromLatin1(str));
                    dev->setMixer(mixer);
                    dev->setElement(mixerElem);

                    // get & store the range
                    long min, max;
                    snd_mixer_selem_get_playback_volume_range(mixerElem, &min, &max);
                    dev->setVolumeMinMax(min, max);

                    updateDevice(dev);

                    // register event callback
                    snd_mixer_elem_set_callback(mixerElem, alsa_elem_event_callback);

                    m_sinks.append(dev);
                }

                mixerElem = snd_mixer_elem_next(mixerElem);
            }
        }

        snd_ctl_close(cardHandle);
    }

    snd_config_update_free_global();
}
<|endoftext|>


<commit_before>#include <cmath>

#include "checker.hpp"

bool Checker::checkStep(GameDesk& a, Points& points) {
    int rownumber = a.getRowNumber();
    if (checkIndex(rownumber, points)) {
        if (a.getDeskNumber(points.p1) == a.getDeskNumber(points.p2)) {
            return true;
        }
        return false;
    }
    return false;
}

bool Checker::checkIndex(int max, Points& points) {
    int p1c = points.p1.col;
    int p2c = points.p2.col;
    int p1r = points.p1.row;
    int p2r = points.p2.row;
    if (checkRange(max, points)) {
        if ((p1c == p2c) && (std::abs((p1r - p2r)) == 1)) {
            return true;
        }
        else if ((p1r == p2r) && std::abs((p1c - p2c) == 1)) {
            return true;
        }
        return false;
    }
    return false;
}

bool Checker::checkRange(int max, Points& points) {
    int p1c = points.p1.col;
    int p2c = points.p2.col;
    int p1r = points.p1.row;
    int p2r = points.p2.row;
    if ((p1r >= 0) && (p1c >= 0) && (p2r >= 0) && (p2c >= 0)) {
        if ((p1r < max) && (p1c < max) && (p2r < max) && (p2c < max)) {
            return true;
        }
        return false;
    }
    return false;
}
<commit_msg>Fix typo in checker.cpp<commit_after>#include <cmath>

#include "checker.hpp"

bool Checker::checkStep(GameDesk& a, Points& points) {
    int rownumber = a.getRowNumber();
    if (checkIndex(rownumber, points)) {
        if (a.getDeskNumber(points.p1) == a.getDeskNumber(points.p2)) {
            return true;
        }
        return false;
    }
    return false;
}

bool Checker::checkIndex(int max, Points& points) {
    int p1c = points.p1.col;
    int p2c = points.p2.col;
    int p1r = points.p1.row;
    int p2r = points.p2.row;
    if (checkRange(max, points)) {
        if ((p1c == p2c) && (std::abs((p1r - p2r)) == 1)) {
            return true;
        }
        else if ((p1r == p2r) && (std::abs(p1c - p2c) == 1)) {
            return true;
        }
        return false;
    }
    return false;
}

bool Checker::checkRange(int max, Points& points) {
    int p1c = points.p1.col;
    int p2c = points.p2.col;
    int p1r = points.p1.row;
    int p2r = points.p2.row;
    if ((p1r >= 0) && (p1c >= 0) && (p2r >= 0) && (p2c >= 0)) {
        if ((p1r < max) && (p1c < max) && (p2r < max) && (p2c < max)) {
            return true;
        }
        return false;
    }
    return false;
}
<|endoftext|>


<commit_before>// Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html
#ifndef __RAPICORN_STRINGS_HH__
#define __RAPICORN_STRINGS_HH__

#include <rcore/utilities.hh>
#include <string>

namespace Rapicorn {

// === i18n ===
const char*                     rapicorn_gettext        (const char *text);
#ifdef __RAPICORN_BUILD__
#define _(str)  rapicorn_gettext (str)
#define N_(str) (str)
#endif

// === String ===
String                          string_multiply          (const String &s,
                                                          uint64       count);
String  			string_tolower           (const String &str);
String  			string_toupper           (const String &str);
String  			string_totitle           (const String &str);
String  			string_printf            (const char *format, ...) RAPICORN_PRINTF (1, 2);
String  			string_vprintf           (const char *format, va_list vargs);
StringVector 			string_split             (const String       &string,
                                                          const String       &splitter = "");
String  			string_join              (const String       &junctor,
                                                          const StringVector &strvec);
bool    			string_to_bool           (const String &string);
String  			string_from_bool         (bool value);
uint64  			string_to_uint           (const String &string, uint base = 10);
String  			string_from_uint         (uint64 value);
bool    			string_has_int           (const String &string);
int64   			string_to_int            (const String &string, uint base = 10);
String  			string_from_int          (int64 value);
String  			string_from_float        (float value);
double  			string_to_double         (const String &string);
double  			string_to_double         (const char  *dblstring,
                                                          const char **endptr);
String                          string_from_double       (double value);
inline String                   string_from_float        (double value)         { return string_from_double (value); }
inline double                   string_to_float          (const String &string) { return string_to_double (string); }
template<typename Type> Type    string_to_type           (const String &string);
template<typename Type> String  string_from_type         (Type          value);
template<> inline double        string_to_type<double>   (const String &string) { return string_to_double (string); }
template<> inline String        string_from_type<double> (double         value) { return string_from_double (value); }
template<> inline float         string_to_type<float>    (const String &string) { return string_to_float (string); }
template<> inline String        string_from_type<float>  (float         value)  { return string_from_float (value); }
template<> inline bool          string_to_type<bool>     (const String &string) { return string_to_bool (string); }
template<> inline String        string_from_type<bool>   (bool         value)   { return string_from_bool (value); }
template<> inline int16         string_to_type<int16>    (const String &string) { return string_to_int (string); }
template<> inline String        string_from_type<int16>  (int16         value)  { return string_from_int (value); }
template<> inline uint16        string_to_type<uint16>   (const String &string) { return string_to_uint (string); }
template<> inline String        string_from_type<uint16> (uint16        value)  { return string_from_uint (value); }
template<> inline int           string_to_type<int>      (const String &string) { return string_to_int (string); }
template<> inline String        string_from_type<int>    (int         value)    { return string_from_int (value); }
template<> inline uint          string_to_type<uint>     (const String &string) { return string_to_uint (string); }
template<> inline String        string_from_type<uint>   (uint           value) { return string_from_uint (value); }
template<> inline int64         string_to_type<int64>    (const String &string) { return string_to_int (string); }
template<> inline String        string_from_type<int64>  (int64         value)  { return string_from_int (value); }
template<> inline uint64        string_to_type<uint64>   (const String &string) { return string_to_uint (string); }
template<> inline String        string_from_type<uint64> (uint64         value) { return string_from_uint (value); }
template<> inline String        string_to_type<String>   (const String &string) { return string; }
template<> inline String        string_from_type<String> (String         value) { return value; }
vector<double>                  string_to_vector         (const String         &string);
String                          string_from_vector       (const vector<double> &dvec,
                                                          const String         &delim = " ");
String  			string_from_errno        (int         errno_val);
bool                            string_is_uuid           (const String &uuid_string); /* check uuid formatting */
int                             string_cmp_uuid          (const String &uuid_string1,
                                                          const String &uuid_string2); /* -1=smaller, 0=equal, +1=greater (assuming valid uuid strings) */
String  string_from_pretty_function_name                 (const char *gnuc_pretty_function);
String  string_to_cescape                                (const String &str);
String  string_to_cquote                                 (const String &str);
String  string_from_cquote                               (const String &input);
String  string_lstrip                                    (const String &input);
String  string_rstrip                                    (const String &input);
String  string_strip                                     (const String &input);
String  string_substitute_char                           (const String &input,
                                                          const char    match,
                                                          const char    subst);
String  string_vector_find (const StringVector  &svector,
                            const String        &key,
                            const String        &fallback);
void    memset4		   (uint32              *mem,
                            uint32               filler,
                            uint                 length);

// === String Options ===
bool    string_option_check     (const String   &option_string,
                                 const String   &option);
String  string_option_get       (const String   &option_string,
                                 const String   &option);

// === Charset Conversions ===
bool    text_convert    (const String &to_charset,
                         String       &output_string,
                         const String &from_charset,
                         const String &input_string,
                         const String &fallback_charset = "ISO-8859-15",
                         const String &output_mark = "");

// === StringVector ===
#define RAPICORN_STRING_VECTOR_FROM_ARRAY(ConstCharArray)               ({ \
  Rapicorn::StringVector __a;                                           \
  const uint64_t __l = RAPICORN_ARRAY_SIZE (ConstCharArray);            \
  for (uint64_t __ai = 0; __ai < __l; __ai++)                           \
    __a.push_back (ConstCharArray[__ai]);                               \
  __a; })

} // Rapicorn

#endif /* __RAPICORN_STRINGS_HH__ */
<commit_msg>RCORE: tell gcc that rapicorn_gettext() passes a printf-style format arg<commit_after>// Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html
#ifndef __RAPICORN_STRINGS_HH__
#define __RAPICORN_STRINGS_HH__

#include <rcore/utilities.hh>
#include <string>

namespace Rapicorn {

// === i18n ===
const char*                     rapicorn_gettext        (const char *text) RAPICORN_FORMAT (1);
#ifdef __RAPICORN_BUILD__
#define _(str)  rapicorn_gettext (str)
#define N_(str) (str)
#endif

// === String ===
String                          string_multiply          (const String &s,
                                                          uint64       count);
String  			string_tolower           (const String &str);
String  			string_toupper           (const String &str);
String  			string_totitle           (const String &str);
String  			string_printf            (const char *format, ...) RAPICORN_PRINTF (1, 2);
String  			string_vprintf           (const char *format, va_list vargs);
StringVector 			string_split             (const String       &string,
                                                          const String       &splitter = "");
String  			string_join              (const String       &junctor,
                                                          const StringVector &strvec);
bool    			string_to_bool           (const String &string);
String  			string_from_bool         (bool value);
uint64  			string_to_uint           (const String &string, uint base = 10);
String  			string_from_uint         (uint64 value);
bool    			string_has_int           (const String &string);
int64   			string_to_int            (const String &string, uint base = 10);
String  			string_from_int          (int64 value);
String  			string_from_float        (float value);
double  			string_to_double         (const String &string);
double  			string_to_double         (const char  *dblstring,
                                                          const char **endptr);
String                          string_from_double       (double value);
inline String                   string_from_float        (double value)         { return string_from_double (value); }
inline double                   string_to_float          (const String &string) { return string_to_double (string); }
template<typename Type> Type    string_to_type           (const String &string);
template<typename Type> String  string_from_type         (Type          value);
template<> inline double        string_to_type<double>   (const String &string) { return string_to_double (string); }
template<> inline String        string_from_type<double> (double         value) { return string_from_double (value); }
template<> inline float         string_to_type<float>    (const String &string) { return string_to_float (string); }
template<> inline String        string_from_type<float>  (float         value)  { return string_from_float (value); }
template<> inline bool          string_to_type<bool>     (const String &string) { return string_to_bool (string); }
template<> inline String        string_from_type<bool>   (bool         value)   { return string_from_bool (value); }
template<> inline int16         string_to_type<int16>    (const String &string) { return string_to_int (string); }
template<> inline String        string_from_type<int16>  (int16         value)  { return string_from_int (value); }
template<> inline uint16        string_to_type<uint16>   (const String &string) { return string_to_uint (string); }
template<> inline String        string_from_type<uint16> (uint16        value)  { return string_from_uint (value); }
template<> inline int           string_to_type<int>      (const String &string) { return string_to_int (string); }
template<> inline String        string_from_type<int>    (int         value)    { return string_from_int (value); }
template<> inline uint          string_to_type<uint>     (const String &string) { return string_to_uint (string); }
template<> inline String        string_from_type<uint>   (uint           value) { return string_from_uint (value); }
template<> inline int64         string_to_type<int64>    (const String &string) { return string_to_int (string); }
template<> inline String        string_from_type<int64>  (int64         value)  { return string_from_int (value); }
template<> inline uint64        string_to_type<uint64>   (const String &string) { return string_to_uint (string); }
template<> inline String        string_from_type<uint64> (uint64         value) { return string_from_uint (value); }
template<> inline String        string_to_type<String>   (const String &string) { return string; }
template<> inline String        string_from_type<String> (String         value) { return value; }
vector<double>                  string_to_vector         (const String         &string);
String                          string_from_vector       (const vector<double> &dvec,
                                                          const String         &delim = " ");
String  			string_from_errno        (int         errno_val);
bool                            string_is_uuid           (const String &uuid_string); /* check uuid formatting */
int                             string_cmp_uuid          (const String &uuid_string1,
                                                          const String &uuid_string2); /* -1=smaller, 0=equal, +1=greater (assuming valid uuid strings) */
String  string_from_pretty_function_name                 (const char *gnuc_pretty_function);
String  string_to_cescape                                (const String &str);
String  string_to_cquote                                 (const String &str);
String  string_from_cquote                               (const String &input);
String  string_lstrip                                    (const String &input);
String  string_rstrip                                    (const String &input);
String  string_strip                                     (const String &input);
String  string_substitute_char                           (const String &input,
                                                          const char    match,
                                                          const char    subst);
String  string_vector_find (const StringVector  &svector,
                            const String        &key,
                            const String        &fallback);
void    memset4		   (uint32              *mem,
                            uint32               filler,
                            uint                 length);

// === String Options ===
bool    string_option_check     (const String   &option_string,
                                 const String   &option);
String  string_option_get       (const String   &option_string,
                                 const String   &option);

// === Charset Conversions ===
bool    text_convert    (const String &to_charset,
                         String       &output_string,
                         const String &from_charset,
                         const String &input_string,
                         const String &fallback_charset = "ISO-8859-15",
                         const String &output_mark = "");

// === StringVector ===
#define RAPICORN_STRING_VECTOR_FROM_ARRAY(ConstCharArray)               ({ \
  Rapicorn::StringVector __a;                                           \
  const uint64_t __l = RAPICORN_ARRAY_SIZE (ConstCharArray);            \
  for (uint64_t __ai = 0; __ai < __l; __ai++)                           \
    __a.push_back (ConstCharArray[__ai]);                               \
  __a; })

} // Rapicorn

#endif /* __RAPICORN_STRINGS_HH__ */
<|endoftext|>


<commit_before>/*
 * Copyright © 2010 Intel Corporation
 *
 * 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 (including the next
 * paragraph) 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.
 */

/**
 * \file opt_structure_splitting.cpp
 *
 * If a structure is only ever referenced by its components, then
 * split those components out to individual variables so they can be
 * handled normally by other optimization passes.
 *
 * This skips structures like uniforms, which need to be accessible as
 * structures for their access by the GL.
 */

#include "ir.h"
#include "ir_visitor.h"
#include "ir_print_visitor.h"
#include "ir_rvalue_visitor.h"
#include "glsl_types.h"

static bool debug = false;

// XXX using variable_entry2 here to avoid collision (MSVC multiply-defined
// function) with the variable_entry class seen in ir_variable_refcount.h
// Perhaps we can use the one in ir_variable_refcount.h and make this class
// here go away?
class variable_entry2 : public exec_node
{
public:
   variable_entry2(ir_variable *var)
   {
      this->var = var;
      this->whole_structure_access = 0;
      this->declaration = false;
      this->components = NULL;
      this->mem_ctx = NULL;
   }

   ir_variable *var; /* The key: the variable's pointer. */

   /** Number of times the variable is referenced, including assignments. */
   unsigned whole_structure_access;

   bool declaration; /* If the variable had a decl in the instruction stream */

   ir_variable **components;

   /** ralloc_parent(this->var) -- the shader's ralloc context. */
   void *mem_ctx;
};

class ir_structure_reference_visitor : public ir_hierarchical_visitor {
public:
   ir_structure_reference_visitor(void)
   {
      this->mem_ctx = ralloc_context(NULL);
      this->variable_list.make_empty();
   }

   ~ir_structure_reference_visitor(void)
   {
      ralloc_free(mem_ctx);
   }

   virtual ir_visitor_status visit(ir_variable *);
   virtual ir_visitor_status visit(ir_dereference_variable *);
   virtual ir_visitor_status visit_enter(ir_dereference_record *);
   virtual ir_visitor_status visit_enter(ir_assignment *);
   virtual ir_visitor_status visit_enter(ir_function_signature *);

   variable_entry2 *get_variable_entry2(ir_variable *var);

   /* List of variable_entry */
   exec_list variable_list;

   void *mem_ctx;
};

variable_entry2 *
ir_structure_reference_visitor::get_variable_entry2(ir_variable *var)
{
   assert(var);

   if (!var->type->is_record() || var->mode == ir_var_uniform)
      return NULL;

   foreach_iter(exec_list_iterator, iter, this->variable_list) {
      variable_entry2 *entry = (variable_entry2 *)iter.get();
      if (entry->var == var)
	 return entry;
   }

   variable_entry2 *entry = new(mem_ctx) variable_entry2(var);
   this->variable_list.push_tail(entry);
   return entry;
}

ir_visitor_status
ir_structure_reference_visitor::visit(ir_variable *ir)
{
   variable_entry2 *entry = this->get_variable_entry2(ir);

   if (entry)
      entry->declaration = true;

   return visit_continue;
}

ir_visitor_status
ir_structure_reference_visitor::visit(ir_dereference_variable *ir)
{
   ir_variable *const var = ir->variable_referenced();
   variable_entry2 *entry = this->get_variable_entry2(var);

   if (entry)
      entry->whole_structure_access++;

   return visit_continue;
}

ir_visitor_status
ir_structure_reference_visitor::visit_enter(ir_dereference_record *ir)
{
   (void) ir;
   /* Don't descend into the ir_dereference_variable below. */
   return visit_continue_with_parent;
}

ir_visitor_status
ir_structure_reference_visitor::visit_enter(ir_assignment *ir)
{
   if (ir->lhs->as_dereference_variable() &&
       ir->rhs->as_dereference_variable() &&
       !ir->condition) {
      /* We'll split copies of a structure to copies of components, so don't
       * descend to the ir_dereference_variables.
       */
      return visit_continue_with_parent;
   }
   return visit_continue;
}

ir_visitor_status
ir_structure_reference_visitor::visit_enter(ir_function_signature *ir)
{
   /* We don't want to descend into the function parameters and
    * dead-code eliminate them, so just accept the body here.
    */
   visit_list_elements(this, &ir->body);
   return visit_continue_with_parent;
}

class ir_structure_splitting_visitor : public ir_rvalue_visitor {
public:
   ir_structure_splitting_visitor(exec_list *vars)
   {
      this->variable_list = vars;
   }

   virtual ~ir_structure_splitting_visitor()
   {
   }

   virtual ir_visitor_status visit_leave(ir_assignment *);

   void split_deref(ir_dereference **deref);
   void handle_rvalue(ir_rvalue **rvalue);
   variable_entry2 *get_splitting_entry(ir_variable *var);

   exec_list *variable_list;
   void *mem_ctx;
};

variable_entry2 *
ir_structure_splitting_visitor::get_splitting_entry(ir_variable *var)
{
   assert(var);

   if (!var->type->is_record())
      return NULL;

   foreach_iter(exec_list_iterator, iter, *this->variable_list) {
      variable_entry2 *entry = (variable_entry2 *)iter.get();
      if (entry->var == var) {
	 return entry;
      }
   }

   return NULL;
}

void
ir_structure_splitting_visitor::split_deref(ir_dereference **deref)
{
   if ((*deref)->ir_type != ir_type_dereference_record)
      return;

   ir_dereference_record *deref_record = (ir_dereference_record *)*deref;
   ir_dereference_variable *deref_var = deref_record->record->as_dereference_variable();
   if (!deref_var)
      return;

   variable_entry2 *entry = get_splitting_entry(deref_var->var);
   if (!entry)
      return;

   unsigned int i;
   for (i = 0; i < entry->var->type->length; i++) {
      if (strcmp(deref_record->field,
		 entry->var->type->fields.structure[i].name) == 0)
	 break;
   }
   assert(i != entry->var->type->length);

   *deref = new(entry->mem_ctx) ir_dereference_variable(entry->components[i]);
}

void
ir_structure_splitting_visitor::handle_rvalue(ir_rvalue **rvalue)
{
   if (!*rvalue)
      return;

   ir_dereference *deref = (*rvalue)->as_dereference();

   if (!deref)
      return;

   split_deref(&deref);
   *rvalue = deref;
}

ir_visitor_status
ir_structure_splitting_visitor::visit_leave(ir_assignment *ir)
{
   ir_dereference_variable *lhs_deref = ir->lhs->as_dereference_variable();
   ir_dereference_variable *rhs_deref = ir->rhs->as_dereference_variable();
   variable_entry2 *lhs_entry = lhs_deref ? get_splitting_entry(lhs_deref->var) : NULL;
   variable_entry2 *rhs_entry = rhs_deref ? get_splitting_entry(rhs_deref->var) : NULL;
   const glsl_type *type = ir->rhs->type;

   if ((lhs_entry || rhs_entry) && !ir->condition) {
      for (unsigned int i = 0; i < type->length; i++) {
	 ir_dereference *new_lhs, *new_rhs;
	 void *mem_ctx = lhs_entry ? lhs_entry->mem_ctx : rhs_entry->mem_ctx;

	 if (lhs_entry) {
	    new_lhs = new(mem_ctx) ir_dereference_variable(lhs_entry->components[i]);
	 } else {
	    new_lhs = new(mem_ctx)
	       ir_dereference_record(ir->lhs->clone(mem_ctx, NULL),
				     type->fields.structure[i].name);
	 }

	 if (rhs_entry) {
	    new_rhs = new(mem_ctx) ir_dereference_variable(rhs_entry->components[i]);
	 } else {
	    new_rhs = new(mem_ctx)
	       ir_dereference_record(ir->rhs->clone(mem_ctx, NULL),
				     type->fields.structure[i].name);
	 }

	 ir->insert_before(new(mem_ctx) ir_assignment(new_lhs,
						      new_rhs,
						      NULL));
      }
      ir->remove();
   } else {
      handle_rvalue(&ir->rhs);
      split_deref(&ir->lhs);
   }

   handle_rvalue(&ir->condition);

   return visit_continue;
}

bool
do_structure_splitting(exec_list *instructions)
{
   ir_structure_reference_visitor refs;

   visit_list_elements(&refs, instructions);

   /* Trim out variables we can't split. */
   foreach_iter(exec_list_iterator, iter, refs.variable_list) {
      variable_entry2 *entry = (variable_entry2 *)iter.get();

      if (debug) {
	 printf("structure %s@%p: decl %d, whole_access %d\n",
		entry->var->name, (void *) entry->var, entry->declaration,
		entry->whole_structure_access);
      }

      if (!entry->declaration || entry->whole_structure_access) {
	 entry->remove();
      }
   }

   if (refs.variable_list.is_empty())
      return false;

   void *mem_ctx = ralloc_context(NULL);

   /* Replace the decls of the structures to be split with their split
    * components.
    */
   foreach_iter(exec_list_iterator, iter, refs.variable_list) {
      variable_entry2 *entry = (variable_entry2 *)iter.get();
      const struct glsl_type *type = entry->var->type;

      entry->mem_ctx = ralloc_parent(entry->var);

      entry->components = ralloc_array(mem_ctx,
				       ir_variable *,
				       type->length);

      for (unsigned int i = 0; i < entry->var->type->length; i++) {
	 const char *name = ralloc_asprintf(mem_ctx, "%s_%s",
					    entry->var->name,
					    type->fields.structure[i].name);

	 entry->components[i] =
	    new(entry->mem_ctx) ir_variable(type->fields.structure[i].type,
					    name,
					    ir_var_temporary);
	 entry->var->insert_before(entry->components[i]);
      }

      entry->var->remove();
   }

   ir_structure_splitting_visitor split(&refs.variable_list);
   visit_list_elements(&split, instructions);

   ralloc_free(mem_ctx);

   return true;
}
<commit_msg>glsl: Reduce processing of expression trees in do_structure_splitting.<commit_after>/*
 * Copyright © 2010 Intel Corporation
 *
 * 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 (including the next
 * paragraph) 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.
 */

/**
 * \file opt_structure_splitting.cpp
 *
 * If a structure is only ever referenced by its components, then
 * split those components out to individual variables so they can be
 * handled normally by other optimization passes.
 *
 * This skips structures like uniforms, which need to be accessible as
 * structures for their access by the GL.
 */

#include "ir.h"
#include "ir_visitor.h"
#include "ir_print_visitor.h"
#include "ir_rvalue_visitor.h"
#include "glsl_types.h"

static bool debug = false;

// XXX using variable_entry2 here to avoid collision (MSVC multiply-defined
// function) with the variable_entry class seen in ir_variable_refcount.h
// Perhaps we can use the one in ir_variable_refcount.h and make this class
// here go away?
class variable_entry2 : public exec_node
{
public:
   variable_entry2(ir_variable *var)
   {
      this->var = var;
      this->whole_structure_access = 0;
      this->declaration = false;
      this->components = NULL;
      this->mem_ctx = NULL;
   }

   ir_variable *var; /* The key: the variable's pointer. */

   /** Number of times the variable is referenced, including assignments. */
   unsigned whole_structure_access;

   bool declaration; /* If the variable had a decl in the instruction stream */

   ir_variable **components;

   /** ralloc_parent(this->var) -- the shader's ralloc context. */
   void *mem_ctx;
};

class ir_structure_reference_visitor : public ir_hierarchical_visitor {
public:
   ir_structure_reference_visitor(void)
   {
      this->mem_ctx = ralloc_context(NULL);
      this->variable_list.make_empty();
   }

   ~ir_structure_reference_visitor(void)
   {
      ralloc_free(mem_ctx);
   }

   virtual ir_visitor_status visit(ir_variable *);
   virtual ir_visitor_status visit(ir_dereference_variable *);
   virtual ir_visitor_status visit_enter(ir_dereference_record *);
   virtual ir_visitor_status visit_enter(ir_assignment *);
   virtual ir_visitor_status visit_enter(ir_function_signature *);

   variable_entry2 *get_variable_entry2(ir_variable *var);

   /* List of variable_entry */
   exec_list variable_list;

   void *mem_ctx;
};

variable_entry2 *
ir_structure_reference_visitor::get_variable_entry2(ir_variable *var)
{
   assert(var);

   if (!var->type->is_record() || var->mode == ir_var_uniform)
      return NULL;

   foreach_iter(exec_list_iterator, iter, this->variable_list) {
      variable_entry2 *entry = (variable_entry2 *)iter.get();
      if (entry->var == var)
	 return entry;
   }

   variable_entry2 *entry = new(mem_ctx) variable_entry2(var);
   this->variable_list.push_tail(entry);
   return entry;
}

ir_visitor_status
ir_structure_reference_visitor::visit(ir_variable *ir)
{
   variable_entry2 *entry = this->get_variable_entry2(ir);

   if (entry)
      entry->declaration = true;

   return visit_continue;
}

ir_visitor_status
ir_structure_reference_visitor::visit(ir_dereference_variable *ir)
{
   ir_variable *const var = ir->variable_referenced();
   variable_entry2 *entry = this->get_variable_entry2(var);

   if (entry)
      entry->whole_structure_access++;

   return visit_continue;
}

ir_visitor_status
ir_structure_reference_visitor::visit_enter(ir_dereference_record *ir)
{
   (void) ir;
   /* Don't descend into the ir_dereference_variable below. */
   return visit_continue_with_parent;
}

ir_visitor_status
ir_structure_reference_visitor::visit_enter(ir_assignment *ir)
{
   /* If there are no structure references yet, no need to bother with
    * processing the expression tree.
    */
   if (this->variable_list.is_empty())
      return visit_continue_with_parent;

   if (ir->lhs->as_dereference_variable() &&
       ir->rhs->as_dereference_variable() &&
       !ir->condition) {
      /* We'll split copies of a structure to copies of components, so don't
       * descend to the ir_dereference_variables.
       */
      return visit_continue_with_parent;
   }
   return visit_continue;
}

ir_visitor_status
ir_structure_reference_visitor::visit_enter(ir_function_signature *ir)
{
   /* We don't want to descend into the function parameters and
    * dead-code eliminate them, so just accept the body here.
    */
   visit_list_elements(this, &ir->body);
   return visit_continue_with_parent;
}

class ir_structure_splitting_visitor : public ir_rvalue_visitor {
public:
   ir_structure_splitting_visitor(exec_list *vars)
   {
      this->variable_list = vars;
   }

   virtual ~ir_structure_splitting_visitor()
   {
   }

   virtual ir_visitor_status visit_leave(ir_assignment *);

   void split_deref(ir_dereference **deref);
   void handle_rvalue(ir_rvalue **rvalue);
   variable_entry2 *get_splitting_entry(ir_variable *var);

   exec_list *variable_list;
   void *mem_ctx;
};

variable_entry2 *
ir_structure_splitting_visitor::get_splitting_entry(ir_variable *var)
{
   assert(var);

   if (!var->type->is_record())
      return NULL;

   foreach_iter(exec_list_iterator, iter, *this->variable_list) {
      variable_entry2 *entry = (variable_entry2 *)iter.get();
      if (entry->var == var) {
	 return entry;
      }
   }

   return NULL;
}

void
ir_structure_splitting_visitor::split_deref(ir_dereference **deref)
{
   if ((*deref)->ir_type != ir_type_dereference_record)
      return;

   ir_dereference_record *deref_record = (ir_dereference_record *)*deref;
   ir_dereference_variable *deref_var = deref_record->record->as_dereference_variable();
   if (!deref_var)
      return;

   variable_entry2 *entry = get_splitting_entry(deref_var->var);
   if (!entry)
      return;

   unsigned int i;
   for (i = 0; i < entry->var->type->length; i++) {
      if (strcmp(deref_record->field,
		 entry->var->type->fields.structure[i].name) == 0)
	 break;
   }
   assert(i != entry->var->type->length);

   *deref = new(entry->mem_ctx) ir_dereference_variable(entry->components[i]);
}

void
ir_structure_splitting_visitor::handle_rvalue(ir_rvalue **rvalue)
{
   if (!*rvalue)
      return;

   ir_dereference *deref = (*rvalue)->as_dereference();

   if (!deref)
      return;

   split_deref(&deref);
   *rvalue = deref;
}

ir_visitor_status
ir_structure_splitting_visitor::visit_leave(ir_assignment *ir)
{
   ir_dereference_variable *lhs_deref = ir->lhs->as_dereference_variable();
   ir_dereference_variable *rhs_deref = ir->rhs->as_dereference_variable();
   variable_entry2 *lhs_entry = lhs_deref ? get_splitting_entry(lhs_deref->var) : NULL;
   variable_entry2 *rhs_entry = rhs_deref ? get_splitting_entry(rhs_deref->var) : NULL;
   const glsl_type *type = ir->rhs->type;

   if ((lhs_entry || rhs_entry) && !ir->condition) {
      for (unsigned int i = 0; i < type->length; i++) {
	 ir_dereference *new_lhs, *new_rhs;
	 void *mem_ctx = lhs_entry ? lhs_entry->mem_ctx : rhs_entry->mem_ctx;

	 if (lhs_entry) {
	    new_lhs = new(mem_ctx) ir_dereference_variable(lhs_entry->components[i]);
	 } else {
	    new_lhs = new(mem_ctx)
	       ir_dereference_record(ir->lhs->clone(mem_ctx, NULL),
				     type->fields.structure[i].name);
	 }

	 if (rhs_entry) {
	    new_rhs = new(mem_ctx) ir_dereference_variable(rhs_entry->components[i]);
	 } else {
	    new_rhs = new(mem_ctx)
	       ir_dereference_record(ir->rhs->clone(mem_ctx, NULL),
				     type->fields.structure[i].name);
	 }

	 ir->insert_before(new(mem_ctx) ir_assignment(new_lhs,
						      new_rhs,
						      NULL));
      }
      ir->remove();
   } else {
      handle_rvalue(&ir->rhs);
      split_deref(&ir->lhs);
   }

   handle_rvalue(&ir->condition);

   return visit_continue;
}

bool
do_structure_splitting(exec_list *instructions)
{
   ir_structure_reference_visitor refs;

   visit_list_elements(&refs, instructions);

   /* Trim out variables we can't split. */
   foreach_iter(exec_list_iterator, iter, refs.variable_list) {
      variable_entry2 *entry = (variable_entry2 *)iter.get();

      if (debug) {
	 printf("structure %s@%p: decl %d, whole_access %d\n",
		entry->var->name, (void *) entry->var, entry->declaration,
		entry->whole_structure_access);
      }

      if (!entry->declaration || entry->whole_structure_access) {
	 entry->remove();
      }
   }

   if (refs.variable_list.is_empty())
      return false;

   void *mem_ctx = ralloc_context(NULL);

   /* Replace the decls of the structures to be split with their split
    * components.
    */
   foreach_iter(exec_list_iterator, iter, refs.variable_list) {
      variable_entry2 *entry = (variable_entry2 *)iter.get();
      const struct glsl_type *type = entry->var->type;

      entry->mem_ctx = ralloc_parent(entry->var);

      entry->components = ralloc_array(mem_ctx,
				       ir_variable *,
				       type->length);

      for (unsigned int i = 0; i < entry->var->type->length; i++) {
	 const char *name = ralloc_asprintf(mem_ctx, "%s_%s",
					    entry->var->name,
					    type->fields.structure[i].name);

	 entry->components[i] =
	    new(entry->mem_ctx) ir_variable(type->fields.structure[i].type,
					    name,
					    ir_var_temporary);
	 entry->var->insert_before(entry->components[i]);
      }

      entry->var->remove();
   }

   ir_structure_splitting_visitor split(&refs.variable_list);
   visit_list_elements(&split, instructions);

   ralloc_free(mem_ctx);

   return true;
}
<|endoftext|>