<commit_before>#include <stdio.h>
#include "gtest/gtest.h"
#include "gmock/gmock.h"
#include "os/os.h"
#include "nmranet/GlobalEventHandler.hxx"
#include "nmranet/NMRAnetEventRegistry.hxx"

using testing::Eq;
using testing::Field;
using testing::InSequence;
using testing::Invoke;
using testing::InvokeWithoutArgs;
using testing::StrictMock;
using testing::WithArg;
using testing::_;

static ThreadExecutor global_executor("ex_thread", 0, 1024);

extern void DecodeRange(EventReport* r);

class DecodeRangeTest : public testing::Test {
 protected:
  void ExpectDecode(uint64_t complex, uint64_t exp_event, uint64_t exp_mask) {
    EventReport r;
    r.event = complex;
    DecodeRange(&r);
    EXPECT_EQ(exp_event, r.event);
    EXPECT_EQ(exp_mask, r.mask);
  }

  uint64_t eventid_;
  uint64_t mask_;
};

TEST_F(DecodeRangeTest, TrivPositive) { ExpectDecode(0b1100, 0b1100, 0b0011); }

TEST_F(DecodeRangeTest, TrivNegative) {
  ExpectDecode(0b110011, 0b110000, 0b0011);
}

TEST_F(DecodeRangeTest, SimplePositive) {
  ExpectDecode(0b1010101110000, 0b1010101110000, 0b1111);
}

TEST_F(DecodeRangeTest, SimpleNegative) {
  ExpectDecode(0b101010111000011111, 0b101010111000000000, 0b11111);
}

TEST_F(DecodeRangeTest, LongPositive) {
  ExpectDecode(0xfffffffffffffff0ULL, 0xfffffffffffffff0ULL, 0xf);
}

TEST_F(DecodeRangeTest, LongNegative) {
  ExpectDecode(0xffffffffffffff0fULL, 0xffffffffffffff00ULL, 0xf);
}

class MockEventHandler : public NMRAnetEventHandler {
 public:
#define DEFPROXYFN(FN) \
  MOCK_METHOD2(FN, void(EventReport* event, Notifiable* done))

  DEFPROXYFN(HandleEventReport);
  DEFPROXYFN(HandleConsumerIdentified);
  DEFPROXYFN(HandleConsumerRangeIdentified);
  DEFPROXYFN(HandleProducerIdentified);
  DEFPROXYFN(HandleProducerRangeIdentified);
  DEFPROXYFN(HandleIdentifyGlobal);
  DEFPROXYFN(HandleIdentifyConsumer);
  DEFPROXYFN(HandleIdentifyProducer);

#undef DEFPROXYFN
};

static void InvokeNotification(Notifiable* done) { done->Notify(); }

static const uint64_t kExitEventId = 0x0808080804040404ULL;
static const uint64_t kTestEventId = 0x0102030405060708ULL;
static const int kEventReportMti = 0x5b4;
static const int kProducerIdentifiedResvdMti = 0x546;

class EventHandlerTests : public ::testing::Test {
 protected:
  EventHandlerTests() : flow_(&global_executor, 10) {
    for (auto* h : {&h1_, &h2_, &h3_, &h4_}) {
      EXPECT_CALL(*h, HandleProducerIdentified(
                          Field(&EventReport::event, kExitEventId), _))
          .WillRepeatedly(
               DoAll(WithArg<1>(Invoke(&InvokeNotification)),
                     InvokeWithoutArgs(
                         this, &EventHandlerTests::InvokeExitNotification)));
    }
  }

  void InvokeExitNotification() { exit_notify_.Notify(); }

  void WaitForCompleted() {
    GlobalEventMessage* m = flow_.AllocateMessage();
    m = flow_.AllocateMessage();
    m->mti = kProducerIdentifiedResvdMti;
    m->event = kExitEventId;
    m->dst_node = 0;
    m->src_node = {0, 0};
    flow_.PostEvent(m);
    exit_notify_.WaitForNotification();
    while (!flow_.executor()->empty()) usleep(100);
  }

  StrictMock<MockEventHandler> h1_;
  StrictMock<MockEventHandler> h2_;
  StrictMock<MockEventHandler> h3_;
  StrictMock<MockEventHandler> h4_;
  GlobalEventFlow flow_;
  SyncNotifiable exit_notify_;
};

TEST_F(EventHandlerTests, SimpleRunTest) {
  NMRAnetEventRegistry::instance()->RegisterHandler(&h1_, 0, 0);
  NMRAnetEventRegistry::instance()->RegisterHandler(&h2_, 0, 0);
  EXPECT_CALL(h1_, HandleEventReport(_, _))
      .WillOnce(WithArg<1>(Invoke(&InvokeNotification)));
  EXPECT_CALL(h2_, HandleEventReport(_, _))
      .WillOnce(WithArg<1>(Invoke(&InvokeNotification)));
  GlobalEventMessage* m = flow_.AllocateMessage();
  m->mti = kEventReportMti;
  m->event = kTestEventId;
  m->dst_node = 0;
  m->src_node = {0, 0};
  flow_.PostEvent(m);
  WaitForCompleted();
}

TEST_F(EventHandlerTests, SimpleRunTest2) {
  NMRAnetEventRegistry::instance()->RegisterHandler(&h1_, 0, 0);
  NMRAnetEventRegistry::instance()->RegisterHandler(&h2_, 0, 0);
  EXPECT_CALL(h1_, HandleEventReport(_, _))
      .WillOnce(WithArg<1>(Invoke(&InvokeNotification)));
  EXPECT_CALL(h2_, HandleEventReport(_, _))
      .WillOnce(WithArg<1>(Invoke(&InvokeNotification)));
  GlobalEventMessage* m = flow_.AllocateMessage();
  m->mti = kEventReportMti;
  m->event = 0x0102030405060708ULL;
  m->dst_node = 0;
  m->src_node = {0, 0};
  flow_.PostEvent(m);
  WaitForCompleted();
}

TEST_F(EventHandlerTests, Run100EventsTest) {
  NMRAnetEventRegistry::instance()->RegisterHandler(&h1_, 0, 0);
  NMRAnetEventRegistry::instance()->RegisterHandler(&h2_, 0, 0);
  EXPECT_CALL(h1_, HandleEventReport(_, _)).Times(100).WillRepeatedly(
      WithArg<1>(Invoke(&InvokeNotification)));
  EXPECT_CALL(h2_, HandleEventReport(_, _)).Times(100).WillRepeatedly(
      WithArg<1>(Invoke(&InvokeNotification)));
  for (int i = 0; i < 100; i++) {
    GlobalEventMessage* m = flow_.AllocateMessage();
    m->mti = kEventReportMti;
    m->event = 0x0102030405060708ULL;
    m->dst_node = 0;
    m->src_node = {0, 0};
    flow_.PostEvent(m);
  }
  WaitForCompleted();
}

TEST_F(EventHandlerTests, EventsOrderTest) {
  NMRAnetEventRegistry::instance()->RegisterHandler(&h1_, 0, 0);
  {
    InSequence s;

    EXPECT_CALL(
        h1_, HandleEventReport(Field(&EventReport::event, kTestEventId + 0), _))
        .WillOnce(WithArg<1>(Invoke(&InvokeNotification)));
    EXPECT_CALL(
        h1_, HandleEventReport(Field(&EventReport::event, kTestEventId + 1), _))
        .WillOnce(WithArg<1>(Invoke(&InvokeNotification)));
    EXPECT_CALL(
        h1_, HandleEventReport(Field(&EventReport::event, kTestEventId + 2), _))
        .WillOnce(WithArg<1>(Invoke(&InvokeNotification)));
  }
  event_handler_mutex.Lock();
  for (int i = 0; i < 3; i++) {
    GlobalEventMessage* m = flow_.AllocateMessage();
    m->mti = kEventReportMti;
    m->event = kTestEventId + i;
    m->dst_node = 0;
    m->src_node = {0, 0};
    flow_.PostEvent(m);
  }
  event_handler_mutex.Unlock();
  WaitForCompleted();
}

int appl_main(int argc, char* argv[]) {
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<commit_msg>Makes use of the new test_main.hxx in the global event handler test.<commit_after>#include "utils/test_main.hxx"
#include "nmranet/GlobalEventHandler.hxx"
#include "nmranet/NMRAnetEventRegistry.hxx"

using testing::Eq;
using testing::Field;
using testing::InSequence;
using testing::Invoke;
using testing::InvokeWithoutArgs;
using testing::StrictMock;
using testing::WithArg;
using testing::_;

static ThreadExecutor global_executor("ex_thread", 0, 1024);

extern void DecodeRange(EventReport* r);

class DecodeRangeTest : public testing::Test {
 protected:
  void ExpectDecode(uint64_t complex, uint64_t exp_event, uint64_t exp_mask) {
    EventReport r;
    r.event = complex;
    DecodeRange(&r);
    EXPECT_EQ(exp_event, r.event);
    EXPECT_EQ(exp_mask, r.mask);
  }

  uint64_t eventid_;
  uint64_t mask_;
};

TEST_F(DecodeRangeTest, TrivPositive) { ExpectDecode(0b1100, 0b1100, 0b0011); }

TEST_F(DecodeRangeTest, TrivNegative) {
  ExpectDecode(0b110011, 0b110000, 0b0011);
}

TEST_F(DecodeRangeTest, SimplePositive) {
  ExpectDecode(0b1010101110000, 0b1010101110000, 0b1111);
}

TEST_F(DecodeRangeTest, SimpleNegative) {
  ExpectDecode(0b101010111000011111, 0b101010111000000000, 0b11111);
}

TEST_F(DecodeRangeTest, LongPositive) {
  ExpectDecode(0xfffffffffffffff0ULL, 0xfffffffffffffff0ULL, 0xf);
}

TEST_F(DecodeRangeTest, LongNegative) {
  ExpectDecode(0xffffffffffffff0fULL, 0xffffffffffffff00ULL, 0xf);
}

class MockEventHandler : public NMRAnetEventHandler {
 public:
#define DEFPROXYFN(FN) \
  MOCK_METHOD2(FN, void(EventReport* event, Notifiable* done))

  DEFPROXYFN(HandleEventReport);
  DEFPROXYFN(HandleConsumerIdentified);
  DEFPROXYFN(HandleConsumerRangeIdentified);
  DEFPROXYFN(HandleProducerIdentified);
  DEFPROXYFN(HandleProducerRangeIdentified);
  DEFPROXYFN(HandleIdentifyGlobal);
  DEFPROXYFN(HandleIdentifyConsumer);
  DEFPROXYFN(HandleIdentifyProducer);

#undef DEFPROXYFN
};

static void InvokeNotification(Notifiable* done) { done->Notify(); }

static const uint64_t kExitEventId = 0x0808080804040404ULL;
static const uint64_t kTestEventId = 0x0102030405060708ULL;
static const int kEventReportMti = 0x5b4;
static const int kProducerIdentifiedResvdMti = 0x546;

class EventHandlerTests : public ::testing::Test {
 protected:
  EventHandlerTests() : flow_(&global_executor, 10) {
    for (auto* h : {&h1_, &h2_, &h3_, &h4_}) {
      EXPECT_CALL(*h, HandleProducerIdentified(
                          Field(&EventReport::event, kExitEventId), _))
          .WillRepeatedly(
               DoAll(WithArg<1>(Invoke(&InvokeNotification)),
                     InvokeWithoutArgs(
                         this, &EventHandlerTests::InvokeExitNotification)));
    }
  }

  void InvokeExitNotification() { exit_notify_.Notify(); }

  void WaitForCompleted() {
    GlobalEventMessage* m = flow_.AllocateMessage();
    m = flow_.AllocateMessage();
    m->mti = kProducerIdentifiedResvdMti;
    m->event = kExitEventId;
    m->dst_node = 0;
    m->src_node = {0, 0};
    flow_.PostEvent(m);
    exit_notify_.WaitForNotification();
    while (!flow_.executor()->empty()) usleep(100);
  }

  StrictMock<MockEventHandler> h1_;
  StrictMock<MockEventHandler> h2_;
  StrictMock<MockEventHandler> h3_;
  StrictMock<MockEventHandler> h4_;
  GlobalEventFlow flow_;
  SyncNotifiable exit_notify_;
};

TEST_F(EventHandlerTests, SimpleRunTest) {
  NMRAnetEventRegistry::instance()->RegisterHandler(&h1_, 0, 0);
  NMRAnetEventRegistry::instance()->RegisterHandler(&h2_, 0, 0);
  EXPECT_CALL(h1_, HandleEventReport(_, _))
      .WillOnce(WithArg<1>(Invoke(&InvokeNotification)));
  EXPECT_CALL(h2_, HandleEventReport(_, _))
      .WillOnce(WithArg<1>(Invoke(&InvokeNotification)));
  GlobalEventMessage* m = flow_.AllocateMessage();
  m->mti = kEventReportMti;
  m->event = kTestEventId;
  m->dst_node = 0;
  m->src_node = {0, 0};
  flow_.PostEvent(m);
  WaitForCompleted();
}

TEST_F(EventHandlerTests, SimpleRunTest2) {
  NMRAnetEventRegistry::instance()->RegisterHandler(&h1_, 0, 0);
  NMRAnetEventRegistry::instance()->RegisterHandler(&h2_, 0, 0);
  EXPECT_CALL(h1_, HandleEventReport(_, _))
      .WillOnce(WithArg<1>(Invoke(&InvokeNotification)));
  EXPECT_CALL(h2_, HandleEventReport(_, _))
      .WillOnce(WithArg<1>(Invoke(&InvokeNotification)));
  GlobalEventMessage* m = flow_.AllocateMessage();
  m->mti = kEventReportMti;
  m->event = 0x0102030405060708ULL;
  m->dst_node = 0;
  m->src_node = {0, 0};
  flow_.PostEvent(m);
  WaitForCompleted();
}

TEST_F(EventHandlerTests, Run100EventsTest) {
  NMRAnetEventRegistry::instance()->RegisterHandler(&h1_, 0, 0);
  NMRAnetEventRegistry::instance()->RegisterHandler(&h2_, 0, 0);
  EXPECT_CALL(h1_, HandleEventReport(_, _)).Times(100).WillRepeatedly(
      WithArg<1>(Invoke(&InvokeNotification)));
  EXPECT_CALL(h2_, HandleEventReport(_, _)).Times(100).WillRepeatedly(
      WithArg<1>(Invoke(&InvokeNotification)));
  for (int i = 0; i < 100; i++) {
    GlobalEventMessage* m = flow_.AllocateMessage();
    m->mti = kEventReportMti;
    m->event = 0x0102030405060708ULL;
    m->dst_node = 0;
    m->src_node = {0, 0};
    flow_.PostEvent(m);
  }
  WaitForCompleted();
}

TEST_F(EventHandlerTests, EventsOrderTest) {
  NMRAnetEventRegistry::instance()->RegisterHandler(&h1_, 0, 0);
  {
    InSequence s;

    EXPECT_CALL(
        h1_, HandleEventReport(Field(&EventReport::event, kTestEventId + 0), _))
        .WillOnce(WithArg<1>(Invoke(&InvokeNotification)));
    EXPECT_CALL(
        h1_, HandleEventReport(Field(&EventReport::event, kTestEventId + 1), _))
        .WillOnce(WithArg<1>(Invoke(&InvokeNotification)));
    EXPECT_CALL(
        h1_, HandleEventReport(Field(&EventReport::event, kTestEventId + 2), _))
        .WillOnce(WithArg<1>(Invoke(&InvokeNotification)));
  }
  event_handler_mutex.Lock();
  for (int i = 0; i < 3; i++) {
    GlobalEventMessage* m = flow_.AllocateMessage();
    m->mti = kEventReportMti;
    m->event = kTestEventId + i;
    m->dst_node = 0;
    m->src_node = {0, 0};
    flow_.PostEvent(m);
  }
  event_handler_mutex.Unlock();
  WaitForCompleted();
}
<|endoftext|>


<commit_before>/*Copyright (c) 2011, Edgar Solomonik, all rights reserved.*/
#ifndef __CTF_HPP__
#define __CTF_HPP__

#include "mpi.h"
#include <stdio.h>
#include <stdint.h>
#include <vector>
#include <map>
#include <set>
#include <deque>
#include <complex>
#include <assert.h>

#define CTF_VERSION 131

#include "../src/interface/tensor.h"
#include "../src/interface/idx_tensor.h"
#include "../src/interface/timer.h"
#include "../src/interface/back_comp.h"

#endif

<commit_msg>increment version to 1.32<commit_after>/*Copyright (c) 2011, Edgar Solomonik, all rights reserved.*/
#ifndef __CTF_HPP__
#define __CTF_HPP__

#include "mpi.h"
#include <stdio.h>
#include <stdint.h>
#include <vector>
#include <map>
#include <set>
#include <deque>
#include <complex>
#include <assert.h>

#define CTF_VERSION 132

#include "../src/interface/tensor.h"
#include "../src/interface/idx_tensor.h"
#include "../src/interface/timer.h"
#include "../src/interface/back_comp.h"

#endif

<|endoftext|>


<commit_before><commit_msg>Start: [skip ci] replace QTextStream and its manipulators with stringstream to avoid deprecation warnings with Qt 5.15<commit_after><|endoftext|>


<commit_before>#pragma once

#include <vector>
#include <tuple>
#include <utility>

namespace helene
{

namespace soa_detail
{
template <class MemberPointerType>
struct deduce_member_pointer;

template <class MemberType, class ObjectType>
struct deduce_member_pointer<MemberType ObjectType::*>
{
    typedef MemberType member_type;
    typedef ObjectType object_type;
};

template <class MemberPointerType>
using member_type_t =
    typename deduce_member_pointer<MemberPointerType>::member_type;

template <class MemberPointerType>
using object_type_t =
    typename deduce_member_pointer<MemberPointerType>::object_type;
}

template <class PointerType, PointerType PointerValue>
struct member_reference
{
    static constexpr PointerType pointer_value = PointerValue;
};

template <class T, class... MemberRefs>
class element_proxy;

template <class T, class... PointerTypes, PointerTypes... PointerValues>
class element_proxy<T, member_reference<PointerTypes, PointerValues>...>
{
    typedef std::tuple<soa_detail::member_type_t<PointerTypes>*...> tuple_type;

    template <std::size_t S, class FirstRef, class... RestRefs>
    struct assignment_helper
    {
        static void
        assign(std::tuple<soa_detail::member_type_t<PointerTypes>*...>& tpl,
               const T& value)
        {
            *std::get<S>(tpl) = value.*FirstRef::pointer_value;

            assignment_helper<S + 1, RestRefs...>::assign(tpl, value);
        }
    };

    template <std::size_t S, class LastRef>
    struct assignment_helper<S, LastRef>
    {

        static void
        assign(std::tuple<soa_detail::member_type_t<PointerTypes>*...>& tpl,
               const T& value)
        {
            *std::get<S>(tpl) = value.*LastRef::pointer_value;
        }
    };

    template <std::size_t S, class FirstRef, class... RestRefs>
    struct make_helper
    {
        static void
        apply(T& v, const tuple_type& tpl)
        {
            v.*FirstRef::pointer_value = *std::get<S>(tpl);
            make_helper<S + 1, RestRefs...>::apply(v, tpl);
        }
    };

    template <std::size_t S, class LastRef>
    struct make_helper<S, LastRef>
    {
        static void
        apply(T& v, const tuple_type& tpl)
        {
            v.*LastRef::pointer_value = *std::get<S>(tpl);
        }
    };

public:
    element_proxy(soa_detail::member_type_t<PointerTypes>&... args)
        : pointers_(&args...)
    {
    }

    operator T() const
    {
        T out{};
        make_helper<0, member_reference<PointerTypes, PointerValues>...>::apply(
            out, pointers_);
        return out;
    }

    element_proxy&
    operator=(const T& value)
    {
        assignment_helper<0, member_reference<PointerTypes, PointerValues>...>::
            assign(pointers_, value);

        return *this;
    }

private:
    tuple_type pointers_;
};

// helper to access respective parents that are multiply inherited
template <class FirstParent, class... RestParents>
struct parent_helper
{
    template <class SoaType>
    static std::size_t
    size(const SoaType& s)
    {
        return s.FirstParent::members_.size();
    }

    template <class SoaType>
    static void
    push_back(SoaType& s, const typename SoaType::value_type& value)
    {
        s.FirstParent::members_.push_back(value.*FirstParent::pointer_value);
        parent_helper<RestParents...>::push_back(s, value);
    }

    template <class SoaType, class FirstElem, class... RestElems>
    static void
    push_back_members(SoaType& s, FirstElem&& f_elm, RestElems&&... rest)
    {
        s.FirstParent::members_.push_back(std::forward<FirstElem>(f_elm));
        parent_helper<RestParents...>::push_back_members(
            s, std::forward<RestElems>(rest)...);
    }
};

template <class LastParent>
struct parent_helper<LastParent>
{
    template <class SoaType>
    static std::size_t
    size(const SoaType& s)
    {
        return s.LastParent::members_.size();
    }

    template <class SoaType>
    static void
    push_back(SoaType& s, const typename SoaType::value_type& value)
    {
        s.LastParent::members_.push_back(value.*LastParent::pointer_value);
    }

    template <class SoaType, class LastElem>
    static void
    push_back_members(SoaType& s, LastElem&& elem)
    {
        s.LastParent::members_.push_back(std::forward<LastElem>(elem));
    }
};

template <class MemberPointerType, MemberPointerType MemberPointerValue>
class member_container
{
public:
    typedef soa_detail::member_type_t<MemberPointerType> member_type;
    typedef soa_detail::object_type_t<MemberPointerType> object_type;

    static constexpr MemberPointerType pointer_value = MemberPointerValue;

public:
    member_container() = default;

    std::vector<member_type> members_;
};

template <class T, class... MemberContainer>
class soa;

template <class T, class... MemberPtrTypes, MemberPtrTypes... MemberPtrValues>
class soa<T, member_container<MemberPtrTypes, MemberPtrValues>...>
    : public member_container<MemberPtrTypes, MemberPtrValues>...
{
public:
    typedef T value_type;
    typedef element_proxy<T,
                          member_reference<MemberPtrTypes, MemberPtrValues>...>
        proxy_value_type;

public:
    soa() : member_container<MemberPtrTypes, MemberPtrValues>()...
    {
    }

    std::size_t
    size() const
    {
        return parent_helper<
            member_container<MemberPtrTypes, MemberPtrValues>...>::size(*this);
    }

    void
    push_back(const T& value)
    {
        parent_helper<member_container<MemberPtrTypes, MemberPtrValues>...>::
            push_back(*this, value);
    }

    template <class... Elems>
    void
    push_back_members(Elems&&... elems)
    {
        parent_helper<member_container<MemberPtrTypes, MemberPtrValues>...>::
            push_back_members(*this, std::forward<Elems>(elems)...);
    }

    proxy_value_type operator[](std::size_t n)
    {
        return proxy_value_type(
            member_container<MemberPtrTypes, MemberPtrValues>::members_[n]...);
    }

    const proxy_value_type operator[](std::size_t n) const
    {
        return proxy_value_type(
            member_container<MemberPtrTypes, MemberPtrValues>::members_[n]...);
    }

    template <class MemberPtrType, MemberPtrType MemberPtrValue>
    soa_detail::member_type_t<MemberPtrType>*
    data()
    {
        return member_container<MemberPtrType, MemberPtrValue>::members_.data();
    }

    template <class MemberPtrType, MemberPtrType MemberPtrValue>
    const soa_detail::member_type_t<MemberPtrType>*
    data() const
    {
        return member_container<MemberPtrType, MemberPtrValue>::members_.data();
    }
};
}
<commit_msg>Add member function reserve. 	modified:   include/soa.hpp<commit_after>#pragma once

#include <vector>
#include <tuple>
#include <utility>

namespace helene
{

namespace soa_detail
{
template <class MemberPointerType>
struct deduce_member_pointer;

template <class MemberType, class ObjectType>
struct deduce_member_pointer<MemberType ObjectType::*>
{
    typedef MemberType member_type;
    typedef ObjectType object_type;
};

template <class MemberPointerType>
using member_type_t =
    typename deduce_member_pointer<MemberPointerType>::member_type;

template <class MemberPointerType>
using object_type_t =
    typename deduce_member_pointer<MemberPointerType>::object_type;
}

template <class PointerType, PointerType PointerValue>
struct member_reference
{
    static constexpr PointerType pointer_value = PointerValue;
};

template <class T, class... MemberRefs>
class element_proxy;

template <class T, class... PointerTypes, PointerTypes... PointerValues>
class element_proxy<T, member_reference<PointerTypes, PointerValues>...>
{
    typedef std::tuple<soa_detail::member_type_t<PointerTypes>*...> tuple_type;

    template <std::size_t S, class FirstRef, class... RestRefs>
    struct assignment_helper
    {
        static void
        assign(std::tuple<soa_detail::member_type_t<PointerTypes>*...>& tpl,
               const T& value)
        {
            *std::get<S>(tpl) = value.*FirstRef::pointer_value;

            assignment_helper<S + 1, RestRefs...>::assign(tpl, value);
        }
    };

    template <std::size_t S, class LastRef>
    struct assignment_helper<S, LastRef>
    {

        static void
        assign(std::tuple<soa_detail::member_type_t<PointerTypes>*...>& tpl,
               const T& value)
        {
            *std::get<S>(tpl) = value.*LastRef::pointer_value;
        }
    };

    template <std::size_t S, class FirstRef, class... RestRefs>
    struct make_helper
    {
        static void
        apply(T& v, const tuple_type& tpl)
        {
            v.*FirstRef::pointer_value = *std::get<S>(tpl);
            make_helper<S + 1, RestRefs...>::apply(v, tpl);
        }
    };

    template <std::size_t S, class LastRef>
    struct make_helper<S, LastRef>
    {
        static void
        apply(T& v, const tuple_type& tpl)
        {
            v.*LastRef::pointer_value = *std::get<S>(tpl);
        }
    };

public:
    element_proxy(soa_detail::member_type_t<PointerTypes>&... args)
        : pointers_(&args...)
    {
    }

    operator T() const
    {
        T out{};
        make_helper<0, member_reference<PointerTypes, PointerValues>...>::apply(
            out, pointers_);
        return out;
    }

    element_proxy&
    operator=(const T& value)
    {
        assignment_helper<0, member_reference<PointerTypes, PointerValues>...>::
            assign(pointers_, value);

        return *this;
    }

private:
    tuple_type pointers_;
};

// helper to access respective parents that are multiply inherited
template <class FirstParent, class... RestParents>
struct parent_helper
{
    template <class SoaType>
    static std::size_t
    size(const SoaType& s)
    {
        return s.FirstParent::members_.size();
    }

    template <class SoaType>
    static void
    push_back(SoaType& s, const typename SoaType::value_type& value)
    {
        s.FirstParent::members_.push_back(value.*FirstParent::pointer_value);
        parent_helper<RestParents...>::push_back(s, value);
    }

    template <class SoaType, class FirstElem, class... RestElems>
    static void
    push_back_members(SoaType& s, FirstElem&& f_elm, RestElems&&... rest)
    {
        s.FirstParent::members_.push_back(std::forward<FirstElem>(f_elm));
        parent_helper<RestParents...>::push_back_members(
            s, std::forward<RestElems>(rest)...);
    }

    template <class SoaType>
    static void
    reserve(SoaType& s, std::size_t n)
    {
        s.FirstParent::members_.reserve(n);
        parent_helper<RestParents...>::reserve(s, n);
    }
};

template <class LastParent>
struct parent_helper<LastParent>
{
    template <class SoaType>
    static std::size_t
    size(const SoaType& s)
    {
        return s.LastParent::members_.size();
    }

    template <class SoaType>
    static void
    push_back(SoaType& s, const typename SoaType::value_type& value)
    {
        s.LastParent::members_.push_back(value.*LastParent::pointer_value);
    }

    template <class SoaType, class LastElem>
    static void
    push_back_members(SoaType& s, LastElem&& elem)
    {
        s.LastParent::members_.push_back(std::forward<LastElem>(elem));
    }

    template <class SoaType>
    static void
    reserve(SoaType& s, std::size_t n)
    {
        s.LastParent::members_.reserve(n);
    }
};

template <class MemberPointerType, MemberPointerType MemberPointerValue>
class member_container
{
public:
    typedef soa_detail::member_type_t<MemberPointerType> member_type;
    typedef soa_detail::object_type_t<MemberPointerType> object_type;

    static constexpr MemberPointerType pointer_value = MemberPointerValue;

public:
    member_container() = default;

    std::vector<member_type> members_;
};

template <class T, class... MemberContainer>
class soa;

template <class T, class... MemberPtrTypes, MemberPtrTypes... MemberPtrValues>
class soa<T, member_container<MemberPtrTypes, MemberPtrValues>...>
    : public member_container<MemberPtrTypes, MemberPtrValues>...
{
public:
    typedef T value_type;
    typedef element_proxy<T,
                          member_reference<MemberPtrTypes, MemberPtrValues>...>
        proxy_value_type;

public:
    soa() : member_container<MemberPtrTypes, MemberPtrValues>()...
    {
    }

    std::size_t
    size() const
    {
        return parent_helper<
            member_container<MemberPtrTypes, MemberPtrValues>...>::size(*this);
    }

    void
    push_back(const T& value)
    {
        parent_helper<member_container<MemberPtrTypes, MemberPtrValues>...>::
            push_back(*this, value);
    }

    template <class... Elems>
    void
    push_back_members(Elems&&... elems)
    {
        parent_helper<member_container<MemberPtrTypes, MemberPtrValues>...>::
            push_back_members(*this, std::forward<Elems>(elems)...);
    }

    proxy_value_type operator[](std::size_t n)
    {
        return proxy_value_type(
            member_container<MemberPtrTypes, MemberPtrValues>::members_[n]...);
    }

    const proxy_value_type operator[](std::size_t n) const
    {
        return proxy_value_type(
            member_container<MemberPtrTypes, MemberPtrValues>::members_[n]...);
    }

    template <class MemberPtrType, MemberPtrType MemberPtrValue>
    soa_detail::member_type_t<MemberPtrType>*
    data()
    {
        return member_container<MemberPtrType, MemberPtrValue>::members_.data();
    }

    template <class MemberPtrType, MemberPtrType MemberPtrValue>
    const soa_detail::member_type_t<MemberPtrType>*
    data() const
    {
        return member_container<MemberPtrType, MemberPtrValue>::members_.data();
    }

    void
    reserve(std::size_t n)
    {
        parent_helper<member_container<MemberPtrTypes,
                                       MemberPtrValues>...>::reserve(*this, n);
    }
};
}
<|endoftext|>


<commit_before>#include "tangram.h"
#include "platform.h"
#include "gl.h"
#include <cmath>

// Forward declaration
void init_main_window();

// Input handling
// ==============

const double double_tap_time = 0.5; // seconds
const double scroll_multiplier = 0.05; // scaling for zoom
const double single_tap_time = 0.25; //seconds (to avoid a long press being considered as a tap)

bool was_panning = false;
double last_mouse_up = -double_tap_time; // First click should never trigger a double tap
double last_mouse_down = 0.0f;
double last_x_down = 0.0;
double last_y_down = 0.0;

void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) {

    if (button != GLFW_MOUSE_BUTTON_1) {
        return; // This event is for a mouse button that we don't care about
    }

    if (was_panning) {
        was_panning = false;
        return; // Clicks with movement don't count as taps
    }

    double x, y;
    glfwGetCursorPos(window, &x, &y);
    double time = glfwGetTime();

    if (action == GLFW_PRESS) {
        Tangram::handlePanGesture(0.0f, 0.0f, 0.0f, 0.0f);
        last_x_down = x;
        last_y_down = y;
        last_mouse_down = glfwGetTime();
        return;
    }

    if (time - last_mouse_up < double_tap_time) {
        Tangram::handleDoubleTapGesture(x, y);
    } else if ( (time - last_mouse_down) < single_tap_time) {
        Tangram::handleTapGesture(x, y);
    }

    last_mouse_up = time;

}

void cursor_pos_callback(GLFWwindow* window, double x, double y) {

    int action = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_1);

    if (action == GLFW_PRESS) {

        if (was_panning) {
            Tangram::handlePanGesture(last_x_down, last_y_down, x, y);
        }

        was_panning = true;
        last_x_down = x;
        last_y_down = y;
    }

}

void scroll_callback(GLFWwindow* window, double scrollx, double scrolly) {

    double x, y;
    glfwGetCursorPos(window, &x, &y);

    bool rotating = glfwGetKey(window, GLFW_KEY_LEFT_ALT) == GLFW_PRESS || glfwGetKey(window, GLFW_KEY_RIGHT_ALT) == GLFW_PRESS;
    bool shoving = glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS || glfwGetKey(window, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS;

    if (shoving) {
        Tangram::handleShoveGesture(scroll_multiplier * scrolly);
    } else if (rotating) {
        Tangram::handleRotateGesture(x, y, scroll_multiplier * scrolly);
    } else {
        Tangram::handlePinchGesture(x, y, 1.0 + scroll_multiplier * scrolly, 0.f);
    }

}

void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {

    if (action == GLFW_PRESS) {
        switch (key) {
            case GLFW_KEY_1:
                Tangram::toggleDebugFlag(Tangram::DebugFlags::freeze_tiles);
                break;
            case GLFW_KEY_2:
                Tangram::toggleDebugFlag(Tangram::DebugFlags::proxy_colors);
                break;
            case GLFW_KEY_3:
                Tangram::toggleDebugFlag(Tangram::DebugFlags::tile_bounds);
                break;
            case GLFW_KEY_4:
                Tangram::toggleDebugFlag(Tangram::DebugFlags::tile_infos);
                break;
            case GLFW_KEY_5:
                Tangram::toggleDebugFlag(Tangram::DebugFlags::labels);
                break;
            case GLFW_KEY_BACKSPACE:
                init_main_window(); // Simulate GL context loss
                break;
            default:
                break;
        }
    }
}

// Window handling
// ===============

GLFWwindow* main_window = nullptr;
int width = 800;
int height = 600;

void window_size_callback(GLFWwindow* window, int width, int height) {

    Tangram::resize(width, height);

}

void init_main_window() {

    // Setup tangram
    Tangram::initialize("scene.yaml");

    // Destroy old window
    if (main_window != nullptr) {
        glfwDestroyWindow(main_window);
    }

    // Create a windowed mode window and its OpenGL context
    glfwWindowHint(GLFW_SAMPLES, 2);
    main_window = glfwCreateWindow(width, height, "Tangram ES", NULL, NULL);
    if (!main_window) {
        glfwTerminate();
    }

    // Make the main_window's context current
    glfwMakeContextCurrent(main_window);

    // Set input callbacks
    glfwSetWindowSizeCallback(main_window, window_size_callback);
    glfwSetMouseButtonCallback(main_window, mouse_button_callback);
    glfwSetCursorPosCallback(main_window, cursor_pos_callback);
    glfwSetScrollCallback(main_window, scroll_callback);
    glfwSetKeyCallback(main_window, key_callback);

    // Setup graphics
    Tangram::setupGL();
    Tangram::resize(width, height);

    // Work-around for a bug in GLFW on retina displays
    int fbWidth = 0, fbHeight = 0;
    glfwGetFramebufferSize(main_window, &fbWidth, &fbHeight);
    glViewport(0, 0, fbWidth, fbHeight);

}

// Main program
// ============

int main(void) {

    // Initialize the windowing library
    if (!glfwInit()) {
        return -1;
    }

    init_main_window();

    // Initialize networking
    NSurlInit();

    double lastTime = glfwGetTime();

    // Loop until the user closes the window
    while (!glfwWindowShouldClose(main_window)) {

        double currentTime = glfwGetTime();
        double delta = currentTime - lastTime;
        lastTime = currentTime;

        // Render
        Tangram::update(delta);
        Tangram::render();

        // Swap front and back buffers
        glfwSwapBuffers(main_window);

        // Poll for and process events
        if (isContinuousRendering()) {
            glfwPollEvents();
        } else {
            glfwWaitEvents();
        }
    }

    glfwTerminate();
    return 0;
}
<commit_msg>Dynamic data rendering in OS X demo<commit_after>#include "tangram.h"
#include "platform.h"
#include "gl.h"
#include <cmath>

// Forward declaration
void init_main_window();

// Input handling
// ==============

const double double_tap_time = 0.5; // seconds
const double scroll_multiplier = 0.05; // scaling for zoom
const double single_tap_time = 0.25; //seconds (to avoid a long press being considered as a tap)

bool was_panning = false;
double last_mouse_up = -double_tap_time; // First click should never trigger a double tap
double last_mouse_down = 0.0f;
double last_x_down = 0.0;
double last_y_down = 0.0;
int data_source_id = -1;

void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) {

    if (button != GLFW_MOUSE_BUTTON_1) {
        return; // This event is for a mouse button that we don't care about
    }

    if (was_panning) {
        was_panning = false;
        return; // Clicks with movement don't count as taps
    }

    double x, y;
    glfwGetCursorPos(window, &x, &y);
    double time = glfwGetTime();

    if (action == GLFW_PRESS) {
        Tangram::handlePanGesture(0.0f, 0.0f, 0.0f, 0.0f);
        last_x_down = x;
        last_y_down = y;
        last_mouse_down = glfwGetTime();
        return;
    }

    if (time - last_mouse_up < double_tap_time) {
        Tangram::clearSourceData(data_source_id);
        // Tangram::handleDoubleTapGesture(x, y);
    } else if ( (time - last_mouse_down) < single_tap_time) {
        double point[2] = { x, y };
        Tangram::screenToWorldCoordinates(point[0], point[1]);
        Tangram::addSourcePoint(data_source_id, point);
        // Tangram::handleTapGesture(x, y);
    }

    last_mouse_up = time;

}

void cursor_pos_callback(GLFWwindow* window, double x, double y) {

    int action = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_1);

    if (action == GLFW_PRESS) {

        if (was_panning) {
            Tangram::handlePanGesture(last_x_down, last_y_down, x, y);
        }

        was_panning = true;
        last_x_down = x;
        last_y_down = y;
    }

}

void scroll_callback(GLFWwindow* window, double scrollx, double scrolly) {

    double x, y;
    glfwGetCursorPos(window, &x, &y);

    bool rotating = glfwGetKey(window, GLFW_KEY_LEFT_ALT) == GLFW_PRESS || glfwGetKey(window, GLFW_KEY_RIGHT_ALT) == GLFW_PRESS;
    bool shoving = glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS || glfwGetKey(window, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS;

    if (shoving) {
        Tangram::handleShoveGesture(scroll_multiplier * scrolly);
    } else if (rotating) {
        Tangram::handleRotateGesture(x, y, scroll_multiplier * scrolly);
    } else {
        Tangram::handlePinchGesture(x, y, 1.0 + scroll_multiplier * scrolly, 0.f);
    }

}

void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {

    if (action == GLFW_PRESS) {
        switch (key) {
            case GLFW_KEY_1:
                Tangram::toggleDebugFlag(Tangram::DebugFlags::freeze_tiles);
                break;
            case GLFW_KEY_2:
                Tangram::toggleDebugFlag(Tangram::DebugFlags::proxy_colors);
                break;
            case GLFW_KEY_3:
                Tangram::toggleDebugFlag(Tangram::DebugFlags::tile_bounds);
                break;
            case GLFW_KEY_4:
                Tangram::toggleDebugFlag(Tangram::DebugFlags::tile_infos);
                break;
            case GLFW_KEY_5:
                Tangram::toggleDebugFlag(Tangram::DebugFlags::labels);
                break;
            case GLFW_KEY_BACKSPACE:
                init_main_window(); // Simulate GL context loss
                break;
            default:
                break;
        }
    }
}

// Window handling
// ===============

GLFWwindow* main_window = nullptr;
int width = 800;
int height = 600;

void window_size_callback(GLFWwindow* window, int width, int height) {

    Tangram::resize(width, height);

}

void init_main_window() {

    // Setup tangram
    Tangram::initialize("scene.yaml");

    // Destroy old window
    if (main_window != nullptr) {
        glfwDestroyWindow(main_window);
    }

    // Create a windowed mode window and its OpenGL context
    glfwWindowHint(GLFW_SAMPLES, 2);
    main_window = glfwCreateWindow(width, height, "Tangram ES", NULL, NULL);
    if (!main_window) {
        glfwTerminate();
    }

    // Make the main_window's context current
    glfwMakeContextCurrent(main_window);

    // Set input callbacks
    glfwSetWindowSizeCallback(main_window, window_size_callback);
    glfwSetMouseButtonCallback(main_window, mouse_button_callback);
    glfwSetCursorPosCallback(main_window, cursor_pos_callback);
    glfwSetScrollCallback(main_window, scroll_callback);
    glfwSetKeyCallback(main_window, key_callback);

    // Setup graphics
    Tangram::setupGL();
    Tangram::resize(width, height);

    // Work-around for a bug in GLFW on retina displays
    int fbWidth = 0, fbHeight = 0;
    glfwGetFramebufferSize(main_window, &fbWidth, &fbHeight);
    glViewport(0, 0, fbWidth, fbHeight);

    data_source_id = Tangram::addDataSource("touch");

}

// Main program
// ============

int main(void) {

    // Initialize the windowing library
    if (!glfwInit()) {
        return -1;
    }

    init_main_window();

    // Initialize networking
    NSurlInit();

    double lastTime = glfwGetTime();

    // Loop until the user closes the window
    while (!glfwWindowShouldClose(main_window)) {

        double currentTime = glfwGetTime();
        double delta = currentTime - lastTime;
        lastTime = currentTime;

        // Render
        Tangram::update(delta);
        Tangram::render();

        // Swap front and back buffers
        glfwSwapBuffers(main_window);

        // Poll for and process events
        if (isContinuousRendering()) {
            glfwPollEvents();
        } else {
            glfwWaitEvents();
        }
    }

    glfwTerminate();
    return 0;
}
<|endoftext|>


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

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "QmitkPropertyTreeItem.h"
#include "QmitkPropertyTreeModel.h"
#include <mitkProperties.h>
#include <mitkColorProperty.h>
#include <mitkEnumerationProperty.h>
#include <mitkStringProperty.h>
#include <mitkRenderingManager.h>
#include <QColor>

QmitkPropertyTreeModel::QmitkPropertyTreeModel(QObject *parent)
: QAbstractItemModel(parent),
  m_Properties(NULL),
  m_RootItem(NULL)
{
  CreateRootItem();
}

void QmitkPropertyTreeModel::SetProperties(mitk::PropertyList *properties)
{
  if (properties == m_Properties)
    return;

  beginResetModel();

  if (m_RootItem != NULL)
  {
    delete m_RootItem;
    m_RootItem = NULL;
    m_Properties = NULL;
  }

  CreateRootItem();

  if (properties != NULL && !properties->IsEmpty())
  {
    m_Properties = properties;

    std::map<std::string, mitk::BaseProperty::Pointer>::const_iterator end = properties->GetMap()->end();

    for (std::map<std::string, mitk::BaseProperty::Pointer>::const_iterator iter = properties->GetMap()->begin(); iter != end; ++iter)
    {
      QList<QVariant> data;
      data << iter->first.c_str() << QVariant::fromValue<void *>((reinterpret_cast<void *>(iter->second.GetPointer())));
      m_RootItem->AppendChild(new QmitkPropertyTreeItem(data));
    }
  }

  endResetModel();
}

void QmitkPropertyTreeModel::CreateRootItem()
{
  if (m_RootItem == NULL)
  {
    QList<QVariant> rootData;
    rootData << "Property" << "Value";
    m_RootItem = new QmitkPropertyTreeItem(rootData);
  }
}

QmitkPropertyTreeModel::~QmitkPropertyTreeModel()
{
  delete m_RootItem;
}

int QmitkPropertyTreeModel::columnCount(const QModelIndex &parent) const
{
  if (parent.isValid())
    return static_cast<QmitkPropertyTreeItem *>(parent.internalPointer())->GetColumnCount();
  else
    return m_RootItem->GetColumnCount();
}

QVariant QmitkPropertyTreeModel::data(const QModelIndex &index, int role) const
{
  if (!index.isValid())
    return QVariant();

  if (index.column() == 0 && role == Qt::DisplayRole)
    return static_cast<QmitkPropertyTreeItem *>(index.internalPointer())->GetData(index.column());

  if (index.column() == 1 && static_cast<QmitkPropertyTreeItem *>(index.internalPointer())->GetData(index.column()).isValid())
  {
    mitk::BaseProperty *property = reinterpret_cast<mitk::BaseProperty *>(static_cast<QmitkPropertyTreeItem *>(index.internalPointer())->GetData(index.column()).value<void *>());

    if (mitk::ColorProperty *colorProperty = dynamic_cast<mitk::ColorProperty *>(property))
    {
      if (role == Qt::DisplayRole || role == Qt::EditRole)
      {
        mitk::Color mitkColor = colorProperty->GetColor();
        QColor qtColor(static_cast<int>(mitkColor.GetRed() * 255), static_cast<int>(mitkColor.GetGreen() * 255), static_cast<int>(mitkColor.GetBlue() * 255));
        return QVariant::fromValue<QColor>(qtColor);
      }
    }
    else if (mitk::BoolProperty *boolProperty = dynamic_cast<mitk::BoolProperty *>(property))
    {
      if (role == Qt::CheckStateRole)
        return boolProperty->GetValue() ? Qt::Checked : Qt::Unchecked;
    }
    else if (mitk::StringProperty *stringProperty = dynamic_cast<mitk::StringProperty *>(property))
    {
      if (role == Qt::DisplayRole || role == Qt::EditRole)
        return QString(stringProperty->GetValue());
    }
    else if (mitk::IntProperty *intProperty = dynamic_cast<mitk::IntProperty *>(property))
    {
      if (role == Qt::DisplayRole || role == Qt::EditRole)
        return intProperty->GetValue();
    }
    else if (mitk::FloatProperty *floatProperty = dynamic_cast<mitk::FloatProperty *>(property))
    {
      if (role == Qt::DisplayRole || role == Qt::EditRole)
        return floatProperty->GetValue();
    }
    else if (mitk::DoubleProperty *doubleProperty = dynamic_cast<mitk::DoubleProperty *>(property))
    {
      if (role == Qt::DisplayRole || role == Qt::EditRole)
        return doubleProperty->GetValue();
    }
    else if (mitk::EnumerationProperty *enumProperty = dynamic_cast<mitk::EnumerationProperty *>(property))
    {
      if (role == Qt::DisplayRole)
      {
        return QString::fromStdString(enumProperty->GetValueAsString());
      }
      else if (role == Qt::EditRole)
      {
        QStringList values;

        for (mitk::EnumerationProperty::EnumConstIterator iter = enumProperty->Begin(); iter != enumProperty->End(); ++iter)
          values << QString::fromStdString(iter->second);

        return QVariant(values);
      }
    }
    else
    {
      if (role == Qt::DisplayRole)
        return QString::fromStdString(property->GetValueAsString());
    }
  }

  return QVariant();
}

Qt::ItemFlags QmitkPropertyTreeModel::flags(const QModelIndex &index) const
{
  Qt::ItemFlags flags = QAbstractItemModel::flags(index);

  if (index.column() == 1)
  {
    if (index.data(Qt::EditRole).isValid())
      flags |= Qt::ItemIsEditable;

    if (index.data(Qt::CheckStateRole).isValid())
      flags |= Qt::ItemIsUserCheckable;
  }

  return flags;
}

QVariant QmitkPropertyTreeModel::headerData(int section, Qt::Orientation orientation, int role) const
{
  if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
    return m_RootItem->GetData(section);

  return QVariant();
}

QModelIndex QmitkPropertyTreeModel::index(int row, int column, const QModelIndex &parent) const
{
  if (!hasIndex(row, column, parent))
    return QModelIndex();

  QmitkPropertyTreeItem *parentItem = parent.isValid() ? static_cast<QmitkPropertyTreeItem *>(parent.internalPointer()) : m_RootItem;
  QmitkPropertyTreeItem *childItem = parentItem->GetChild(row);

  if (childItem != NULL)
    return createIndex(row, column, childItem);
  else
    return QModelIndex();
}

QModelIndex QmitkPropertyTreeModel::parent(const QModelIndex &child) const
{
  if (!child.isValid())
    return QModelIndex();

  QmitkPropertyTreeItem *parentItem = static_cast<QmitkPropertyTreeItem *>(child.internalPointer())->GetParent();

  if (parentItem == m_RootItem)
    return QModelIndex();

  return createIndex(parentItem->GetRow(), 0, parentItem);
}

int QmitkPropertyTreeModel::rowCount(const QModelIndex &parent) const
{
  if (parent.column() > 0)
    return 0;

  QmitkPropertyTreeItem *parentItem = parent.isValid() ? static_cast<QmitkPropertyTreeItem *>(parent.internalPointer()) : m_RootItem;

  return parentItem->GetChildCount();
}

bool QmitkPropertyTreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
  if (index.isValid() && (role == Qt::EditRole || role == Qt::CheckStateRole))
  {
    if (index.column() == 1)
    {
      mitk::BaseProperty *property = reinterpret_cast<mitk::BaseProperty *>(static_cast<QmitkPropertyTreeItem *>(index.internalPointer())->GetData(index.column()).value<void *>());

      if (mitk::ColorProperty *colorProperty = dynamic_cast<mitk::ColorProperty *>(property))
      {
        QColor qtColor = value.value<QColor>();

        if (!qtColor.isValid())
          return false;

        mitk::Color mitkColor = colorProperty->GetColor();
        mitkColor.SetRed(qtColor.red() / 255.0);
        mitkColor.SetGreen(qtColor.green() / 255.0);
        mitkColor.SetBlue(qtColor.blue() / 255.0);
        colorProperty->SetColor(mitkColor);

        m_Properties->InvokeEvent(itk::ModifiedEvent());
        m_Properties->Modified();

        mitk::RenderingManager::GetInstance()->RequestUpdateAll();
      }
      else if (mitk::BoolProperty *boolProperty = dynamic_cast<mitk::BoolProperty *>(property))
      {
        boolProperty->SetValue(value.toInt() == Qt::Checked ? true : false);

        m_Properties->InvokeEvent(itk::ModifiedEvent());
        m_Properties->Modified();

        mitk::RenderingManager::GetInstance()->RequestUpdateAll();
      }
      else if (mitk::StringProperty *stringProperty = dynamic_cast<mitk::StringProperty *>(property))
      {
        stringProperty->SetValue(value.toString().toStdString());

        m_Properties->InvokeEvent(itk::ModifiedEvent());
        m_Properties->Modified();

        mitk::RenderingManager::GetInstance()->RequestUpdateAll();
      }
      else if (mitk::IntProperty *intProperty = dynamic_cast<mitk::IntProperty *>(property))
      {
        int intValue = value.toInt();

        if (intValue != intProperty->GetValue())
        {
          intProperty->SetValue(intValue);
          m_Properties->InvokeEvent(itk::ModifiedEvent());
          m_Properties->Modified();

          mitk::RenderingManager::GetInstance()->RequestUpdateAll();
        }
      }
      else if (mitk::FloatProperty *floatProperty = dynamic_cast<mitk::FloatProperty *>(property))
      {
        int floatValue = value.toFloat();

        if (floatValue != floatProperty->GetValue())
        {
          floatProperty->SetValue(floatValue);
          m_Properties->InvokeEvent(itk::ModifiedEvent());
          m_Properties->Modified();

          mitk::RenderingManager::GetInstance()->RequestUpdateAll();
        }
      }
      else if (mitk::EnumerationProperty *enumProperty = dynamic_cast<mitk::EnumerationProperty *>(property))
      {
        std::string activatedItem = value.toString().toStdString();

        if (activatedItem != enumProperty->GetValueAsString())
        {
          enumProperty->SetValue(activatedItem);
          m_Properties->InvokeEvent(itk::ModifiedEvent());
          m_Properties->Modified();

          mitk::RenderingManager::GetInstance()->RequestUpdateAll();
        }
      }
    }

    emit dataChanged(index, index);
    return true;
  }

  return false;
}
<commit_msg>Fixed accidental type conversion and enhanced float comparison.<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "QmitkPropertyTreeItem.h"
#include "QmitkPropertyTreeModel.h"
#include <mitkProperties.h>
#include <mitkColorProperty.h>
#include <mitkEnumerationProperty.h>
#include <mitkStringProperty.h>
#include <mitkRenderingManager.h>
#include <QColor>

QmitkPropertyTreeModel::QmitkPropertyTreeModel(QObject *parent)
: QAbstractItemModel(parent),
  m_Properties(NULL),
  m_RootItem(NULL)
{
  CreateRootItem();
}

void QmitkPropertyTreeModel::SetProperties(mitk::PropertyList *properties)
{
  if (properties == m_Properties)
    return;

  beginResetModel();

  if (m_RootItem != NULL)
  {
    delete m_RootItem;
    m_RootItem = NULL;
    m_Properties = NULL;
  }

  CreateRootItem();

  if (properties != NULL && !properties->IsEmpty())
  {
    m_Properties = properties;

    std::map<std::string, mitk::BaseProperty::Pointer>::const_iterator end = properties->GetMap()->end();

    for (std::map<std::string, mitk::BaseProperty::Pointer>::const_iterator iter = properties->GetMap()->begin(); iter != end; ++iter)
    {
      QList<QVariant> data;
      data << iter->first.c_str() << QVariant::fromValue<void *>((reinterpret_cast<void *>(iter->second.GetPointer())));
      m_RootItem->AppendChild(new QmitkPropertyTreeItem(data));
    }
  }

  endResetModel();
}

void QmitkPropertyTreeModel::CreateRootItem()
{
  if (m_RootItem == NULL)
  {
    QList<QVariant> rootData;
    rootData << "Property" << "Value";
    m_RootItem = new QmitkPropertyTreeItem(rootData);
  }
}

QmitkPropertyTreeModel::~QmitkPropertyTreeModel()
{
  delete m_RootItem;
}

int QmitkPropertyTreeModel::columnCount(const QModelIndex &parent) const
{
  if (parent.isValid())
    return static_cast<QmitkPropertyTreeItem *>(parent.internalPointer())->GetColumnCount();
  else
    return m_RootItem->GetColumnCount();
}

QVariant QmitkPropertyTreeModel::data(const QModelIndex &index, int role) const
{
  if (!index.isValid())
    return QVariant();

  if (index.column() == 0 && role == Qt::DisplayRole)
    return static_cast<QmitkPropertyTreeItem *>(index.internalPointer())->GetData(index.column());

  if (index.column() == 1 && static_cast<QmitkPropertyTreeItem *>(index.internalPointer())->GetData(index.column()).isValid())
  {
    mitk::BaseProperty *property = reinterpret_cast<mitk::BaseProperty *>(static_cast<QmitkPropertyTreeItem *>(index.internalPointer())->GetData(index.column()).value<void *>());

    if (mitk::ColorProperty *colorProperty = dynamic_cast<mitk::ColorProperty *>(property))
    {
      if (role == Qt::DisplayRole || role == Qt::EditRole)
      {
        mitk::Color mitkColor = colorProperty->GetColor();
        QColor qtColor(static_cast<int>(mitkColor.GetRed() * 255), static_cast<int>(mitkColor.GetGreen() * 255), static_cast<int>(mitkColor.GetBlue() * 255));
        return QVariant::fromValue<QColor>(qtColor);
      }
    }
    else if (mitk::BoolProperty *boolProperty = dynamic_cast<mitk::BoolProperty *>(property))
    {
      if (role == Qt::CheckStateRole)
        return boolProperty->GetValue() ? Qt::Checked : Qt::Unchecked;
    }
    else if (mitk::StringProperty *stringProperty = dynamic_cast<mitk::StringProperty *>(property))
    {
      if (role == Qt::DisplayRole || role == Qt::EditRole)
        return QString(stringProperty->GetValue());
    }
    else if (mitk::IntProperty *intProperty = dynamic_cast<mitk::IntProperty *>(property))
    {
      if (role == Qt::DisplayRole || role == Qt::EditRole)
        return intProperty->GetValue();
    }
    else if (mitk::FloatProperty *floatProperty = dynamic_cast<mitk::FloatProperty *>(property))
    {
      if (role == Qt::DisplayRole || role == Qt::EditRole)
        return floatProperty->GetValue();
    }
    else if (mitk::DoubleProperty *doubleProperty = dynamic_cast<mitk::DoubleProperty *>(property))
    {
      if (role == Qt::DisplayRole || role == Qt::EditRole)
        return doubleProperty->GetValue();
    }
    else if (mitk::EnumerationProperty *enumProperty = dynamic_cast<mitk::EnumerationProperty *>(property))
    {
      if (role == Qt::DisplayRole)
      {
        return QString::fromStdString(enumProperty->GetValueAsString());
      }
      else if (role == Qt::EditRole)
      {
        QStringList values;

        for (mitk::EnumerationProperty::EnumConstIterator iter = enumProperty->Begin(); iter != enumProperty->End(); ++iter)
          values << QString::fromStdString(iter->second);

        return QVariant(values);
      }
    }
    else
    {
      if (role == Qt::DisplayRole)
        return QString::fromStdString(property->GetValueAsString());
    }
  }

  return QVariant();
}

Qt::ItemFlags QmitkPropertyTreeModel::flags(const QModelIndex &index) const
{
  Qt::ItemFlags flags = QAbstractItemModel::flags(index);

  if (index.column() == 1)
  {
    if (index.data(Qt::EditRole).isValid())
      flags |= Qt::ItemIsEditable;

    if (index.data(Qt::CheckStateRole).isValid())
      flags |= Qt::ItemIsUserCheckable;
  }

  return flags;
}

QVariant QmitkPropertyTreeModel::headerData(int section, Qt::Orientation orientation, int role) const
{
  if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
    return m_RootItem->GetData(section);

  return QVariant();
}

QModelIndex QmitkPropertyTreeModel::index(int row, int column, const QModelIndex &parent) const
{
  if (!hasIndex(row, column, parent))
    return QModelIndex();

  QmitkPropertyTreeItem *parentItem = parent.isValid() ? static_cast<QmitkPropertyTreeItem *>(parent.internalPointer()) : m_RootItem;
  QmitkPropertyTreeItem *childItem = parentItem->GetChild(row);

  if (childItem != NULL)
    return createIndex(row, column, childItem);
  else
    return QModelIndex();
}

QModelIndex QmitkPropertyTreeModel::parent(const QModelIndex &child) const
{
  if (!child.isValid())
    return QModelIndex();

  QmitkPropertyTreeItem *parentItem = static_cast<QmitkPropertyTreeItem *>(child.internalPointer())->GetParent();

  if (parentItem == m_RootItem)
    return QModelIndex();

  return createIndex(parentItem->GetRow(), 0, parentItem);
}

int QmitkPropertyTreeModel::rowCount(const QModelIndex &parent) const
{
  if (parent.column() > 0)
    return 0;

  QmitkPropertyTreeItem *parentItem = parent.isValid() ? static_cast<QmitkPropertyTreeItem *>(parent.internalPointer()) : m_RootItem;

  return parentItem->GetChildCount();
}

bool QmitkPropertyTreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
  if (index.isValid() && (role == Qt::EditRole || role == Qt::CheckStateRole))
  {
    if (index.column() == 1)
    {
      mitk::BaseProperty *property = reinterpret_cast<mitk::BaseProperty *>(static_cast<QmitkPropertyTreeItem *>(index.internalPointer())->GetData(index.column()).value<void *>());

      if (mitk::ColorProperty *colorProperty = dynamic_cast<mitk::ColorProperty *>(property))
      {
        QColor qtColor = value.value<QColor>();

        if (!qtColor.isValid())
          return false;

        mitk::Color mitkColor = colorProperty->GetColor();
        mitkColor.SetRed(qtColor.red() / 255.0);
        mitkColor.SetGreen(qtColor.green() / 255.0);
        mitkColor.SetBlue(qtColor.blue() / 255.0);
        colorProperty->SetColor(mitkColor);

        m_Properties->InvokeEvent(itk::ModifiedEvent());
        m_Properties->Modified();

        mitk::RenderingManager::GetInstance()->RequestUpdateAll();
      }
      else if (mitk::BoolProperty *boolProperty = dynamic_cast<mitk::BoolProperty *>(property))
      {
        boolProperty->SetValue(value.toInt() == Qt::Checked ? true : false);

        m_Properties->InvokeEvent(itk::ModifiedEvent());
        m_Properties->Modified();

        mitk::RenderingManager::GetInstance()->RequestUpdateAll();
      }
      else if (mitk::StringProperty *stringProperty = dynamic_cast<mitk::StringProperty *>(property))
      {
        stringProperty->SetValue(value.toString().toStdString());

        m_Properties->InvokeEvent(itk::ModifiedEvent());
        m_Properties->Modified();

        mitk::RenderingManager::GetInstance()->RequestUpdateAll();
      }
      else if (mitk::IntProperty *intProperty = dynamic_cast<mitk::IntProperty *>(property))
      {
        int intValue = value.toInt();

        if (intValue != intProperty->GetValue())
        {
          intProperty->SetValue(intValue);
          m_Properties->InvokeEvent(itk::ModifiedEvent());
          m_Properties->Modified();

          mitk::RenderingManager::GetInstance()->RequestUpdateAll();
        }
      }
      else if (mitk::FloatProperty *floatProperty = dynamic_cast<mitk::FloatProperty *>(property))
      {
        float floatValue = value.toFloat();

        if (abs(floatValue - floatProperty->GetValue()) >= mitk::eps)
        {
          floatProperty->SetValue(floatValue);
          m_Properties->InvokeEvent(itk::ModifiedEvent());
          m_Properties->Modified();

          mitk::RenderingManager::GetInstance()->RequestUpdateAll();
        }
      }
      else if (mitk::EnumerationProperty *enumProperty = dynamic_cast<mitk::EnumerationProperty *>(property))
      {
        std::string activatedItem = value.toString().toStdString();

        if (activatedItem != enumProperty->GetValueAsString())
        {
          enumProperty->SetValue(activatedItem);
          m_Properties->InvokeEvent(itk::ModifiedEvent());
          m_Properties->Modified();

          mitk::RenderingManager::GetInstance()->RequestUpdateAll();
        }
      }
    }

    emit dataChanged(index, index);
    return true;
  }

  return false;
}
<|endoftext|>


<commit_before>/*
 -----------------------------------------------------------------------------
 This source file is part of OGRE
 (Object-oriented Graphics Rendering Engine)
 For the latest info, see http://www.ogre3d.org/

 Copyright (c) 2000-2013 Torus Knot Software Ltd

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 -----------------------------------------------------------------------------
 */

#include "OgreStableHeaders.h"
#include "OgreGLES2StateCacheManagerImp.h"
#include "OgreGLES2RenderSystem.h"
#include "OgreLogManager.h"
#include "OgreRoot.h"

namespace Ogre {

    GLES2StateCacheManagerImp::GLES2StateCacheManagerImp(void)
    {
        clearCache();
    }

    void GLES2StateCacheManagerImp::initializeCache()
    {
        OGRE_CHECK_GL_ERROR(glBlendEquation(GL_FUNC_ADD));

        OGRE_CHECK_GL_ERROR(glBlendFunc(GL_ONE, GL_ZERO));

        OGRE_CHECK_GL_ERROR(glCullFace(mCullFace));

        OGRE_CHECK_GL_ERROR(glDepthFunc(mDepthFunc));

        OGRE_CHECK_GL_ERROR(glDepthMask(mDepthMask));

        OGRE_CHECK_GL_ERROR(glStencilMask(mStencilMask));

        OGRE_CHECK_GL_ERROR(glClearDepthf(mClearDepth));

        OGRE_CHECK_GL_ERROR(glBindTexture(GL_TEXTURE_2D, 0));

        OGRE_CHECK_GL_ERROR(glBindBuffer(GL_ARRAY_BUFFER, 0));

        OGRE_CHECK_GL_ERROR(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));

        OGRE_CHECK_GL_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, 0));

        OGRE_CHECK_GL_ERROR(glBindRenderbuffer(GL_RENDERBUFFER, 0));

        OGRE_CHECK_GL_ERROR(glActiveTexture(GL_TEXTURE0));

        OGRE_CHECK_GL_ERROR(glClearColor(mClearColour[0], mClearColour[1], mClearColour[2], mClearColour[3]));

        OGRE_CHECK_GL_ERROR(glColorMask(mColourMask[0], mColourMask[1], mColourMask[2], mColourMask[3]));
    }

    void GLES2StateCacheManagerImp::clearCache()
    {
        mDepthMask = GL_TRUE;
        mPolygonMode = GL_FILL;
        mBlendEquation = GL_FUNC_ADD;
        mCullFace = GL_BACK;
        mDepthFunc = GL_LESS;
        mStencilMask = 0xFFFFFFFF;
        mActiveTextureUnit = 0;
        mDiscardBuffers = 0;
        mClearDepth = 1.0f;
        mLastBoundTexID = 0;

        // Initialize our cache variables and also the GL so that the
        // stored values match the GL state
        mBlendFuncSource = GL_ONE;
        mBlendFuncDest = GL_ZERO;

        mClearColour.resize(4);
        mClearColour[0] = mClearColour[1] = mClearColour[2] = mClearColour[3] = 0.0f;

        mColourMask.resize(4);
        mColourMask[0] = mColourMask[1] = mColourMask[2] = mColourMask[3] = GL_TRUE;

        mEnableVector.reserve(25);
        mEnableVector.clear();
        mActiveBufferMap.clear();
        mTexUnitsMap.clear();

        mEnableVector.reserve(64);
        mEnabledVertexAttribs.clear();
    }

    GLES2StateCacheManagerImp::~GLES2StateCacheManagerImp(void)
    {
        mColourMask.clear();
        mClearColour.clear();
        mActiveBufferMap.clear();
        mEnableVector.clear();
        mTexUnitsMap.clear();
    }

    void GLES2StateCacheManagerImp::bindGLBuffer(GLenum target, GLuint buffer, GLenum attach, bool force)
    {
		bool update = false;
        BindBufferMap::iterator i = mActiveBufferMap.find(target);
        if (i == mActiveBufferMap.end())
        {
            // Haven't cached this state yet.  Insert it into the map
            mActiveBufferMap.insert(BindBufferMap::value_type(target, buffer));
			update = true;
        }
        else if((*i).second != buffer || force) // Update the cached value if needed
        {
			(*i).second = buffer;
			update = true;
        }

		// Update GL
		if(update)
		{
            if(target == GL_FRAMEBUFFER)
            {
                OGRE_CHECK_GL_ERROR(glBindFramebuffer(target, buffer));
            }
            else if(target == GL_RENDERBUFFER)
            {
                OGRE_CHECK_GL_ERROR(glBindRenderbuffer(target, buffer));
            }
            else
            {
                OGRE_CHECK_GL_ERROR(glBindBuffer(target, buffer));
            }
		}
    }

    void GLES2StateCacheManagerImp::deleteGLBuffer(GLenum target, GLuint buffer, GLenum attach, bool force)
    {
        // Buffer name 0 is reserved and we should never try to delete it
        if(buffer == 0)
            return;

        BindBufferMap::iterator i = mActiveBufferMap.find(target);

        if (i != mActiveBufferMap.end() && ((*i).second == buffer || force))
        {
			if(target == GL_FRAMEBUFFER)
            {
				OGRE_CHECK_GL_ERROR(glDeleteFramebuffers(1, &buffer));
            }
            else if(target == GL_RENDERBUFFER)
            {
				OGRE_CHECK_GL_ERROR(glDeleteRenderbuffers(1, &buffer));
            }
            else
            {
				OGRE_CHECK_GL_ERROR(glDeleteBuffers(1, &buffer));
            }

            // Currently bound buffer is being deleted, update the cached value to 0,
            // which it likely the buffer that will be bound by the driver.
            // An update will be forced next time we try to bind on this target.
            (*i).second = 0;
        }
    }

    void GLES2StateCacheManagerImp::invalidateStateForTexture(GLuint texture)
    {
        TexUnitsMap::iterator it = mTexUnitsMap.find(texture);
        mTexUnitsMap.erase(it);
    }

    // TODO: Store as high/low bits of a GLuint, use vector instead of map for TexParameteriMap
    void GLES2StateCacheManagerImp::setTexParameteri(GLenum target, GLenum pname, GLint param)
    {
        // Check if we have a map entry for this texture id. If not, create a blank one and insert it.
        TexUnitsMap::iterator it = mTexUnitsMap.find(mLastBoundTexID);
        if (it == mTexUnitsMap.end())
        {
            TextureUnitParams unit;
            mTexUnitsMap[mLastBoundTexID] = unit;

            // Update the iterator
            it = mTexUnitsMap.find(mLastBoundTexID);
        }

        // Get a local copy of the parameter map and search for this parameter
        TexParameteriMap &myMap = (*it).second.mTexParameteriMap;
        TexParameteriMap::iterator i = myMap.find(pname);

        if (i == myMap.end())
        {
            // Haven't cached this state yet.  Insert it into the map
            myMap.insert(TexParameteriMap::value_type(pname, param));

            // Update GL
            OGRE_CHECK_GL_ERROR(glTexParameteri(target, pname, param));
        }
        else
        {
            // Update the cached value if needed
            if((*i).second != param)
            {
                (*i).second = param;

                // Update GL
                OGRE_CHECK_GL_ERROR(glTexParameteri(target, pname, param));
            }
        }
    }

    void GLES2StateCacheManagerImp::setTexParameterf(GLenum target, GLenum pname, GLfloat param)
    {
        // Check if we have a map entry for this texture id. If not, create a blank one and insert it.
        TexUnitsMap::iterator it = mTexUnitsMap.find(mLastBoundTexID);
        if (it == mTexUnitsMap.end())
        {
            TextureUnitParams unit;
            mTexUnitsMap[mLastBoundTexID] = unit;

            // Update the iterator
            it = mTexUnitsMap.find(mLastBoundTexID);
        }

        // Get a local copy of the parameter map and search for this parameter
        TexParameterfMap &myMap = (*it).second.mTexParameterfMap;
        TexParameterfMap::iterator i = myMap.find(pname);

        if (i == myMap.end())
        {
            // Haven't cached this state yet.  Insert it into the map
            myMap.insert(TexParameterfMap::value_type(pname, param));

            // Update GL
            OGRE_CHECK_GL_ERROR(glTexParameterf(target, pname, param));
        }
        else
        {
            // Update the cached value if needed
            if((*i).second != param)
            {
                (*i).second = param;

                // Update GL
                OGRE_CHECK_GL_ERROR(glTexParameterf(target, pname, param));
            }
        }
    }

    void GLES2StateCacheManagerImp::getTexParameterfv(GLenum target, GLenum pname, GLfloat *params)
    {
        // Check if we have a map entry for this texture id.
        TexUnitsMap::iterator it = mTexUnitsMap.find(mLastBoundTexID);

        // Get a local copy of the parameter map and search for this parameter
        TexParameterfMap::iterator i = (*it).second.mTexParameterfMap.find(pname);

        params = &(*i).second;
    }

    void GLES2StateCacheManagerImp::bindGLTexture(GLenum target, GLuint texture)
    {
        mLastBoundTexID = texture;

        // Update GL
        OGRE_CHECK_GL_ERROR(glBindTexture(target, texture));
    }

    bool GLES2StateCacheManagerImp::activateGLTextureUnit(size_t unit)
	{
		if (mActiveTextureUnit != unit)
		{
			if (unit < dynamic_cast<GLES2RenderSystem*>(Root::getSingleton().getRenderSystem())->getCapabilities()->getNumTextureUnits())
			{
				OGRE_CHECK_GL_ERROR(glActiveTexture(GL_TEXTURE0 + unit));
				mActiveTextureUnit = unit;
				return true;
			}
			else if (!unit)
			{
				// always ok to use the first unit
				return true;
			}
			else
			{
				return false;
			}
		}
		else
		{
			return true;
		}
	}

    // TODO: Store as high/low bits of a GLuint
    void GLES2StateCacheManagerImp::setBlendFunc(GLenum source, GLenum dest)
    {
        if(mBlendFuncSource != source || mBlendFuncDest != dest)
        {
            mBlendFuncSource = source;
            mBlendFuncDest = dest;

            OGRE_CHECK_GL_ERROR(glBlendFunc(source, dest));
        }
    }

    void GLES2StateCacheManagerImp::setBlendEquation(GLenum eq)
    {
        if(mBlendEquation != eq)
        {
            mBlendEquation = eq;

            OGRE_CHECK_GL_ERROR(glBlendEquation(eq));
        }
    }

    void GLES2StateCacheManagerImp::setDepthMask(GLboolean mask)
    {
        if(mDepthMask != mask)
        {
            mDepthMask = mask;

            OGRE_CHECK_GL_ERROR(glDepthMask(mask));
        }
    }

    void GLES2StateCacheManagerImp::setDepthFunc(GLenum func)
    {
        if(mDepthFunc != func)
        {
            mDepthFunc = func;

            OGRE_CHECK_GL_ERROR(glDepthFunc(func));
        }
    }

    void GLES2StateCacheManagerImp::setClearDepth(GLclampf depth)
    {
        if(mClearDepth != depth)
        {
            mClearDepth = depth;

            OGRE_CHECK_GL_ERROR(glClearDepthf(depth));
        }
    }

    void GLES2StateCacheManagerImp::setClearColour(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
    {
        if((mClearColour[0] != red) ||
           (mClearColour[1] != green) ||
           (mClearColour[2] != blue) ||
           (mClearColour[3] != alpha))
        {
            mClearColour[0] = red;
            mClearColour[1] = green;
            mClearColour[2] = blue;
            mClearColour[3] = alpha;

            OGRE_CHECK_GL_ERROR(glClearColor(mClearColour[0], mClearColour[1], mClearColour[2], mClearColour[3]));
        }
    }

    void GLES2StateCacheManagerImp::setColourMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
    {
        if((mColourMask[0] != red) ||
           (mColourMask[1] != green) ||
           (mColourMask[2] != blue) ||
           (mColourMask[3] != alpha))
        {
            mColourMask[0] = red;
            mColourMask[1] = green;
            mColourMask[2] = blue;
            mColourMask[3] = alpha;

            OGRE_CHECK_GL_ERROR(glColorMask(mColourMask[0], mColourMask[1], mColourMask[2], mColourMask[3]));
        }
    }

    void GLES2StateCacheManagerImp::setStencilMask(GLuint mask)
    {
        if(mStencilMask != mask)
        {
            mStencilMask = mask;

            OGRE_CHECK_GL_ERROR(glStencilMask(mask));
        }
    }

    void GLES2StateCacheManagerImp::setEnabled(GLenum flag)
    {
        bool found = std::find(mEnableVector.begin(), mEnableVector.end(), flag) != mEnableVector.end();
        if(!found)
        {
            mEnableVector.push_back(flag);

            OGRE_CHECK_GL_ERROR(glEnable(flag));
        }
    }

    void GLES2StateCacheManagerImp::setDisabled(GLenum flag)
    {
        vector<GLenum>::iterator iter = std::find(mEnableVector.begin(), mEnableVector.end(), flag);
        if(iter != mEnableVector.end())
        {
            mEnableVector.erase(iter);

            OGRE_CHECK_GL_ERROR(glDisable(flag));
        }
    }

    void GLES2StateCacheManagerImp::setVertexAttribEnabled(GLuint attrib)
    {
        bool found = std::find(mEnabledVertexAttribs.begin(), mEnabledVertexAttribs.end(), attrib) != mEnabledVertexAttribs.end();
        if(!found)
        {
            mEnabledVertexAttribs.push_back(attrib);

            OGRE_CHECK_GL_ERROR(glEnableVertexAttribArray(attrib));
        }
    }

    void GLES2StateCacheManagerImp::setVertexAttribDisabled(GLuint attrib)
    {
        vector<GLuint>::iterator iter = std::find(mEnabledVertexAttribs.begin(), mEnabledVertexAttribs.end(), attrib);
        if(iter != mEnabledVertexAttribs.end())
        {
            mEnabledVertexAttribs.erase(iter);

            OGRE_CHECK_GL_ERROR(glDisableVertexAttribArray(attrib));
        }
    }

    void GLES2StateCacheManagerImp::setCullFace(GLenum face)
    {
        if(mCullFace != face)
        {
            mCullFace = face;

            OGRE_CHECK_GL_ERROR(glCullFace(face));
        }
    }
}
<commit_msg>[OGRE-300] Apply GL state cache crash fix to GLES2 state cache.<commit_after>/*
 -----------------------------------------------------------------------------
 This source file is part of OGRE
 (Object-oriented Graphics Rendering Engine)
 For the latest info, see http://www.ogre3d.org/

 Copyright (c) 2000-2013 Torus Knot Software Ltd

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 -----------------------------------------------------------------------------
 */

#include "OgreStableHeaders.h"
#include "OgreGLES2StateCacheManagerImp.h"
#include "OgreGLES2RenderSystem.h"
#include "OgreLogManager.h"
#include "OgreRoot.h"

namespace Ogre {

    GLES2StateCacheManagerImp::GLES2StateCacheManagerImp(void)
    {
        clearCache();
    }

    void GLES2StateCacheManagerImp::initializeCache()
    {
        OGRE_CHECK_GL_ERROR(glBlendEquation(GL_FUNC_ADD));

        OGRE_CHECK_GL_ERROR(glBlendFunc(GL_ONE, GL_ZERO));

        OGRE_CHECK_GL_ERROR(glCullFace(mCullFace));

        OGRE_CHECK_GL_ERROR(glDepthFunc(mDepthFunc));

        OGRE_CHECK_GL_ERROR(glDepthMask(mDepthMask));

        OGRE_CHECK_GL_ERROR(glStencilMask(mStencilMask));

        OGRE_CHECK_GL_ERROR(glClearDepthf(mClearDepth));

        OGRE_CHECK_GL_ERROR(glBindTexture(GL_TEXTURE_2D, 0));

        OGRE_CHECK_GL_ERROR(glBindBuffer(GL_ARRAY_BUFFER, 0));

        OGRE_CHECK_GL_ERROR(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));

        OGRE_CHECK_GL_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, 0));

        OGRE_CHECK_GL_ERROR(glBindRenderbuffer(GL_RENDERBUFFER, 0));

        OGRE_CHECK_GL_ERROR(glActiveTexture(GL_TEXTURE0));

        OGRE_CHECK_GL_ERROR(glClearColor(mClearColour[0], mClearColour[1], mClearColour[2], mClearColour[3]));

        OGRE_CHECK_GL_ERROR(glColorMask(mColourMask[0], mColourMask[1], mColourMask[2], mColourMask[3]));
    }

    void GLES2StateCacheManagerImp::clearCache()
    {
        mDepthMask = GL_TRUE;
        mPolygonMode = GL_FILL;
        mBlendEquation = GL_FUNC_ADD;
        mCullFace = GL_BACK;
        mDepthFunc = GL_LESS;
        mStencilMask = 0xFFFFFFFF;
        mActiveTextureUnit = 0;
        mDiscardBuffers = 0;
        mClearDepth = 1.0f;
        mLastBoundTexID = 0;

        // Initialize our cache variables and also the GL so that the
        // stored values match the GL state
        mBlendFuncSource = GL_ONE;
        mBlendFuncDest = GL_ZERO;

        mClearColour.resize(4);
        mClearColour[0] = mClearColour[1] = mClearColour[2] = mClearColour[3] = 0.0f;

        mColourMask.resize(4);
        mColourMask[0] = mColourMask[1] = mColourMask[2] = mColourMask[3] = GL_TRUE;

        mEnableVector.reserve(25);
        mEnableVector.clear();
        mActiveBufferMap.clear();
        mTexUnitsMap.clear();

        mEnableVector.reserve(64);
        mEnabledVertexAttribs.clear();
    }

    GLES2StateCacheManagerImp::~GLES2StateCacheManagerImp(void)
    {
        mColourMask.clear();
        mClearColour.clear();
        mActiveBufferMap.clear();
        mEnableVector.clear();
        mTexUnitsMap.clear();
    }

    void GLES2StateCacheManagerImp::bindGLBuffer(GLenum target, GLuint buffer, GLenum attach, bool force)
    {
		bool update = false;
        BindBufferMap::iterator i = mActiveBufferMap.find(target);
        if (i == mActiveBufferMap.end())
        {
            // Haven't cached this state yet.  Insert it into the map
            mActiveBufferMap.insert(BindBufferMap::value_type(target, buffer));
			update = true;
        }
        else if((*i).second != buffer || force) // Update the cached value if needed
        {
			(*i).second = buffer;
			update = true;
        }

		// Update GL
		if(update)
		{
            if(target == GL_FRAMEBUFFER)
            {
                OGRE_CHECK_GL_ERROR(glBindFramebuffer(target, buffer));
            }
            else if(target == GL_RENDERBUFFER)
            {
                OGRE_CHECK_GL_ERROR(glBindRenderbuffer(target, buffer));
            }
            else
            {
                OGRE_CHECK_GL_ERROR(glBindBuffer(target, buffer));
            }
		}
    }

    void GLES2StateCacheManagerImp::deleteGLBuffer(GLenum target, GLuint buffer, GLenum attach, bool force)
    {
        // Buffer name 0 is reserved and we should never try to delete it
        if(buffer == 0)
            return;

        BindBufferMap::iterator i = mActiveBufferMap.find(target);

        if (i != mActiveBufferMap.end() && ((*i).second == buffer || force))
        {
			if(target == GL_FRAMEBUFFER)
            {
				OGRE_CHECK_GL_ERROR(glDeleteFramebuffers(1, &buffer));
            }
            else if(target == GL_RENDERBUFFER)
            {
				OGRE_CHECK_GL_ERROR(glDeleteRenderbuffers(1, &buffer));
            }
            else
            {
				OGRE_CHECK_GL_ERROR(glDeleteBuffers(1, &buffer));
            }

            // Currently bound buffer is being deleted, update the cached value to 0,
            // which it likely the buffer that will be bound by the driver.
            // An update will be forced next time we try to bind on this target.
            (*i).second = 0;
        }
    }

    void GLES2StateCacheManagerImp::invalidateStateForTexture(GLuint texture)
    {
        mTexUnitsMap.erase(texture);
    }

    // TODO: Store as high/low bits of a GLuint, use vector instead of map for TexParameteriMap
    void GLES2StateCacheManagerImp::setTexParameteri(GLenum target, GLenum pname, GLint param)
    {
        // Check if we have a map entry for this texture id. If not, create a blank one and insert it.
        TexUnitsMap::iterator it = mTexUnitsMap.find(mLastBoundTexID);
        if (it == mTexUnitsMap.end())
        {
            TextureUnitParams unit;
            mTexUnitsMap[mLastBoundTexID] = unit;

            // Update the iterator
            it = mTexUnitsMap.find(mLastBoundTexID);
        }

        // Get a local copy of the parameter map and search for this parameter
        TexParameteriMap &myMap = (*it).second.mTexParameteriMap;
        TexParameteriMap::iterator i = myMap.find(pname);

        if (i == myMap.end())
        {
            // Haven't cached this state yet.  Insert it into the map
            myMap.insert(TexParameteriMap::value_type(pname, param));

            // Update GL
            OGRE_CHECK_GL_ERROR(glTexParameteri(target, pname, param));
        }
        else
        {
            // Update the cached value if needed
            if((*i).second != param)
            {
                (*i).second = param;

                // Update GL
                OGRE_CHECK_GL_ERROR(glTexParameteri(target, pname, param));
            }
        }
    }

    void GLES2StateCacheManagerImp::setTexParameterf(GLenum target, GLenum pname, GLfloat param)
    {
        // Check if we have a map entry for this texture id. If not, create a blank one and insert it.
        TexUnitsMap::iterator it = mTexUnitsMap.find(mLastBoundTexID);
        if (it == mTexUnitsMap.end())
        {
            TextureUnitParams unit;
            mTexUnitsMap[mLastBoundTexID] = unit;

            // Update the iterator
            it = mTexUnitsMap.find(mLastBoundTexID);
        }

        // Get a local copy of the parameter map and search for this parameter
        TexParameterfMap &myMap = (*it).second.mTexParameterfMap;
        TexParameterfMap::iterator i = myMap.find(pname);

        if (i == myMap.end())
        {
            // Haven't cached this state yet.  Insert it into the map
            myMap.insert(TexParameterfMap::value_type(pname, param));

            // Update GL
            OGRE_CHECK_GL_ERROR(glTexParameterf(target, pname, param));
        }
        else
        {
            // Update the cached value if needed
            if((*i).second != param)
            {
                (*i).second = param;

                // Update GL
                OGRE_CHECK_GL_ERROR(glTexParameterf(target, pname, param));
            }
        }
    }

    void GLES2StateCacheManagerImp::getTexParameterfv(GLenum target, GLenum pname, GLfloat *params)
    {
        // Check if we have a map entry for this texture id.
        TexUnitsMap::iterator it = mTexUnitsMap.find(mLastBoundTexID);

        // Get a local copy of the parameter map and search for this parameter
        TexParameterfMap::iterator i = (*it).second.mTexParameterfMap.find(pname);

        params = &(*i).second;
    }

    void GLES2StateCacheManagerImp::bindGLTexture(GLenum target, GLuint texture)
    {
        mLastBoundTexID = texture;

        // Update GL
        OGRE_CHECK_GL_ERROR(glBindTexture(target, texture));
    }

    bool GLES2StateCacheManagerImp::activateGLTextureUnit(size_t unit)
	{
		if (mActiveTextureUnit != unit)
		{
			if (unit < dynamic_cast<GLES2RenderSystem*>(Root::getSingleton().getRenderSystem())->getCapabilities()->getNumTextureUnits())
			{
				OGRE_CHECK_GL_ERROR(glActiveTexture(GL_TEXTURE0 + unit));
				mActiveTextureUnit = unit;
				return true;
			}
			else if (!unit)
			{
				// always ok to use the first unit
				return true;
			}
			else
			{
				return false;
			}
		}
		else
		{
			return true;
		}
	}

    // TODO: Store as high/low bits of a GLuint
    void GLES2StateCacheManagerImp::setBlendFunc(GLenum source, GLenum dest)
    {
        if(mBlendFuncSource != source || mBlendFuncDest != dest)
        {
            mBlendFuncSource = source;
            mBlendFuncDest = dest;

            OGRE_CHECK_GL_ERROR(glBlendFunc(source, dest));
        }
    }

    void GLES2StateCacheManagerImp::setBlendEquation(GLenum eq)
    {
        if(mBlendEquation != eq)
        {
            mBlendEquation = eq;

            OGRE_CHECK_GL_ERROR(glBlendEquation(eq));
        }
    }

    void GLES2StateCacheManagerImp::setDepthMask(GLboolean mask)
    {
        if(mDepthMask != mask)
        {
            mDepthMask = mask;

            OGRE_CHECK_GL_ERROR(glDepthMask(mask));
        }
    }

    void GLES2StateCacheManagerImp::setDepthFunc(GLenum func)
    {
        if(mDepthFunc != func)
        {
            mDepthFunc = func;

            OGRE_CHECK_GL_ERROR(glDepthFunc(func));
        }
    }

    void GLES2StateCacheManagerImp::setClearDepth(GLclampf depth)
    {
        if(mClearDepth != depth)
        {
            mClearDepth = depth;

            OGRE_CHECK_GL_ERROR(glClearDepthf(depth));
        }
    }

    void GLES2StateCacheManagerImp::setClearColour(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
    {
        if((mClearColour[0] != red) ||
           (mClearColour[1] != green) ||
           (mClearColour[2] != blue) ||
           (mClearColour[3] != alpha))
        {
            mClearColour[0] = red;
            mClearColour[1] = green;
            mClearColour[2] = blue;
            mClearColour[3] = alpha;

            OGRE_CHECK_GL_ERROR(glClearColor(mClearColour[0], mClearColour[1], mClearColour[2], mClearColour[3]));
        }
    }

    void GLES2StateCacheManagerImp::setColourMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
    {
        if((mColourMask[0] != red) ||
           (mColourMask[1] != green) ||
           (mColourMask[2] != blue) ||
           (mColourMask[3] != alpha))
        {
            mColourMask[0] = red;
            mColourMask[1] = green;
            mColourMask[2] = blue;
            mColourMask[3] = alpha;

            OGRE_CHECK_GL_ERROR(glColorMask(mColourMask[0], mColourMask[1], mColourMask[2], mColourMask[3]));
        }
    }

    void GLES2StateCacheManagerImp::setStencilMask(GLuint mask)
    {
        if(mStencilMask != mask)
        {
            mStencilMask = mask;

            OGRE_CHECK_GL_ERROR(glStencilMask(mask));
        }
    }

    void GLES2StateCacheManagerImp::setEnabled(GLenum flag)
    {
        bool found = std::find(mEnableVector.begin(), mEnableVector.end(), flag) != mEnableVector.end();
        if(!found)
        {
            mEnableVector.push_back(flag);

            OGRE_CHECK_GL_ERROR(glEnable(flag));
        }
    }

    void GLES2StateCacheManagerImp::setDisabled(GLenum flag)
    {
        vector<GLenum>::iterator iter = std::find(mEnableVector.begin(), mEnableVector.end(), flag);
        if(iter != mEnableVector.end())
        {
            mEnableVector.erase(iter);

            OGRE_CHECK_GL_ERROR(glDisable(flag));
        }
    }

    void GLES2StateCacheManagerImp::setVertexAttribEnabled(GLuint attrib)
    {
        bool found = std::find(mEnabledVertexAttribs.begin(), mEnabledVertexAttribs.end(), attrib) != mEnabledVertexAttribs.end();
        if(!found)
        {
            mEnabledVertexAttribs.push_back(attrib);

            OGRE_CHECK_GL_ERROR(glEnableVertexAttribArray(attrib));
        }
    }

    void GLES2StateCacheManagerImp::setVertexAttribDisabled(GLuint attrib)
    {
        vector<GLuint>::iterator iter = std::find(mEnabledVertexAttribs.begin(), mEnabledVertexAttribs.end(), attrib);
        if(iter != mEnabledVertexAttribs.end())
        {
            mEnabledVertexAttribs.erase(iter);

            OGRE_CHECK_GL_ERROR(glDisableVertexAttribArray(attrib));
        }
    }

    void GLES2StateCacheManagerImp::setCullFace(GLenum face)
    {
        if(mCullFace != face)
        {
            mCullFace = face;

            OGRE_CHECK_GL_ERROR(glCullFace(face));
        }
    }
}
<|endoftext|>