<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/lib/splaytree.C $                                         */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* COPYRIGHT International Business Machines Corp. 2012,2014              */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

#include <util/impl/splaytree.H>
#include <builtins.h>

/** @file splaytree.C
 *  Implementation of the Util::__Util_SplayTree_Impl::SplayTree class.
 */

namespace Util
{
    namespace __Util_SplayTree_Impl
    {

        SplayTree::SplayTree(SplayTree::comparator comp,
                             SplayTree::copier copy,
                             SplayTree::deleter del) :
            compare_functor(comp),
            copy_functor(copy),
            delete_functor(del)
        {
        }

        SplayTree::SplayTree(const SplayTree& t)
        {
            (*this) = t;
        }

        SplayTree::~SplayTree()
        {
            this->clear();
        }

        SplayTree& SplayTree::operator=(const SplayTree& t)
        {
            this->clear();

            compare_functor = t.compare_functor;
            copy_functor = t.copy_functor;
            delete_functor = t.delete_functor;

            insert_range(t.front(), NULL);
            if (likely(NULL != header.child[LEFT]))
            {
                splay(header.child[LEFT]);
            }

            return *this;
        }

        void SplayTree::insert(node* n)
        {
            if (unlikely(header.parent == NULL))  // First element.
            {
                header.parent = header.child[LEFT] = header.child[RIGHT] = n;
                n->parent = n->child[LEFT] = n->child[RIGHT] = NULL;
            }
            else // Not first element.
            {
                // Find place to insert node and insert it.
                node* insert_location = header.parent;
                __find(insert_location, n);
                __insert(insert_location, n);

                // Fix up header nodes.
                header.child[LEFT] = leftmost(header.child[LEFT]);
                header.child[RIGHT] = rightmost(header.child[RIGHT]);

                // Splay new node.
                splay(n);
            }

            // Increment size count.
            (header_n()->data)++;
        }

        void SplayTree::insert_range(const node* n1, const node* n2)
        {
            while(n1 != n2)
            {
                insert(copy_functor(n1));
                n1 = successor(n1);
            }
        }

        void SplayTree::remove(node* n)
        {
            // Fix up left-most and right-most node pointers if deleting
            // them.  We'll fix up the root in the node removal itself.
            if (unlikely(header.child[LEFT] == n))
            {
                header.child[LEFT] = successor(n);
            }
            if (unlikely(header.child[RIGHT] == n))
            {
                header.child[RIGHT] = predecessor(n);
            }

            // Decrement size count.
            (header_n()->data)--;

            // Find node to splice out of the tree.
            //    If n has one or no child, splice itself out, otherwise the
            //    successor.
            node* y = ((!n->child[LEFT]) || (!n->child[RIGHT])) ?
                            n : successor(n);

            // Find the subtree of y and link it with y's parent.
            node* x = y->child[LEFT] ? y->child[LEFT] : y->child[RIGHT];
            if (likely(NULL != x))
            {
                x->parent = y->parent;
            }
            if (unlikely(!y->parent))
            {
                // Fix root.
                header.parent = x;
            }
            else
            {
                y->parent->child[direction(y->parent, y)] = x;
            }

            // Replace n with y.
            if (likely(y != n))
            {
                y->parent = n->parent;
                if (y->parent)
                {
                    y->parent->child[direction(y->parent, n)] = y;
                }
                else
                {
                    // Removing root, so update header.
                    header.parent = y;
                }

                y->child[LEFT] = n->child[LEFT];
                if (y->child[LEFT])
                {
                    y->child[LEFT]->parent = y;
                }

                y->child[RIGHT] = n->child[RIGHT];
                if (y->child[RIGHT])
                {
                    y->child[RIGHT]->parent = y;
                }

                // Splay y up to the root.
                splay(y);
            }
        }

        bool SplayTree::find_hint(node* n, node*& hint) const
        {
            if (unlikely(NULL == header.parent))
            {
                return false;
            }

            hint = header.parent;

            bool found = __find(hint, n);

            // Splay hint up the tree to make future searches quicker.
            if (likely(NULL != hint))
            {
                splay(hint);
            }

            return found;
        }

        void SplayTree::clear()
        {
            node* n = front();
            while(n)
            {
                node* temp = n;
                n = successor(n);
                remove(temp);
                delete_functor(temp);
            }
        }

        void SplayTree::swap(SplayTree& tree)
        {
            node temp(header);
            header = tree.header;
            tree.header = temp;
        }

        bool SplayTree::insert_by_value(const void** v, node*& n)
        {
            n = find_by_value(v);

            if (unlikely(NULL != n))
            {
                return false;
            }
            else
            {
                n = copy_functor(node::convertToNode(v));
                insert(n);
                return true;
            }
        }

        size_t SplayTree::remove_by_value(const void** v)
        {
            if (unlikely(NULL == header.parent))
            {
                return 0;
            }

            node* v_node = header.parent;
            if (likely(__find(v_node, node::convertToNode(v))))
            {
                remove(v_node);
                delete_functor(v_node);
                return 1;
            }
            return 0;
        }

        bool SplayTree::find_hint_by_value(const void** v, node*& hint) const
        {
            return find_hint(node::convertToNode(v), hint);
        }

        SplayTree::node* SplayTree::find_by_value(const void** v) const
        {
            node* n = NULL;
            if (find_hint_by_value(v, n))
            {
                return n;
            }
            else
            {
                return NULL;
            }
        }

        SplayTree::node* SplayTree::lower_bound_by_value(const void** v) const
        {
            node* n = NULL;
            node* v_n = node::convertToNode(v);

            if (find_hint(v_n, n) || (NULL == n))
            {
                return n;
            }
            else
            {
                if (-1 == compare_functor(this, n, v_n))
                {
                    return successor(n);
                }
                else
                {
                    return n;
                }
            }
        }

        SplayTree::node* SplayTree::upper_bound_by_value(const void** v) const
        {
            node* n = NULL;
            node* v_n = node::convertToNode(v);

            if (find_hint(v_n, n))
            {
                return successor(n);
            }
            else if (NULL == n)
            {
                return NULL;
            }
            else
            {
                if (-1 == compare_functor(this, n, v_n))
                {
                    return successor(n);
                }
                else
                {
                    return n;
                }
            }
        }

        const SplayTree::node* SplayTree::predecessor(const node* n) const
        {
            // If left child, predecessor is just the largest of the left
            // subtree.
            if (likely(NULL != n->child[LEFT]))
            {
                return rightmost(n->child[LEFT]);
            }

            // Else, need to work up the tree to find predecessor.
            const node* y = n->parent;
            while ((NULL != y) && (n == y->child[LEFT]))
            {
                n = y;
                y = y->parent;
            }

            return y;
        }

        const SplayTree::node* SplayTree::successor(const node* n) const
        {
            // If right child, predecessor is just the smallest of the right
            // subtree.
            if (likely(NULL != n->child[RIGHT]))
            {
                return leftmost(n->child[RIGHT]);
            }

            // Else, need to work up the tree to find successor.
            const node* y = n->parent;
            while ((NULL != y) && (n == y->child[RIGHT]))
            {
                n = y;
                y = y->parent;
            }

            return y;
        }

        void SplayTree::rotate(node* n, DIRECTION d) const
        {
            // Get parent node.
            node* p = n->parent;

            // Link n's d-subtree into p.
            p->child[!d] = n->child[d];
            if (likely(NULL != n->child[d]))
            {
                n->child[d]->parent = p;
            }

            // Link p's parent to n.
            n->parent = p->parent;
            if (unlikely(!p->parent))
            {
                header.parent = n;
            }
            else
            {
                p->parent->child[direction(p->parent, p)] = n;
            }

            // Put p onto d-subtree of n.
            p->parent = n;
            n->child[d] = p;

        }

        void SplayTree::splay(node* n) const
        {
            // There are three splay operations.  "zig", "zig-zig" and
            // "zig-zag" based on the shape of the links between child, parent
            // and grand-parent.

            if (unlikely(!n->parent)) // This is the root node already.
            {
                return;
            }

            if (unlikely(!n->parent->parent)) // "zig" since no grand-parent.
            {
                // Rotate n into parent's location.
                rotate(n, !direction(n->parent, n));
            }
            else if (direction(n->parent, n) ==
                     direction(n->parent->parent, n->parent)) // "zig-zig"
            {
                // Rotate parent into grand-parent first, then rotate
                // n into parent.
                rotate(n->parent, !direction(n->parent->parent, n->parent));
                rotate(n, !direction(n->parent, n));

                // Continue splay.
                splay(n);
            }
            else // "zig-zag"
            {
                // Rotate n into parent, then n into grand-parent.
                rotate(n, !direction(n->parent, n));
                    // Note: grand-parent is now parent due to first rotate.
                rotate(n, !direction(n->parent, n));

                // Continue splay.
                splay(n);
            }
        }

        void SplayTree::__insert(node* t, node* n)
        {
            node*& child = (0 > (*compare_functor)(this, n, t)) ?
                                    t->child[LEFT] : t->child[RIGHT];

            if (likely(NULL == child)) // Assumption is the subtree hint is
                                       // correct, so this should be NULL.
            {
                // Link node into "child" slot.
                child = n;
                n->parent = t;
            }
            else
            {
                // Subtree hint was wrong, recurse tree.
                __insert(n, child);
            }
        }

        bool SplayTree::__find(node*& t, node* n) const
        {
            int compare = (*compare_functor)(this, n, t);

            if (unlikely(compare == 0)) // Node matches, return true.
            {
                return true;
            }

            node* child = (0 > compare) ? t->child[LEFT] : t->child[RIGHT];

            if (unlikely(NULL == child)) // No more children, no match.
            {
                return false;
            }
            else // Recurse to child.
            {
                t = child;
                return __find(t, n);
            }
        }

        void Iterator::increment()
        {
            if (NULL == node)
            {
                node = tree->front(); // This causes "begin() == ++end()" but
                                      // is necessary so that --rend() becomes
                                      // a reverse iterator to begin().
            }
            else
            {
                node = tree->successor(node);
            }
        };

        void Iterator::decrement()
        {
            if (NULL == node)
            {
                node = tree->back();
            }
            else
            {
                node = tree->predecessor(node);
            }
        }

        void ConstIterator::increment()
        {
            if (NULL == node)
            {
                node = tree->front(); // This causes "begin() == ++end()" but
                                      // is necessary so that --rend() becomes
                                      // a reverse iterator to begin().
            }
            else
            {
                node = tree->successor(node);
            }
        }

        void ConstIterator::decrement()
        {
            if (NULL == node)
            {
                node = tree->back();
            }
            else
            {
                node = tree->predecessor(node);
            }
        }

    };
};
<commit_msg>Do not splay in SplayTree::find_hint<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/lib/splaytree.C $                                         */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2012,2022                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

#include <util/impl/splaytree.H>
#include <builtins.h>

/** @file splaytree.C
 *  Implementation of the Util::__Util_SplayTree_Impl::SplayTree class.
 */

namespace Util
{
    namespace __Util_SplayTree_Impl
    {

        SplayTree::SplayTree(SplayTree::comparator comp,
                             SplayTree::copier copy,
                             SplayTree::deleter del) :
            compare_functor(comp),
            copy_functor(copy),
            delete_functor(del)
        {
        }

        SplayTree::SplayTree(const SplayTree& t)
        {
            (*this) = t;
        }

        SplayTree::~SplayTree()
        {
            this->clear();
        }

        SplayTree& SplayTree::operator=(const SplayTree& t)
        {
            this->clear();

            compare_functor = t.compare_functor;
            copy_functor = t.copy_functor;
            delete_functor = t.delete_functor;

            insert_range(t.front(), NULL);
            if (likely(NULL != header.child[LEFT]))
            {
                splay(header.child[LEFT]);
            }

            return *this;
        }

        void SplayTree::insert(node* n)
        {
            if (unlikely(header.parent == NULL))  // First element.
            {
                header.parent = header.child[LEFT] = header.child[RIGHT] = n;
                n->parent = n->child[LEFT] = n->child[RIGHT] = NULL;
            }
            else // Not first element.
            {
                // Find place to insert node and insert it.
                node* insert_location = header.parent;
                __find(insert_location, n);
                __insert(insert_location, n);

                // Fix up header nodes.
                header.child[LEFT] = leftmost(header.child[LEFT]);
                header.child[RIGHT] = rightmost(header.child[RIGHT]);

                // Splay new node.
                splay(n);
            }

            // Increment size count.
            (header_n()->data)++;
        }

        void SplayTree::insert_range(const node* n1, const node* n2)
        {
            while(n1 != n2)
            {
                insert(copy_functor(n1));
                n1 = successor(n1);
            }
        }

        void SplayTree::remove(node* n)
        {
            // Fix up left-most and right-most node pointers if deleting
            // them.  We'll fix up the root in the node removal itself.
            if (unlikely(header.child[LEFT] == n))
            {
                header.child[LEFT] = successor(n);
            }
            if (unlikely(header.child[RIGHT] == n))
            {
                header.child[RIGHT] = predecessor(n);
            }

            // Decrement size count.
            (header_n()->data)--;

            // Find node to splice out of the tree.
            //    If n has one or no child, splice itself out, otherwise the
            //    successor.
            node* y = ((!n->child[LEFT]) || (!n->child[RIGHT])) ?
                            n : successor(n);

            // Find the subtree of y and link it with y's parent.
            node* x = y->child[LEFT] ? y->child[LEFT] : y->child[RIGHT];
            if (likely(NULL != x))
            {
                x->parent = y->parent;
            }
            if (unlikely(!y->parent))
            {
                // Fix root.
                header.parent = x;
            }
            else
            {
                y->parent->child[direction(y->parent, y)] = x;
            }

            // Replace n with y.
            if (likely(y != n))
            {
                y->parent = n->parent;
                if (y->parent)
                {
                    y->parent->child[direction(y->parent, n)] = y;
                }
                else
                {
                    // Removing root, so update header.
                    header.parent = y;
                }

                y->child[LEFT] = n->child[LEFT];
                if (y->child[LEFT])
                {
                    y->child[LEFT]->parent = y;
                }

                y->child[RIGHT] = n->child[RIGHT];
                if (y->child[RIGHT])
                {
                    y->child[RIGHT]->parent = y;
                }

                // Splay y up to the root.
                splay(y);
            }
        }

        bool SplayTree::find_hint(node* n, node*& hint) const
        {
            if (unlikely(NULL == header.parent))
            {
                return false;
            }

            hint = header.parent;

            bool found = __find(hint, n);

/*          DO NOT SPLAY HERE
 *          It increases the probability of hitting an
 *          issue when multi-threaded.
 *          @TODO JIRA PFHB-297 Temporary fix, while a more permanent
 *          fix is being developed.
 *
 *          Splay hint up the tree to make future searches quicker.
 *          if (likely(NULL != hint))
 *          {
 *             splay(hint);
 *          }
 */
            return found;
        }

        void SplayTree::clear()
        {
            node* n = front();
            while(n)
            {
                node* temp = n;
                n = successor(n);
                remove(temp);
                delete_functor(temp);
            }
        }

        void SplayTree::swap(SplayTree& tree)
        {
            node temp(header);
            header = tree.header;
            tree.header = temp;
        }

        bool SplayTree::insert_by_value(const void** v, node*& n)
        {
            n = find_by_value(v);

            if (unlikely(NULL != n))
            {
                return false;
            }
            else
            {
                n = copy_functor(node::convertToNode(v));
                insert(n);
                return true;
            }
        }

        size_t SplayTree::remove_by_value(const void** v)
        {
            if (unlikely(NULL == header.parent))
            {
                return 0;
            }

            node* v_node = header.parent;
            if (likely(__find(v_node, node::convertToNode(v))))
            {
                remove(v_node);
                delete_functor(v_node);
                return 1;
            }
            return 0;
        }

        bool SplayTree::find_hint_by_value(const void** v, node*& hint) const
        {
            return find_hint(node::convertToNode(v), hint);
        }

        SplayTree::node* SplayTree::find_by_value(const void** v) const
        {
            node* n = NULL;
            if (find_hint_by_value(v, n))
            {
                return n;
            }
            else
            {
                return NULL;
            }
        }

        SplayTree::node* SplayTree::lower_bound_by_value(const void** v) const
        {
            node* n = NULL;
            node* v_n = node::convertToNode(v);

            if (find_hint(v_n, n) || (NULL == n))
            {
                return n;
            }
            else
            {
                if (-1 == compare_functor(this, n, v_n))
                {
                    return successor(n);
                }
                else
                {
                    return n;
                }
            }
        }

        SplayTree::node* SplayTree::upper_bound_by_value(const void** v) const
        {
            node* n = NULL;
            node* v_n = node::convertToNode(v);

            if (find_hint(v_n, n))
            {
                return successor(n);
            }
            else if (NULL == n)
            {
                return NULL;
            }
            else
            {
                if (-1 == compare_functor(this, n, v_n))
                {
                    return successor(n);
                }
                else
                {
                    return n;
                }
            }
        }

        const SplayTree::node* SplayTree::predecessor(const node* n) const
        {
            // If left child, predecessor is just the largest of the left
            // subtree.
            if (likely(NULL != n->child[LEFT]))
            {
                return rightmost(n->child[LEFT]);
            }

            // Else, need to work up the tree to find predecessor.
            const node* y = n->parent;
            while ((NULL != y) && (n == y->child[LEFT]))
            {
                n = y;
                y = y->parent;
            }

            return y;
        }

        const SplayTree::node* SplayTree::successor(const node* n) const
        {
            // If right child, predecessor is just the smallest of the right
            // subtree.
            if (likely(NULL != n->child[RIGHT]))
            {
                return leftmost(n->child[RIGHT]);
            }

            // Else, need to work up the tree to find successor.
            const node* y = n->parent;
            while ((NULL != y) && (n == y->child[RIGHT]))
            {
                n = y;
                y = y->parent;
            }

            return y;
        }

        void SplayTree::rotate(node* n, DIRECTION d) const
        {
            // Get parent node.
            node* p = n->parent;

            // Link n's d-subtree into p.
            p->child[!d] = n->child[d];
            if (likely(NULL != n->child[d]))
            {
                n->child[d]->parent = p;
            }

            // Link p's parent to n.
            n->parent = p->parent;
            if (unlikely(!p->parent))
            {
                header.parent = n;
            }
            else
            {
                p->parent->child[direction(p->parent, p)] = n;
            }

            // Put p onto d-subtree of n.
            p->parent = n;
            n->child[d] = p;

        }

        void SplayTree::splay(node* n) const
        {
            // There are three splay operations.  "zig", "zig-zig" and
            // "zig-zag" based on the shape of the links between child, parent
            // and grand-parent.

            if (unlikely(!n->parent)) // This is the root node already.
            {
                return;
            }

            if (unlikely(!n->parent->parent)) // "zig" since no grand-parent.
            {
                // Rotate n into parent's location.
                rotate(n, !direction(n->parent, n));
            }
            else if (direction(n->parent, n) ==
                     direction(n->parent->parent, n->parent)) // "zig-zig"
            {
                // Rotate parent into grand-parent first, then rotate
                // n into parent.
                rotate(n->parent, !direction(n->parent->parent, n->parent));
                rotate(n, !direction(n->parent, n));

                // Continue splay.
                splay(n);
            }
            else // "zig-zag"
            {
                // Rotate n into parent, then n into grand-parent.
                rotate(n, !direction(n->parent, n));
                    // Note: grand-parent is now parent due to first rotate.
                rotate(n, !direction(n->parent, n));

                // Continue splay.
                splay(n);
            }
        }

        void SplayTree::__insert(node* t, node* n)
        {
            node*& child = (0 > (*compare_functor)(this, n, t)) ?
                                    t->child[LEFT] : t->child[RIGHT];

            if (likely(NULL == child)) // Assumption is the subtree hint is
                                       // correct, so this should be NULL.
            {
                // Link node into "child" slot.
                child = n;
                n->parent = t;
            }
            else
            {
                // Subtree hint was wrong, recurse tree.
                __insert(n, child);
            }
        }

        bool SplayTree::__find(node*& t, node* n) const
        {
            int compare = (*compare_functor)(this, n, t);

            if (unlikely(compare == 0)) // Node matches, return true.
            {
                return true;
            }

            node* child = (0 > compare) ? t->child[LEFT] : t->child[RIGHT];

            if (unlikely(NULL == child)) // No more children, no match.
            {
                return false;
            }
            else // Recurse to child.
            {
                t = child;
                return __find(t, n);
            }
        }

        void Iterator::increment()
        {
            if (NULL == node)
            {
                node = tree->front(); // This causes "begin() == ++end()" but
                                      // is necessary so that --rend() becomes
                                      // a reverse iterator to begin().
            }
            else
            {
                node = tree->successor(node);
            }
        };

        void Iterator::decrement()
        {
            if (NULL == node)
            {
                node = tree->back();
            }
            else
            {
                node = tree->predecessor(node);
            }
        }

        void ConstIterator::increment()
        {
            if (NULL == node)
            {
                node = tree->front(); // This causes "begin() == ++end()" but
                                      // is necessary so that --rend() becomes
                                      // a reverse iterator to begin().
            }
            else
            {
                node = tree->successor(node);
            }
        }

        void ConstIterator::decrement()
        {
            if (NULL == node)
            {
                node = tree->back();
            }
            else
            {
                node = tree->predecessor(node);
            }
        }

    };
};
<|endoftext|>


<commit_before>// Copyright 2012-2019 Richard Copley
//
// 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.

#include "mswin.h"

#include "make_system.h"
#include "compiler.h"
#include "memory.h"
#include "rotor.h"
#include "vector.h"
#include <cstring>
#include <utility>

// Return the order of the rotation group of the pqr triangulation.
unsigned moebius_order (unsigned p, unsigned q, unsigned r)
{
  return (2 * p * q * r) / (q * r + r * p + p * q - p * q * r);
}

NOINLINE unsigned sigma_inverse (unsigned dart, unsigned order)
{
  if (dart % order < 1u) {
    dart += order;
  }
  return dart - 1u;
}

unsigned make_system (const unsigned (& p) [3],
                      const float (& triangle) [3] [4],
                      float (* nodes) [4], std::uint8_t (* indices) [6])
{
  ALIGNED16 rotor_t rotate;
  void * memory = allocate (3 * 6 * 60 * sizeof (unsigned));
  unsigned * alpha = reinterpret_cast <unsigned *> (memory);
  unsigned * sigma = alpha + 6 * 60;
  unsigned * origin = sigma + 6 * 60;
  const unsigned n = moebius_order (p [0], p [1], p [2]);
  unsigned next [3], a [3];

  unsigned dart = 0, node = 0;
  for (unsigned i = 0; i != 3; ++ i) {
    a [i] = dart + 1;
    next [i] = dart + 2 * p [i];
    store4f (nodes [node], load4f (triangle [i]));
    for (unsigned m = 0; m != n / p [i]; ++ m) {
      unsigned predecessor = dart + 2 * p [i] - 1;
      for (unsigned j = 0; j != 2 * p [i]; ++ j) {
        predecessor [sigma] = dart;
        origin [dart] = node;
        predecessor = dart ++;
      }
      ++ node;
    }
  }

  constexpr unsigned undef = -1;
  std::memset (alpha, '\xff', 6 * 60 * sizeof 0 [alpha]);
  unsigned mu [3] = { 0, 1, 2 };
  bool even = true;
  rotate.about (nodes [0], -6.28318531f / ui2f (p [0]));

  while (true) {
    a [0] [sigma] [alpha] = a [1];
    a [1] [sigma] [alpha] = a [2];
    a [2] [sigma] [alpha] = a [0];

    unsigned b [3];
    b [1] = sigma_inverse (a [2], 2 * p [2 [mu]]);
    if (a [2] [alpha] == undef && b [1] [alpha] != undef) {
      b [0] = sigma_inverse (b [1] [alpha], 2 * p [0 [mu]]);
      b [2] = a [1] [sigma];

      b [0] [sigma] [alpha] = b [1];
      b [1] [sigma] [alpha] = b [2];
      b [2] [sigma] [alpha] = b [0];
    }

    if (a [0] [sigma] [sigma] [alpha] == undef) {
      a [0] = a [0] [sigma];
      std::swap (1 [mu], 2 [mu]);
    }
    else if (a [1] [sigma] [sigma] [alpha] == undef) {
      a [0] = a [1] [sigma];
      std::swap (0 [mu], 1 [mu]);
      rotate.about (nodes [origin [a [0]]], -6.28318531f / ui2f (p [0 [mu]]));
    }
    else break;
    even = !even;

    if (a [0] [sigma] [sigma] [alpha] == undef) {
      a [1] = next [1 [mu]] + even;
      next [1 [mu]] += 2 * p [1 [mu]];
      rotate (nodes [origin [a [0] [alpha] [sigma] [alpha]]],
              nodes [origin [a [1]]]);
    }
    else {
      a [1] = a [0] [sigma] [sigma] [alpha] [sigma] [alpha] [sigma];
    }
    a [2] = sigma_inverse (a [0] [alpha], 2 * p [2 [mu]]);
  }

  for (unsigned i = 0; i != n / p [0]; ++ i) {
    unsigned d = 2 * p [0] * i;
    for (unsigned m = 0; m != p [0]; ++ m) {
      std::uint8_t (& block) [6] = indices [p [0] * i + m];
      block [0] = origin [d];
      block [1] = origin [d = d [alpha]];
      block [2] = origin [d = d [sigma] [alpha]];
      block [3] = origin [d = d [sigma] [sigma] [sigma] [alpha]];
      block [4] = origin [d = d [sigma] [alpha]];
      block [5] = origin [d = d [sigma] [sigma] [sigma] [alpha]];
      d = d [sigma] [alpha] [sigma];
    }
  }

  deallocate (memory);
  return n;
}
<commit_msg>make_system.cpp: Adjust to achieve smaller code. Comments.<commit_after>// Copyright 2012-2019 Richard Copley
//
// 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.

#include "mswin.h"

#include "make_system.h"
#include "compiler.h"
#include "memory.h"
#include "rotor.h"
#include "vector.h"
#include <cstring>
#include <utility>

// Return the number of positive-sense triangles in the spherical tiling
// generated by the Moebius triangle with dihedral angles pi/p, pi/q and pi/r.
constexpr unsigned moebius_order (unsigned p, unsigned q, unsigned r)
{
  return (2 * p * q * r) / (q * r + r * p + p * q - p * q * r);
}

NOINLINE unsigned sigma_inverse (unsigned dart, unsigned order)
{
  if (dart % order < 1u) {
    dart += order;
  }
  return dart - 1u;
}

// Construct a dart system for the spherical tiling and find node coordinates.
unsigned make_system (const unsigned (& p) [3],
                      const float (& triangle) [3] [4],
                      float (* nodes) [4], std::uint8_t (* indices) [6])
{
  const unsigned n = moebius_order (p [0], p [1], p [2]);
  void * memory = allocate (3 * 6 * n * sizeof (unsigned));
  unsigned * array = reinterpret_cast <unsigned *> (memory);
  unsigned * alpha = array;            // Opposite dart in the same edge.
  unsigned * sigma = array + 6 * n;    // Next dart around same origin node.
  unsigned * origin = array + 12 * n;  // Map from dart to its start node.
  unsigned next [3];                   // First dart of next free node of type.
  unsigned a [3];                      // Cursor darts.
  unsigned mu [3] = { 0, 1, 2 };       // Tracks the type of the current darts.
  bool even = true;                    // Tracks the parity of mu.

  // Initialize alpha to undefined.
  constexpr unsigned undef = -1;
  std::memset (alpha, '\xff', 6 * n * sizeof 0 [alpha]);

  // Choose some permutation sigma with the necessary disjoint-cycle structure.
  // Initialize origin, next and a, and copy vertices from triangle to nodes.
  unsigned dart = 0, node = 0;
  for (unsigned i = 0; i != 3; ++ i) {
    a [i] = dart + 1;
    next [i] = dart + 2 * p [i];
    store4f (nodes [node], load4f (triangle [i]));
    for (unsigned m = 0; m != n / p [i]; ++ m) {
      unsigned predecessor = dart + 2 * p [i] - 1;
      for (unsigned j = 0; j != 2 * p [i]; ++ j) {
        predecessor [sigma] = dart;
        origin [dart] = node;
        predecessor = dart ++;
      }
      ++ node;
    }
  }

  ALIGNED16 rotor_t rotate;
  rotate.about (nodes [0], -6.28318531f / ui2f (p [0]));

  // Extend alpha to a fixed point free involution, maintaining the invariant
  // d[alpha] == undef || d == d[alpha][sigma][alpha][sigma][alpha][sigma],
  // and locate the remaining nodes.
  while (true) {
    a [0] [sigma] [alpha] = a [1];
    a [1] [sigma] [alpha] = a [2];
    a [2] [sigma] [alpha] = a [0];

    a [0] = a [0] [sigma];
    if (a [0] [sigma] [alpha] != undef) {
      a [0] = a [1] [sigma];
      if (a [0] [sigma] [alpha] != undef) {
        break;
      }
      std::swap (mu [0], mu [2]);
      std::swap (mu [0], mu [1]);
      rotate.about (nodes [origin [a [0]]], -6.28318531f / ui2f (p [mu [0]]));
    }

    std::swap (mu [1], mu [2]);
    even = !even;

    a [2] = sigma_inverse (a [0] [alpha], 2 * p [mu [2]]);
    if (a [0] [sigma] [sigma] [alpha] != undef) {
      a [1] = a [0] [sigma] [sigma] [alpha] [sigma] [alpha] [sigma];
    }
    else {
      // Locate a new node.
      a [1] = next [mu [1]] + even;
      next [mu [1]] += 2 * p [mu [1]];
      rotate (nodes [origin [a [0] [alpha] [sigma] [alpha]]],
              nodes [origin [a [1]]]);
    }

    if (a [2] [alpha] == undef) {
      unsigned b [3];
      b [1] = sigma_inverse (a [2], 2 * p [mu [2]]);
      if (b [1] [alpha] != undef) {
        b [0] = sigma_inverse (b [1] [alpha], 2 * p [mu [0]]);
        b [2] = a [1] [sigma];

        b [0] [sigma] [alpha] = b [1];
        b [1] [sigma] [alpha] = b [2];
        b [2] [sigma] [alpha] = b [0];
      }
    }
  }

  //    X1    Use the dart system to construct blocks {X0, Z1, Y0, X1, Z0, Y1}
  //   /  \   of nodes, one block for each positive-sense triangle X0 Y0 Z0.
  //  Y0--Z0  The nodes and index blocks are stored in a vertex array object.
  //  |\  /|  Each invocation of the geometry shader accepts a block of 6 nodes
  //  | X0 |  and emits the vertex figure for a polyhedron vertex at a point
  //  |/  \|  inside the spherical triangle X0 Y0 Z0. Drawing n copies of the
  //  Z1  Y1  vertex figure produces a complete polyhedron.

  for (unsigned i = 0; i != n / p [0]; ++ i) {
    unsigned d = 2 * p [0] * i;
    for (unsigned m = 0; m != p [0]; ++ m) {
      std::uint8_t (& block) [6] = indices [p [0] * i + m];
      block [0] = origin [d];
      block [1] = origin [d = d [alpha]];
      block [2] = origin [d = d [sigma] [alpha]];
      block [3] = origin [d = d [sigma] [sigma] [sigma] [alpha]];
      block [4] = origin [d = d [sigma] [alpha]];
      block [5] = origin [d = d [sigma] [sigma] [sigma] [alpha]];
      d = d [sigma] [alpha] [sigma];
    }
  }

  deallocate (memory);
  return n;
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/modules/desktop_capture/window_capturer.h"

#include <assert.h>

#include "webrtc/base/scoped_ptr.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/win32.h"
#include "webrtc/modules/desktop_capture/desktop_frame_win.h"
#include "webrtc/modules/desktop_capture/win/window_capture_utils.h"
#include "webrtc/system_wrappers/include/logging.h"

namespace webrtc {

namespace {

BOOL CALLBACK WindowsEnumerationHandler(HWND hwnd, LPARAM param) {
  WindowCapturer::WindowList* list =
      reinterpret_cast<WindowCapturer::WindowList*>(param);

  // Skip windows that are invisible, minimized, have no title, or are owned,
  // unless they have the app window style set.
  int len = GetWindowTextLength(hwnd);
  HWND owner = GetWindow(hwnd, GW_OWNER);
  LONG exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
  if (len == 0 || IsIconic(hwnd) || !IsWindowVisible(hwnd) ||
      (owner && !(exstyle & WS_EX_APPWINDOW))) {
    return TRUE;
  }

  // Skip the Program Manager window and the Start button.
  const size_t kClassLength = 256;
  WCHAR class_name[kClassLength];
  const int class_name_length = GetClassName(hwnd, class_name, kClassLength);
  RTC_DCHECK(class_name_length)
      << "Error retrieving the application's class name";

  // Skip Program Manager window and the Start button. This is the same logic
  // that's used in Win32WindowPicker in libjingle. Consider filtering other
  // windows as well (e.g. toolbars).
  if (wcscmp(class_name, L"Progman") == 0 || wcscmp(class_name, L"Button") == 0)
    return TRUE;

  // Windows 8 introduced a "Modern App" identified by their class name being
  // either ApplicationFrameWindow or windows.UI.Core.coreWindow. The
  // associated windows cannot be captured, so we skip them.
  // http://crbug.com/526883.
  if (rtc::IsWindows8OrLater() &&
      (wcscmp(class_name, L"ApplicationFrameWindow") == 0 ||
       wcscmp(class_name, L"Windows.UI.Core.CoreWindow") == 0)) {
    return TRUE;
  }

  WindowCapturer::Window window;
  window.id = reinterpret_cast<WindowCapturer::WindowId>(hwnd);

  const size_t kTitleLength = 500;
  WCHAR window_title[kTitleLength];
  // Truncate the title if it's longer than kTitleLength.
  GetWindowText(hwnd, window_title, kTitleLength);
  window.title = rtc::ToUtf8(window_title);

  // Skip windows when we failed to convert the title or it is empty.
  if (window.title.empty())
    return TRUE;

  list->push_back(window);

  return TRUE;
}

class WindowCapturerWin : public WindowCapturer {
 public:
  WindowCapturerWin();
  virtual ~WindowCapturerWin();

  // WindowCapturer interface.
  bool GetWindowList(WindowList* windows) override;
  bool SelectWindow(WindowId id) override;
  bool BringSelectedWindowToFront() override;

  // DesktopCapturer interface.
  void Start(Callback* callback) override;
  void Capture(const DesktopRegion& region) override;

 private:
  Callback* callback_;

  // HWND and HDC for the currently selected window or NULL if window is not
  // selected.
  HWND window_;

  DesktopSize previous_size_;

  AeroChecker aero_checker_;

  RTC_DISALLOW_COPY_AND_ASSIGN(WindowCapturerWin);
};

WindowCapturerWin::WindowCapturerWin()
    : callback_(NULL),
      window_(NULL) {
}

WindowCapturerWin::~WindowCapturerWin() {
}

bool WindowCapturerWin::GetWindowList(WindowList* windows) {
  WindowList result;
  LPARAM param = reinterpret_cast<LPARAM>(&result);
  if (!EnumWindows(&WindowsEnumerationHandler, param))
    return false;
  windows->swap(result);
  return true;
}

bool WindowCapturerWin::SelectWindow(WindowId id) {
  HWND window = reinterpret_cast<HWND>(id);
  if (!IsWindow(window) || !IsWindowVisible(window) || IsIconic(window))
    return false;
  window_ = window;
  previous_size_.set(0, 0);
  return true;
}

bool WindowCapturerWin::BringSelectedWindowToFront() {
  if (!window_)
    return false;

  if (!IsWindow(window_) || !IsWindowVisible(window_) || IsIconic(window_))
    return false;

  return SetForegroundWindow(window_) != 0;
}

void WindowCapturerWin::Start(Callback* callback) {
  assert(!callback_);
  assert(callback);

  callback_ = callback;
}

void WindowCapturerWin::Capture(const DesktopRegion& region) {
  if (!window_) {
    LOG(LS_ERROR) << "Window hasn't been selected: " << GetLastError();
    callback_->OnCaptureCompleted(NULL);
    return;
  }

  // Stop capturing if the window has been closed.
  if (!IsWindow(window_)) {
    callback_->OnCaptureCompleted(NULL);
    return;
  }

  // Return a 1x1 black frame if the window is minimized or invisible, to match
  // behavior on mace. Window can be temporarily invisible during the
  // transition of full screen mode on/off.
  if (IsIconic(window_) || !IsWindowVisible(window_)) {
    BasicDesktopFrame* frame = new BasicDesktopFrame(DesktopSize(1, 1));
    memset(frame->data(), 0, frame->stride() * frame->size().height());

    previous_size_ = frame->size();
    callback_->OnCaptureCompleted(frame);
    return;
  }

  DesktopRect original_rect;
  DesktopRect cropped_rect;
  if (!GetCroppedWindowRect(window_, &cropped_rect, &original_rect)) {
    LOG(LS_WARNING) << "Failed to get window info: " << GetLastError();
    callback_->OnCaptureCompleted(NULL);
    return;
  }

  HDC window_dc = GetWindowDC(window_);
  if (!window_dc) {
    LOG(LS_WARNING) << "Failed to get window DC: " << GetLastError();
    callback_->OnCaptureCompleted(NULL);
    return;
  }

  rtc::scoped_ptr<DesktopFrameWin> frame(
      DesktopFrameWin::Create(cropped_rect.size(), NULL, window_dc));
  if (!frame.get()) {
    ReleaseDC(window_, window_dc);
    callback_->OnCaptureCompleted(NULL);
    return;
  }

  HDC mem_dc = CreateCompatibleDC(window_dc);
  HGDIOBJ previous_object = SelectObject(mem_dc, frame->bitmap());
  BOOL result = FALSE;

  // When desktop composition (Aero) is enabled each window is rendered to a
  // private buffer allowing BitBlt() to get the window content even if the
  // window is occluded. PrintWindow() is slower but lets rendering the window
  // contents to an off-screen device context when Aero is not available.
  // PrintWindow() is not supported by some applications.
  //
  // If Aero is enabled, we prefer BitBlt() because it's faster and avoids
  // window flickering. Otherwise, we prefer PrintWindow() because BitBlt() may
  // render occluding windows on top of the desired window.
  //
  // When composition is enabled the DC returned by GetWindowDC() doesn't always
  // have window frame rendered correctly. Windows renders it only once and then
  // caches the result between captures. We hack it around by calling
  // PrintWindow() whenever window size changes, including the first time of
  // capturing - it somehow affects what we get from BitBlt() on the subsequent
  // captures.

  if (!aero_checker_.IsAeroEnabled() || !previous_size_.equals(frame->size())) {
    result = PrintWindow(window_, mem_dc, 0);
  }

  // Aero is enabled or PrintWindow() failed, use BitBlt.
  if (!result) {
    result = BitBlt(mem_dc, 0, 0, frame->size().width(), frame->size().height(),
                    window_dc,
                    cropped_rect.left() - original_rect.left(),
                    cropped_rect.top() - original_rect.top(),
                    SRCCOPY);
  }

  SelectObject(mem_dc, previous_object);
  DeleteDC(mem_dc);
  ReleaseDC(window_, window_dc);

  previous_size_ = frame->size();

  frame->mutable_updated_region()->SetRect(
      DesktopRect::MakeSize(frame->size()));

  if (!result) {
    LOG(LS_ERROR) << "Both PrintWindow() and BitBlt() failed.";
    frame.reset();
  }

  callback_->OnCaptureCompleted(frame.release());
}

}  // namespace

// static
WindowCapturer* WindowCapturer::Create(const DesktopCaptureOptions& options) {
  return new WindowCapturerWin();
}

}  // namespace webrtc
<commit_msg>Screen was flickering when the picker for desktop medias showed up in Windows platform. Keeping track of window size for each window so that BitBlt() instead of PrintWindow() will be called for windows with unchanged sizes.<commit_after>/*
 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/modules/desktop_capture/window_capturer.h"

#include <assert.h>

#include "webrtc/base/scoped_ptr.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/win32.h"
#include "webrtc/modules/desktop_capture/desktop_frame_win.h"
#include "webrtc/modules/desktop_capture/win/window_capture_utils.h"
#include "webrtc/system_wrappers/include/logging.h"

namespace webrtc {

namespace {

BOOL CALLBACK WindowsEnumerationHandler(HWND hwnd, LPARAM param) {
  WindowCapturer::WindowList* list =
      reinterpret_cast<WindowCapturer::WindowList*>(param);

  // Skip windows that are invisible, minimized, have no title, or are owned,
  // unless they have the app window style set.
  int len = GetWindowTextLength(hwnd);
  HWND owner = GetWindow(hwnd, GW_OWNER);
  LONG exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
  if (len == 0 || IsIconic(hwnd) || !IsWindowVisible(hwnd) ||
      (owner && !(exstyle & WS_EX_APPWINDOW))) {
    return TRUE;
  }

  // Skip the Program Manager window and the Start button.
  const size_t kClassLength = 256;
  WCHAR class_name[kClassLength];
  const int class_name_length = GetClassName(hwnd, class_name, kClassLength);
  RTC_DCHECK(class_name_length)
      << "Error retrieving the application's class name";

  // Skip Program Manager window and the Start button. This is the same logic
  // that's used in Win32WindowPicker in libjingle. Consider filtering other
  // windows as well (e.g. toolbars).
  if (wcscmp(class_name, L"Progman") == 0 || wcscmp(class_name, L"Button") == 0)
    return TRUE;

  // Windows 8 introduced a "Modern App" identified by their class name being
  // either ApplicationFrameWindow or windows.UI.Core.coreWindow. The
  // associated windows cannot be captured, so we skip them.
  // http://crbug.com/526883.
  if (rtc::IsWindows8OrLater() &&
      (wcscmp(class_name, L"ApplicationFrameWindow") == 0 ||
       wcscmp(class_name, L"Windows.UI.Core.CoreWindow") == 0)) {
    return TRUE;
  }

  WindowCapturer::Window window;
  window.id = reinterpret_cast<WindowCapturer::WindowId>(hwnd);

  const size_t kTitleLength = 500;
  WCHAR window_title[kTitleLength];
  // Truncate the title if it's longer than kTitleLength.
  GetWindowText(hwnd, window_title, kTitleLength);
  window.title = rtc::ToUtf8(window_title);

  // Skip windows when we failed to convert the title or it is empty.
  if (window.title.empty())
    return TRUE;

  list->push_back(window);

  return TRUE;
}

class WindowCapturerWin : public WindowCapturer {
 public:
  WindowCapturerWin();
  virtual ~WindowCapturerWin();

  // WindowCapturer interface.
  bool GetWindowList(WindowList* windows) override;
  bool SelectWindow(WindowId id) override;
  bool BringSelectedWindowToFront() override;

  // DesktopCapturer interface.
  void Start(Callback* callback) override;
  void Capture(const DesktopRegion& region) override;

 private:
  Callback* callback_;

  // HWND and HDC for the currently selected window or NULL if window is not
  // selected.
  HWND window_;

  DesktopSize previous_size_;

  AeroChecker aero_checker_;

  // This map is used to avoid flickering for the case when SelectWindow() calls
  // are interleaved with Capture() calls.
  std::map<HWND, DesktopSize> window_size_map_;

  RTC_DISALLOW_COPY_AND_ASSIGN(WindowCapturerWin);
};

WindowCapturerWin::WindowCapturerWin()
    : callback_(NULL),
      window_(NULL) {
}

WindowCapturerWin::~WindowCapturerWin() {
}

bool WindowCapturerWin::GetWindowList(WindowList* windows) {
  WindowList result;
  LPARAM param = reinterpret_cast<LPARAM>(&result);
  if (!EnumWindows(&WindowsEnumerationHandler, param))
    return false;
  windows->swap(result);

  std::map<HWND, DesktopSize> new_map;
  for (const auto& item : *windows) {
    HWND hwnd = reinterpret_cast<HWND>(item.id);
    new_map[hwnd] = window_size_map_[hwnd];
  }
  window_size_map_.swap(new_map);

  return true;
}

bool WindowCapturerWin::SelectWindow(WindowId id) {
  HWND window = reinterpret_cast<HWND>(id);
  if (!IsWindow(window) || !IsWindowVisible(window) || IsIconic(window))
    return false;
  window_ = window;
  // When a window is not in the map, window_size_map_[window] will create an
  // item with DesktopSize (0, 0).
  previous_size_ = window_size_map_[window];
  return true;
}

bool WindowCapturerWin::BringSelectedWindowToFront() {
  if (!window_)
    return false;

  if (!IsWindow(window_) || !IsWindowVisible(window_) || IsIconic(window_))
    return false;

  return SetForegroundWindow(window_) != 0;
}

void WindowCapturerWin::Start(Callback* callback) {
  assert(!callback_);
  assert(callback);

  callback_ = callback;
}

void WindowCapturerWin::Capture(const DesktopRegion& region) {
  if (!window_) {
    LOG(LS_ERROR) << "Window hasn't been selected: " << GetLastError();
    callback_->OnCaptureCompleted(NULL);
    return;
  }

  // Stop capturing if the window has been closed.
  if (!IsWindow(window_)) {
    callback_->OnCaptureCompleted(NULL);
    return;
  }

  // Return a 1x1 black frame if the window is minimized or invisible, to match
  // behavior on mace. Window can be temporarily invisible during the
  // transition of full screen mode on/off.
  if (IsIconic(window_) || !IsWindowVisible(window_)) {
    BasicDesktopFrame* frame = new BasicDesktopFrame(DesktopSize(1, 1));
    memset(frame->data(), 0, frame->stride() * frame->size().height());

    previous_size_ = frame->size();
    window_size_map_[window_] = previous_size_;
    callback_->OnCaptureCompleted(frame);
    return;
  }

  DesktopRect original_rect;
  DesktopRect cropped_rect;
  if (!GetCroppedWindowRect(window_, &cropped_rect, &original_rect)) {
    LOG(LS_WARNING) << "Failed to get window info: " << GetLastError();
    callback_->OnCaptureCompleted(NULL);
    return;
  }

  HDC window_dc = GetWindowDC(window_);
  if (!window_dc) {
    LOG(LS_WARNING) << "Failed to get window DC: " << GetLastError();
    callback_->OnCaptureCompleted(NULL);
    return;
  }

  rtc::scoped_ptr<DesktopFrameWin> frame(
      DesktopFrameWin::Create(cropped_rect.size(), NULL, window_dc));
  if (!frame.get()) {
    ReleaseDC(window_, window_dc);
    callback_->OnCaptureCompleted(NULL);
    return;
  }

  HDC mem_dc = CreateCompatibleDC(window_dc);
  HGDIOBJ previous_object = SelectObject(mem_dc, frame->bitmap());
  BOOL result = FALSE;

  // When desktop composition (Aero) is enabled each window is rendered to a
  // private buffer allowing BitBlt() to get the window content even if the
  // window is occluded. PrintWindow() is slower but lets rendering the window
  // contents to an off-screen device context when Aero is not available.
  // PrintWindow() is not supported by some applications.
  //
  // If Aero is enabled, we prefer BitBlt() because it's faster and avoids
  // window flickering. Otherwise, we prefer PrintWindow() because BitBlt() may
  // render occluding windows on top of the desired window.
  //
  // When composition is enabled the DC returned by GetWindowDC() doesn't always
  // have window frame rendered correctly. Windows renders it only once and then
  // caches the result between captures. We hack it around by calling
  // PrintWindow() whenever window size changes, including the first time of
  // capturing - it somehow affects what we get from BitBlt() on the subsequent
  // captures.

  if (!aero_checker_.IsAeroEnabled() || !previous_size_.equals(frame->size())) {
    result = PrintWindow(window_, mem_dc, 0);
  }

  // Aero is enabled or PrintWindow() failed, use BitBlt.
  if (!result) {
    result = BitBlt(mem_dc, 0, 0, frame->size().width(), frame->size().height(),
                    window_dc,
                    cropped_rect.left() - original_rect.left(),
                    cropped_rect.top() - original_rect.top(),
                    SRCCOPY);
  }

  SelectObject(mem_dc, previous_object);
  DeleteDC(mem_dc);
  ReleaseDC(window_, window_dc);

  previous_size_ = frame->size();
  window_size_map_[window_] = previous_size_;

  frame->mutable_updated_region()->SetRect(
      DesktopRect::MakeSize(frame->size()));

  if (!result) {
    LOG(LS_ERROR) << "Both PrintWindow() and BitBlt() failed.";
    frame.reset();
  }

  callback_->OnCaptureCompleted(frame.release());
}

}  // namespace

// static
WindowCapturer* WindowCapturer::Create(const DesktopCaptureOptions& options) {
  return new WindowCapturerWin();
}

}  // namespace webrtc
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <fstream>
using namespace std;

template<typename T>
struct Node
{
	T x;
	Node<T> * left;
	Node<T> * right;
	Node(T const& value) : x{ value }, left{ nullptr }, right{ nullptr } {}
};

template<typename T>
class Tree
{
private:
	Node<T> * root;
public:
	Tree()
	{
		root  = nullptr;
	}

	~Tree()
	{
		deleteNode(root);
	}

	void deleteNode(Node<T> * node)
	{
		if (node == nullptr) return;
		deleteNode(node->left);
		deleteNode(node->right);
		delete node;
	}

	T x_() const
	{
		return root->x;
	}

	Node<T> * left_() const
	{
		return root->left;
	}

	Node<T> * right_() const
	{
		return root->right;
	}

	Node<T> * root_() const
	{
		return root;
	}

	void insert(const T& value)
	{
		insert(root, value);
	}

	void insert(Node<T>* & node, const T& value)
	{
		if (node)
		{
			if (value < node->x)
				insert(node->left, value);
			else if (value > node->x)
				insert(node->right, value);
			else return;
		}
		else node = new Node<T>(value);
	}

	Node<T> * search(const T& x)const
	{
		Node<T> * curEl = root;
		while (curEl != nullptr)
		{
			if (curEl->x == x)
				break;
			else
			{
				if (x > curEl->x)
					curEl = curEl->right;
				else curEl = curEl->left;
			}
		}
		return curEl;
	}

	bool check_search(const T& x)
	{
		Node<T> * node;
		node = search(x);
		if (node != nullptr)
			return true;
		else return false;
	}

	void fIn(const string filename)
	{
		ifstream fin;
		unsigned int k;
		fin.open(filename);
		if (!fin.is_open())
			cout << "The file isn't find" << endl;
		else
		{
			deleteNode(root);
			if (fin.eof()) return;
			else
			{
				fin >> k;
				T newEl;
				for (unsigned int i = 0; i < k; ++i)
				{
					fin >> newEl;
					insert(newEl);
				}
			}
			fin.close();
		}
	}

	unsigned int size(Node<T> * node)const
	{
		unsigned int size_ = 0;
		if (node != nullptr)
			size_ = size(node->left) + 1 + size(node->right);
		return size_;
	}

	void out_to_file(const string filename)const
	{
		ofstream fout;
		fout.open(filename);
		if (!fout.is_open())
			cout << "The file isn't find" << endl;
		else
		{
			unsigned int size_ = size(root);
			if (size_ == 0)
				return;
			fout << size_ << "\t";
			fOut(root, fout);
			fout.close();
		}
	}

	void fOut(Node<T> * node, ostream&stream)const
	{
		if (node != nullptr)
		{
			fOut(node->left, stream);
			stream << node->x << " ";
			fOut(node->right, stream);
		}
	}

	void out(ostream & stream)const
	{
		Out(root, stream, 0);
	}

	void Out(Node<T> * node, ostream&stream, size_t level)const
	{
		Node<T> * curEl = node;
		if (curEl != nullptr)
		{
			Out(curEl->right, stream, level + 1);
			for (unsigned int i = 0; i < level; ++i)
				stream << '-';
			stream << curEl->x << endl;
			Out(curEl->left, stream, level + 1);
		}
	}

	Node<T> * prev_(const T& x)
	{
		return prev_(root, x);
	}

	Node<T> * prev_(Node<T> * & node, const T& x)
	{
		Node<T> * cur = node;
		if (check_search(x))
		{
			if (x < cur->x)
			{
				if (x != cur->left->x)
					prev_(cur->left, x);
				else return cur;
			}
			else if (x > cur->x)
			{
				if (x != cur->right->x)
					prev_(cur->right, x);
				else return cur;
			}
			else return nullptr;
		}
		else return nullptr;
	}

	void deleteX(const T& x)
	{
		Node<T> * curEl = search(x);
		Node<T> * prev = prev_(x);
		if (curEl != nullptr)
		{
			if (curEl->left == nullptr && curEl->right == nullptr)
			{
				if (prev->left == curEl)
					prev->left = nullptr;
				if (prev->right == curEl)
					prev->right = nullptr;
			}
			else if (curEl->left != nullptr&&curEl->right == nullptr)
			{
				if (curEl->x < prev->x)
					prev->left = curEl->left;
				else prev->right = curEl->left;
			}
			else if (curEl->right != nullptr)
			{
				Node<T> * min = curEl->right;
				while (min->left)
					min = min->left;
				T a = min->x;
				deleteX(min->x);
				curEl->x = a;
			}
		}
		else return;
	}
};
<commit_msg>Update BinaryTree.hpp<commit_after>#include <iostream>
#include <string>
#include <fstream>
using namespace std;

template<typename T>
struct Node
{
	T x;
	Node<T> * left;
	Node<T> * right;
	Node(T const& value) : x{ value }, left{ nullptr }, right{ nullptr } {}
};

template<typename T>
class Tree
{
private:
	Node<T> * root;
public:
	Tree()
	{
		root  = nullptr;
	}

	~Tree()
	{
		deleteNode(root);
	}

	void deleteNode(Node<T> * node)
	{
		if (node == nullptr) return;
		deleteNode(node->left);
		deleteNode(node->right);
		delete node;
	}

	T x_() const
	{
		return root->x;
	}

	Node<T> * left_() const
	{
		return root->left;
	}

	Node<T> * right_() const
	{
		return root->right;
	}

	Node<T> * root_() const
	{
		return root;
	}

	void insert(const T& value)
	{
		insert(root, value);
	}

	void insert(Node<T>* & node, const T& value)
	{
		if (node)
		{
			try
			{
				if (value == node->x)
					throw 2;
				if (value < node->x)
					insert(node->left, value);
				else if (value > node->x)
					insert(node->right, value);
			}
			catch (int i)
			{
				cout << "This element is saved in the tree\n";
			}
		}
		else node = new Node<T>(value);
	}

	Node<T> * search(const T& x)const
	{
		Node<T> * curEl = root;
		while (curEl != nullptr)
		{
			if (curEl->x == x)
				break;
			else
			{
				if (x > curEl->x)
					curEl = curEl->right;
				else curEl = curEl->left;
			}
		}
		return curEl;
	}

	bool check_search(const T& x)
	{
		Node<T> * node;
		node = search(x);
		if (node != nullptr)
			return true;
		else return false;
	}

	void fIn(const string filename)
	{
		ifstream fin;
		unsigned int k;
		fin.open(filename);
		try
		{
			if (!fin.is_open())
				throw 4;
		}
		catch (int i)
		{
			cout << "The file isn't find" << endl;
		}
		else
		{
			deleteNode(root);
			if (fin.eof()) return;
			else
			{
				fin >> k;
				T newEl;
				for (unsigned int i = 0; i < k; ++i)
				{
					fin >> newEl;
					insert(newEl);
				}
			}
			fin.close();
		}
	}

	unsigned int size(Node<T> * node)const
	{
		unsigned int size_ = 0;
		if (node != nullptr)
			size_ = size(node->left) + 1 + size(node->right);
		return size_;
	}

	void out_to_file(const string filename)const
	{
		ofstream fout;
		fout.open(filename);
		try
		{
			if (!fout.is_open())
				throw 4;
		}
		catch (int i)
		{
			cout << "The file isn't find" << endl;
		}
		else
		{
			unsigned int size_ = size(root);
			try
			{
				if (size_ == 0)
					throw 1;
				fout << size_ << "\t";
				fOut(root, fout);
				fout.close();
			}
			catch (int i)
			{
				cout << "The tree is empty\n";
			}
		}
	}

	void fOut(Node<T> * node, ostream&stream)const
	{
		if (node != nullptr)
		{
			fOut(node->left, stream);
			stream << node->x << " ";
			fOut(node->right, stream);
		}
	}

	void out(ostream & stream)const
	{
		Out(root, stream, 0);
	}

	void Out(Node<T> * node, ostream&stream, size_t level)const
	{
		Node<T> * curEl = node;
		if (curEl != nullptr)
		{
			Out(curEl->right, stream, level + 1);
			for (unsigned int i = 0; i < level; ++i)
				stream << '-';
			stream << curEl->x << endl;
			Out(curEl->left, stream, level + 1);
		}
	}

	Node<T> * prev_(const T& x)
	{
		return prev_(root, x);
	}

	Node<T> * prev_(Node<T> * & node, const T& x)
	{
		Node<T> * cur = node;
		if (check_search(x))
		{
			if (x < cur->x)
			{
				if (x != cur->left->x)
					prev_(cur->left, x);
				else return cur;
			}
			else if (x > cur->x)
			{
				if (x != cur->right->x)
					prev_(cur->right, x);
				else return cur;
			}
			else return nullptr;
		}
		else return nullptr;
	}

	void deleteX(const T& x)
	{
		try
		{
			if (check_search(x) == false)
				throw 3;
			Node<T> * curEl = search(x);
			Node<T> * prev = prev_(x);
			if (curEl->left == nullptr && curEl->right == nullptr)
			{
				if (prev->left == curEl)
					prev->left = nullptr;
				if (prev->right == curEl)
					prev->right = nullptr;
			}
			else if (curEl->left != nullptr&&curEl->right == nullptr)
			{
				if (curEl->x < prev->x)
					prev->left = curEl->left;
				else prev->right = curEl->left;
			}
			else if (curEl->right != nullptr)
			{
				Node<T> * min = curEl->right;
				while (min->left)
					min = min->left;
				T a = min->x;
				deleteX(min->x);
				curEl->x = a;
			}
		}
		catch (int i)
		{
			cout << "There isn't this element in the tree\n";
		}
	}
};
<|endoftext|>


<commit_before>#pragma once

// Set Includes path
// C:\Libraries\OculusSDK\LibOVR\Include
// C:\Libraries\OculusSDK\LibOVR\Src

// Set LibPath
// C:\Libraries\OculusSDK\LibOVR\Lib\<Platform: ex Win32>\<Runtime ex:VS2010>

// ȉ̃CuKv?
//libovr64.lib
//winmm.lib
//winsock2.lib

//#ifdef DEBUG
//#pragma comment(lib, "libovrd64.lib")
//#else
//#pragma comment(lib, "libovr64.lib")
//#endif

#include <stdexcept>
#include <utility>
#include <OVR.h>
#include <OVR_CAPI_GL.h>
#include <vlCore/Vector2.hpp>
#include <vlCore/Matrix4.hpp>
#include <vlCore/math_utils.hpp>
#include <vlGraphics/Texture.hpp>
#include <vlGraphics/Framebuffer.hpp>
#include <vlGraphics/FramebufferObject.hpp>
#include <vlGraphics/OpenGLContext.hpp>

class OVRManager
{
public:
    OVRManager()
    {
    }

    ~OVRManager()
    {
    }
    static void init()
    {
        ovr_Initialize();
        ovr_InitializeRenderingShim();
    }

    static void finish()
    {
        ovr_Shutdown();
    }

    void prepereOVR(HWND hWnd, HDC dc, bool directMode= true)
    {
        createDevice();
        configureTracking();
        configureRendering(hWnd, dc);
        ovrHmd_SetEnabledCaps(m_hmd, ovrHmdCap_LowPersistence | ovrHmdCap_DynamicPrediction );
        if (directMode)
        {
            directRenderingTo(hWnd);
        }
    }

    void getHmdPose(ovrPosef outEyePoses[2])
    {
        ovrTrackingState outHmdTrackingState;
        getHmdPose(outEyePoses, &outHmdTrackingState);
    }

    void getHmdPose(ovrPosef outEyePoses[2], ovrTrackingState* outHmdTrackingState, unsigned int frameIdx = 0)
    {

        ovrVector3f hmdToEyeViewOffset[2] = {
            getEyeRenderDesc(ovrEye_Left).HmdToEyeViewOffset,
            getEyeRenderDesc(ovrEye_Right).HmdToEyeViewOffset,
        };
        ovrHmd_GetEyePoses(m_hmd, frameIdx, hmdToEyeViewOffset,
                                   outEyePoses,
                                   outHmdTrackingState);
    }

    ovrMatrix4f getEyeProjection(ovrEyeType eye, float nearPlane = 0.01f, float farPlane = 10000.0f)
    {
        return ovrMatrix4f_Projection(getEyeRenderDesc(eye).Fov, nearPlane, farPlane, true);
    }

    ovrEyeRenderDesc getEyeRenderDesc(ovrEyeType t)
    {
        return ovrHmd_GetRenderDesc(m_hmd, t, m_hmd->DefaultEyeFov[t]);
    }

    ovrRecti getEyeRenderViewport(int idx)
    {
        ovrRecti viewport;
        if (idx == 0)
        {
            viewport.Pos = OVR::Vector2i(0, 0);
            viewport.Size = OVR::Sizei((getRenderTargetSizeOvr().w + 1)/2, getRenderTargetSizeOvr().h);
            return viewport;
        }
        else
        {
            viewport.Pos = OVR::Vector2i((getRenderTargetSizeOvr().w + 1) / 2, 0);
            viewport.Size = OVR::Sizei((getRenderTargetSizeOvr().w + 1)/2, getRenderTargetSizeOvr().h);
            return viewport;
        }
    }

    vl::ref<vl::FramebufferObject> createRenderTarget(vl::OpenGLContext* ctx, bool depth, bool stencil)
    {
        auto targetTex = getRenderTexture();
        vl::ref<vl::FramebufferObject> fbo = ctx->createFramebufferObject(targetTex->width(), targetTex->height());
        fbo->addTextureAttachment(
            vl::AP_COLOR_ATTACHMENT0,
            new vl::FBOTexture2DAttachment(
                targetTex.get(), 0, vl::ETex2DTarget::T2DT_TEXTURE_2D));
        if (depth && stencil)
        {
            if (vl::Has_GL_EXT_packed_depth_stencil)
            {
                vl::Log::print(vl::Say("with packed depth stencil\n"));
                fbo->addDepthStencilAttachment(new vl::FBODepthStencilBufferAttachment());
            }
            else
            {
                vl::Log::print(vl::Say("without packed depth stencil\n"));
                fbo->addDepthAttachment(new vl::FBODepthBufferAttachment(vl::DBF_DEPTH_COMPONENT24));
                fbo->addStencilAttachment(new vl::FBOStencilBufferAttachment(vl::SBF_STENCIL_INDEX8));
            }
        }
        else
        {
            if (depth)
            {
                fbo->addDepthAttachment(new vl::FBODepthBufferAttachment(vl::DBF_DEPTH_COMPONENT24));
            }
            if (stencil)
            {
                fbo->addStencilAttachment(new vl::FBOStencilBufferAttachment(vl::SBF_STENCIL_INDEX8));
            }
        }
        return fbo;

    }

    ovrGLTexture getEyeTexture(int eye)
    {
        auto tex = getRenderTexture();
        ovrGLTexture ovrTex;
        ovrTex.OGL.Header.API = ovrRenderAPI_OpenGL;
        ovrTex.OGL.Header.TextureSize = getRenderTargetSizeOvr();
        ovrTex.OGL.Header.RenderViewport = getEyeRenderViewport(eye);
        ovrTex.OGL.TexId = tex->handle();
        return ovrTex;
    }
    std::vector<ovrGLTexture> getEyeTexture()
    {
        auto tex = getRenderTexture();
        ovrGLTexture ovrTex[2] = {
            getEyeTexture(0),
            getEyeTexture(1)
        };
        return std::vector<ovrGLTexture>(ovrTex, ovrTex+2);
    }

    vl::mat4 getTrackingState()
    {
        ovrTrackingState ts = ovrHmd_GetTrackingState(m_hmd, ovr_GetTimeInSeconds());
        if (ts.StatusFlags & (ovrStatus_OrientationTracked | ovrStatus_PositionTracked))
        {
            ovrPosef pose = ts.HeadPose.ThePose;
            vl::mat4 tracking;
            auto m = OVR::Matrix4f(pose);
            return vl::mat4(&(m.M[0][0]));
        }
        else
        {
            return vl::mat4();
        }
    }

    void dismissHSW()
    {
        // Health and Safety Warning display state.
        ovrHSWDisplayState hswDisplayState;
        ovrHmd_GetHSWDisplayState(m_hmd, &hswDisplayState);
        if (hswDisplayState.Displayed)
        {
            // Dismiss the warning if the user pressed the appropriate key or if the user
            // is tapping the side of the HMD.
            // If the user has requested to dismiss the warning via keyboard or controller input...
            {
                // Detect a moderate tap on the side of the HMD.
                ovrTrackingState ts = ovrHmd_GetTrackingState(m_hmd, ovr_GetTimeInSeconds());
                if (ts.StatusFlags & ovrStatus_OrientationTracked)
                {
                    const OVR::Vector3f v(
                        ts.RawSensorData.Accelerometer.x,
                        ts.RawSensorData.Accelerometer.y,
                        ts.RawSensorData.Accelerometer.z);
                    // Arbitrary value and representing moderate tap on the side of the DK2 Rift.
                    if (v.LengthSq() > 250.f)
                        ovrHmd_DismissHSWDisplay(m_hmd);
                }
            }
        }
    }

    ovrEyeType getEyeRenderOrder(int eyeIndex)
    {
        return m_hmd->EyeRenderOrder[eyeIndex];
    }

    ovrHmd getHmd()
    {
        return m_hmd;
    }

    void directRenderingTo(HWND window)
    {
        ovrHmd_AttachToWindow(m_hmd, window, nullptr, nullptr);
    }

    void doRenderHmd(std::function<void(ovrEyeType, ovrRecti const& viewport, OVR::Matrix4f const& proj)> renderCallback)
    {
        dismissHSW();
        using namespace OVR;
        ovrPosef headPose[2];
        getHmdPose(headPose);
        for (int eyeIndex = 0; eyeIndex < ovrEye_Count; eyeIndex++)
        {
            ovrEyeType eye = getEyeRenderOrder(eyeIndex);
            Quatf orientation = Quatf(headPose[eye].Orientation);

            Matrix4f proj = getEyeProjection(eye);
            proj.Transpose();
            // * Test code *
            // Assign quaternion result directly to view (translation is ignored).
            //Matrix4f view = Matrix4f(orientation.Inverted()) * Matrix4f::Translation(-WorldEyePos);
            auto renderViewport = getEyeRenderViewport(eye);
            renderCallback(eye, renderViewport, proj);
        }

        auto eyeTex = getEyeTexture();
        ovrHmd_EndFrame(getHmd(), headPose, (const ovrTexture*)eyeTex.data());
    }

    vl::uvec2 getRenderTargetSize()
    {
        // Configure Stereo settings.
        ovrSizei recommenedTex0Size = ovrHmd_GetFovTextureSize(m_hmd, ovrEye_Left,
            m_hmd->DefaultEyeFov[0], 1.0f);
        ovrSizei recommenedTex1Size = ovrHmd_GetFovTextureSize(m_hmd, ovrEye_Right,
            m_hmd->DefaultEyeFov[1], 1.0f);
        ovrSizei renderTargetSize;
        renderTargetSize.w = recommenedTex0Size.w + recommenedTex1Size.w;
        renderTargetSize.h = std::max( recommenedTex0Size.h, recommenedTex1Size.h );
        const int eyeRenderMultisample = 1;
        m_renderTargetSize = vl::uvec2(renderTargetSize.w, renderTargetSize.h);
        return m_renderTargetSize;
    }

private:
    void createDevice()
    {
        m_hmd = ovrHmd_Create(0);
        if (!m_hmd)
        {
            throw std::runtime_error("can't initialized OVR");
        }
    }

    void destroyDevice()
    {
        if (m_hmd)
        {
            ovrHmd_Destroy(m_hmd);
        }
    }
    void configureTracking()
    {
        ovrHmd_ConfigureTracking(m_hmd, ovrTrackingCap_Orientation |
            ovrTrackingCap_MagYawCorrection |
            ovrTrackingCap_Position, 0);
    }

    void configureRendering(HWND hWnd, HDC dc)
    {
        // Configure OpenGL.
        // Initialize ovrEyeRenderDesc struct.
        ovrFovPort eyeFov[2];
        std::memcpy(eyeFov, m_hmd->DefaultEyeFov, sizeof(eyeFov));
        ovrGLConfig cfg;
        memset(&cfg, 0, sizeof(cfg));
        cfg.OGL.Header.API = ovrRenderAPI_OpenGL;
        cfg.OGL.Header.RTSize.w = m_hmd->Resolution.w;
        cfg.OGL.Header.RTSize.h = m_hmd->Resolution.h;
        cfg.OGL.Header.Multisample = 0;
        cfg.OGL.Window = hWnd;
        cfg.OGL.DC = dc;
        ovrEyeRenderDesc eyeRenderDesc[2];
        ovrBool result = ovrHmd_ConfigureRendering(m_hmd, &cfg.Config, ovrDistortionCap_Chromatic |
                                                        ovrDistortionCap_TimeWarp |
                                                        ovrDistortionCap_Overdrive,
                                                        eyeFov, eyeRenderDesc);
    }
    ovrSizei getRenderTargetSizeOvr()
    {
        // Configure Stereo settings.
        ovrSizei recommenedTex0Size = ovrHmd_GetFovTextureSize(m_hmd, ovrEye_Left,
            m_hmd->DefaultEyeFov[0], 1.0f);
        ovrSizei recommenedTex1Size = ovrHmd_GetFovTextureSize(m_hmd, ovrEye_Right,
            m_hmd->DefaultEyeFov[1], 1.0f);
        ovrSizei renderTargetSize;
        renderTargetSize.w = recommenedTex0Size.w + recommenedTex1Size.w;
        renderTargetSize.h = std::max( recommenedTex0Size.h, recommenedTex1Size.h );
        const int eyeRenderMultisample = 1;
        return renderTargetSize;
    }
    vl::ref<vl::Texture> getRenderTexture()
    {
        if (mTargetTex.get())
        {
            return mTargetTex;
        }
        auto texSize = getRenderTargetSize();
        mTargetTex = new vl::Texture();
        mTargetTex->createTexture2D(texSize.x(), texSize.y(), vl::TF_RGBA, false);
        glBindTexture(GL_TEXTURE_2D, mTargetTex->handle());
        glTexImage2D(GL_TEXTURE_2D, 0, GL_ABGR_EXT, texSize.x(), texSize.y(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
        return mTargetTex;
    }

    vl::uvec2 m_renderTargetSize;
    vl::ref<vl::Texture> mTargetTex;
    ovrHmd m_hmd;
};
<commit_msg>fixed for OVR SDK 0.4.4<commit_after>#pragma once

#include <stdexcept>
#include <utility>
#include <OVR.h>
#include <OVR_CAPI_GL.h>
#include <vlCore/Vector2.hpp>
#include <vlCore/Matrix4.hpp>
#include <vlCore/math_utils.hpp>
#include <vlGraphics/Texture.hpp>
#include <vlGraphics/Framebuffer.hpp>
#include <vlGraphics/FramebufferObject.hpp>
#include <vlGraphics/OpenGLContext.hpp>

class OVRManager
{
public:
    OVRManager()
    {
    }

    ~OVRManager()
    {
    }
    static void init()
    {
        ovr_Initialize();
    }

    static void finish()
    {
        ovr_Shutdown();
    }

    void prepereOVR(HWND hWnd, HDC dc, bool directMode= true)
    {
        createDevice();
        configureTracking();
        configureRendering(hWnd, dc);
        ovrHmd_SetEnabledCaps(m_hmd, ovrHmdCap_LowPersistence | ovrHmdCap_DynamicPrediction);
        if (directMode)
        {
            directRenderingTo(hWnd);
        }
    }

    void getHmdPose(ovrPosef outEyePoses[2])
    {
        ovrTrackingState outHmdTrackingState;
        getHmdPose(outEyePoses, &outHmdTrackingState);
    }

    void getHmdPose(ovrPosef outEyePoses[2], ovrTrackingState* outHmdTrackingState, unsigned int frameIdx = 0)
    {

        ovrVector3f hmdToEyeViewOffset[2] = {
            getEyeRenderDesc(ovrEye_Left).HmdToEyeViewOffset,
            getEyeRenderDesc(ovrEye_Right).HmdToEyeViewOffset,
        };
        ovrHmd_GetEyePoses(m_hmd, frameIdx, hmdToEyeViewOffset,
                                   outEyePoses,
                                   outHmdTrackingState);
    }

    ovrMatrix4f getEyeProjection(ovrEyeType eye, float nearPlane = 0.01f, float farPlane = 10000.0f)
    {
        return ovrMatrix4f_Projection(getEyeRenderDesc(eye).Fov, nearPlane, farPlane, true);
    }

    ovrEyeRenderDesc getEyeRenderDesc(ovrEyeType t)
    {
        return ovrHmd_GetRenderDesc(m_hmd, t, m_hmd->DefaultEyeFov[t]);
    }

    ovrRecti getEyeRenderViewport(int idx)
    {
        ovrRecti viewport;
        if (idx == 0)
        {
            viewport.Pos = OVR::Vector2i(0, 0);
            viewport.Size = OVR::Sizei((getRenderTargetSizeOvr().w + 1)/2, getRenderTargetSizeOvr().h);
            return viewport;
        }
        else
        {
            viewport.Pos = OVR::Vector2i((getRenderTargetSizeOvr().w + 1) / 2, 0);
            viewport.Size = OVR::Sizei((getRenderTargetSizeOvr().w + 1)/2, getRenderTargetSizeOvr().h);
            return viewport;
        }
    }

    vl::ref<vl::FramebufferObject> createRenderTarget(vl::OpenGLContext* ctx, bool depth, bool stencil)
    {
        auto targetTex = getRenderTexture();
        vl::ref<vl::FramebufferObject> fbo = ctx->createFramebufferObject(targetTex->width(), targetTex->height());
        fbo->addTextureAttachment(
            vl::AP_COLOR_ATTACHMENT0,
            new vl::FBOTexture2DAttachment(
                targetTex.get(), 0, vl::ETex2DTarget::T2DT_TEXTURE_2D));
        if (depth && stencil)
        {
            if (vl::Has_GL_EXT_packed_depth_stencil)
            {
                vl::Log::print(vl::Say("with packed depth stencil\n"));
                fbo->addDepthStencilAttachment(new vl::FBODepthStencilBufferAttachment());
            }
            else
            {
                vl::Log::print(vl::Say("without packed depth stencil\n"));
                fbo->addDepthAttachment(new vl::FBODepthBufferAttachment(vl::DBF_DEPTH_COMPONENT24));
                fbo->addStencilAttachment(new vl::FBOStencilBufferAttachment(vl::SBF_STENCIL_INDEX8));
            }
        }
        else
        {
            if (depth)
            {
                fbo->addDepthAttachment(new vl::FBODepthBufferAttachment(vl::DBF_DEPTH_COMPONENT24));
            }
            if (stencil)
            {
                fbo->addStencilAttachment(new vl::FBOStencilBufferAttachment(vl::SBF_STENCIL_INDEX8));
            }
        }
        return fbo;

    }

    ovrGLTexture getEyeTexture(int eye)
    {
        auto tex = getRenderTexture();
        ovrGLTexture ovrTex;
        ovrTex.OGL.Header.API = ovrRenderAPI_OpenGL;
        ovrTex.OGL.Header.TextureSize = getRenderTargetSizeOvr();
        ovrTex.OGL.Header.RenderViewport = getEyeRenderViewport(eye);
        ovrTex.OGL.TexId = tex->handle();
        return ovrTex;
    }
    std::array<ovrGLTexture, 2> getEyeTextures()
    {
        auto tex = getRenderTexture();
        std::array<ovrGLTexture, 2> ovrTex;
        ovrTex[0] = getEyeTexture(0);
        ovrTex[1] = getEyeTexture(1);
        return ovrTex;
    }

    vl::mat4 getTrackingState()
    {
        ovrTrackingState ts = ovrHmd_GetTrackingState(m_hmd, ovr_GetTimeInSeconds());
        if (ts.StatusFlags & (ovrStatus_OrientationTracked | ovrStatus_PositionTracked))
        {
            ovrPosef pose = ts.HeadPose.ThePose;
            vl::mat4 tracking;
            auto m = OVR::Matrix4f(pose);
            return vl::mat4(&(m.M[0][0]));
        }
        else
        {
            return vl::mat4();
        }
    }

    void dismissHSW()
    {
        // Health and Safety Warning display state.
        ovrHSWDisplayState hswDisplayState;
        ovrHmd_GetHSWDisplayState(m_hmd, &hswDisplayState);
        if (hswDisplayState.Displayed)
        {
            // Dismiss the warning if the user pressed the appropriate key or if the user
            // is tapping the side of the HMD.
            // If the user has requested to dismiss the warning via keyboard or controller input...
            {
                // Detect a moderate tap on the side of the HMD.
                ovrTrackingState ts = ovrHmd_GetTrackingState(m_hmd, ovr_GetTimeInSeconds());
                if (ts.StatusFlags & ovrStatus_OrientationTracked)
                {
                    const OVR::Vector3f v(
                        ts.RawSensorData.Accelerometer.x,
                        ts.RawSensorData.Accelerometer.y,
                        ts.RawSensorData.Accelerometer.z);
                    // Arbitrary value and representing moderate tap on the side of the DK2 Rift.
                    if (v.LengthSq() > 250.f)
                        ovrHmd_DismissHSWDisplay(m_hmd);
                }
            }
        }
    }

    ovrEyeType getEyeRenderOrder(int eyeIndex)
    {
        return m_hmd->EyeRenderOrder[eyeIndex];
    }

    ovrHmd getHmd()
    {
        return m_hmd;
    }

    void directRenderingTo(HWND window)
    {
        ovrHmd_AttachToWindow(m_hmd, window, nullptr, nullptr);
    }

    void doRenderHmd(std::function<void(ovrEyeType, ovrRecti const& viewport, OVR::Matrix4f const& proj)> renderCallback)
    {
        using namespace OVR;
        ovrPosef headPose[2];
        getHmdPose(headPose);
        dismissHSW();
        for (int eyeIndex = 0; eyeIndex < ovrEye_Count; eyeIndex++)
        {
            ovrEyeType eye = getEyeRenderOrder(eyeIndex);
            Quatf orientation = Quatf(headPose[eye].Orientation);

            Matrix4f proj = getEyeProjection(eye);
            proj.Transpose();
            // * Test code *
            // Assign quaternion result directly to view (translation is ignored).
            //Matrix4f view = Matrix4f(orientation.Inverted()) * Matrix4f::Translation(-WorldEyePos);
            auto renderViewport = getEyeRenderViewport(eye);
            renderCallback(eye, renderViewport, proj);
        }

        auto eyeTex = getEyeTextures();
        ovrHmd_EndFrame(getHmd(), headPose, (const ovrTexture*)eyeTex.data());
    }

private:
    void createDevice()
    {
        m_hmd = ovrHmd_Create(0);
        if (!m_hmd)
        {
            throw std::runtime_error("can't initialized OVR");
        }
    }

    void destroyDevice()
    {
        if (m_hmd)
        {
            ovrHmd_Destroy(m_hmd);
        }
    }
    void configureTracking()
    {
        ovrHmd_ConfigureTracking(m_hmd, ovrTrackingCap_Orientation |
            ovrTrackingCap_MagYawCorrection |
            ovrTrackingCap_Position, 0);
    }

    void configureRendering(HWND hWnd, HDC dc)
    {
        // Configure OpenGL.
        // Initialize ovrEyeRenderDesc struct.
        ovrFovPort eyeFov[2];
        std::memcpy(eyeFov, m_hmd->DefaultEyeFov, sizeof(eyeFov));
        ovrGLConfig cfg;
        memset(&cfg, 0, sizeof(cfg));
        cfg.OGL.Header.API = ovrRenderAPI_OpenGL;
        cfg.OGL.Header.BackBufferSize.w = m_hmd->Resolution.w;
        cfg.OGL.Header.BackBufferSize.h = m_hmd->Resolution.h;
        cfg.OGL.Header.Multisample = 0;
        cfg.OGL.Window = hWnd;
        cfg.OGL.DC = dc;
        ovrEyeRenderDesc eyeRenderDesc[2];
        ovrBool result = ovrHmd_ConfigureRendering(m_hmd, &cfg.Config, ovrDistortionCap_Chromatic |
                                                        ovrDistortionCap_TimeWarp |
                                                        ovrDistortionCap_Overdrive,
                                                        eyeFov, eyeRenderDesc);
    }
    vl::uvec2 getRenderTargetSize()
    {
        // Configure Stereo settings.
        ovrSizei recommenedTex0Size = ovrHmd_GetFovTextureSize(m_hmd, ovrEye_Left,
            m_hmd->DefaultEyeFov[0], 1.0f);
        ovrSizei recommenedTex1Size = ovrHmd_GetFovTextureSize(m_hmd, ovrEye_Right,
            m_hmd->DefaultEyeFov[1], 1.0f);
        ovrSizei renderTargetSize;
        renderTargetSize.w = recommenedTex0Size.w + recommenedTex1Size.w;
        renderTargetSize.h = std::max( recommenedTex0Size.h, recommenedTex1Size.h );
        const int eyeRenderMultisample = 1;
        m_renderTargetSize = vl::uvec2(renderTargetSize.w, renderTargetSize.h);
        return m_renderTargetSize;
    }

    ovrSizei getRenderTargetSizeOvr()
    {
        // Configure Stereo settings.
        ovrSizei recommenedTex0Size = ovrHmd_GetFovTextureSize(m_hmd, ovrEye_Left,
            m_hmd->DefaultEyeFov[0], 1.0f);
        ovrSizei recommenedTex1Size = ovrHmd_GetFovTextureSize(m_hmd, ovrEye_Right,
            m_hmd->DefaultEyeFov[1], 1.0f);
        ovrSizei renderTargetSize;
        renderTargetSize.w = recommenedTex0Size.w + recommenedTex1Size.w;
        renderTargetSize.h = std::max( recommenedTex0Size.h, recommenedTex1Size.h );
        const int eyeRenderMultisample = 1;
        return renderTargetSize;
    }
    vl::ref<vl::Texture> getRenderTexture()
    {
        if (mTargetTex.get())
        {
            return mTargetTex;
        }
        auto texSize = getRenderTargetSize();
        mTargetTex = new vl::Texture();
        mTargetTex->createTexture2D(texSize.x(), texSize.y(), vl::TF_RGB, false);
        return mTargetTex;
    }

    vl::uvec2 m_renderTargetSize;
    vl::ref<vl::Texture> mTargetTex;
    ovrHmd m_hmd;
};<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#ifndef AST_STRUCT_H
#define AST_STRUCT_H

#include <boost/fusion/include/adapt_struct.hpp>

#include "ast/Deferred.hpp"

namespace eddic {

namespace ast {

struct ASTStruct {

};

typedef Deferred<ASTStruct> Struct;

} //end of ast

} //end of eddic

//Adapt the struct for the AST
BOOST_FUSION_ADAPT_STRUCT(
    eddic::ast::Struct
)

#endif
<commit_msg>A struct can have any number of member declarations<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#ifndef AST_STRUCT_H
#define AST_STRUCT_H

#include <vector>

#include <boost/fusion/include/adapt_struct.hpp>

#include "ast/Deferred.hpp"
#include "ast/MemberDeclaration.hpp"

namespace eddic {

namespace ast {

struct ASTStruct {
    std::vector<MemberDeclaration> declarations;
};

typedef Deferred<ASTStruct> Struct;

} //end of ast

} //end of eddic

//Adapt the struct for the AST
BOOST_FUSION_ADAPT_STRUCT(
    eddic::ast::Struct,
    (std::vector<eddic::ast::MemberDeclaration>, Content->declarations)
)

#endif
<|endoftext|>


<commit_before>// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/tools/quic/quic_spdy_server_stream.h"

#include "base/strings/string_piece.h"
#include "net/quic/quic_connection.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "net/tools/quic/test_tools/quic_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"

using base::StringPiece;
using net::tools::test::MockConnection;
using net::test::MockSession;

namespace net {
namespace tools {
namespace test {
namespace {

class QuicSpdyServerStreamTest : public ::testing::Test {
 public:
  QuicSpdyServerStreamTest()
      : connection_(new MockConnection(1, IPEndPoint(), false)),
        session_(connection_, true),
        stream_(1, &session_) {
  }

  MockConnection* connection_;
  MockSession session_;
  QuicSpdyServerStream stream_;
};

TEST_F(QuicSpdyServerStreamTest, InvalidHeadersWithFin) {
  char arr[] = {
    0x00, 0x00, 0x00, 0x05,  // ....
    0x00, 0x00, 0x00, 0x05,  // ....
    0x3a, 0x68, 0x6f, 0x73,  // :hos
    0x74, 0x00, 0x00, 0x00,  // t...
    0x00, 0x00, 0x00, 0x00,  // ....
    0x07, 0x3a, 0x6d, 0x65,  // .:me
    0x74, 0x68, 0x6f, 0x64,  // thod
    0x00, 0x00, 0x00, 0x03,  // ....
    0x47, 0x45, 0x54, 0x00,  // GET.
    0x00, 0x00, 0x05, 0x3a,  // ...:
    0x70, 0x61, 0x74, 0x68,  // path
    0x00, 0x00, 0x00, 0x04,  // ....
    0x2f, 0x66, 0x6f, 0x6f,  // /foo
    0x00, 0x00, 0x00, 0x07,  // ....
    0x3a, 0x73, 0x63, 0x68,  // :sch
    0x65, 0x6d, 0x65, 0x00,  // eme.
    0x00, 0x00, 0x00, 0x00,  // ....
    0x00, 0x00, 0x08, 0x3a,  // ...:
    0x76, 0x65, 0x72, 0x73,  // vers
    0x96, 0x6f, 0x6e, 0x00,  // <i(69)>on.
    0x00, 0x00, 0x08, 0x48,  // ...H
    0x54, 0x54, 0x50, 0x2f,  // TTP/
    0x31, 0x2e, 0x31,        // 1.1
  };
  QuicStreamFrame frame(1, true, 0, StringPiece(arr, arraysize(arr)));
  // Verify that we don't crash when we get a invalid headers in stream frame.
  stream_.OnStreamFrame(frame);
}

}  // namespace
}  // namespace test
}  // namespace tools
}  // namespace net
<commit_msg>Build fix for quic_unittests.<commit_after>// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/tools/quic/quic_spdy_server_stream.h"

#include "base/strings/string_piece.h"
#include "net/quic/quic_connection.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "net/tools/quic/test_tools/quic_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"

using base::StringPiece;
using net::tools::test::MockConnection;
using net::test::MockSession;

namespace net {
namespace tools {
namespace test {
namespace {

class QuicSpdyServerStreamTest : public ::testing::Test {
 public:
  QuicSpdyServerStreamTest()
      : connection_(new MockConnection(1, IPEndPoint(), false)),
        session_(connection_, true),
        stream_(1, &session_) {
  }

  MockConnection* connection_;
  MockSession session_;
  QuicSpdyServerStream stream_;
};

TEST_F(QuicSpdyServerStreamTest, InvalidHeadersWithFin) {
  char arr[] = {
    0x00, 0x00, 0x00, 0x05,  // ....
    0x00, 0x00, 0x00, 0x05,  // ....
    0x3a, 0x68, 0x6f, 0x73,  // :hos
    0x74, 0x00, 0x00, 0x00,  // t...
    0x00, 0x00, 0x00, 0x00,  // ....
    0x07, 0x3a, 0x6d, 0x65,  // .:me
    0x74, 0x68, 0x6f, 0x64,  // thod
    0x00, 0x00, 0x00, 0x03,  // ....
    0x47, 0x45, 0x54, 0x00,  // GET.
    0x00, 0x00, 0x05, 0x3a,  // ...:
    0x70, 0x61, 0x74, 0x68,  // path
    0x00, 0x00, 0x00, 0x04,  // ....
    0x2f, 0x66, 0x6f, 0x6f,  // /foo
    0x00, 0x00, 0x00, 0x07,  // ....
    0x3a, 0x73, 0x63, 0x68,  // :sch
    0x65, 0x6d, 0x65, 0x00,  // eme.
    0x00, 0x00, 0x00, 0x00,  // ....
    0x00, 0x00, 0x08, 0x3a,  // ...:
    0x76, 0x65, 0x72, 0x73,  // vers
    '\x96', 0x6f, 0x6e, 0x00,  // <i(69)>on.
    0x00, 0x00, 0x08, 0x48,  // ...H
    0x54, 0x54, 0x50, 0x2f,  // TTP/
    0x31, 0x2e, 0x31,        // 1.1
  };
  QuicStreamFrame frame(1, true, 0, StringPiece(arr, arraysize(arr)));
  // Verify that we don't crash when we get a invalid headers in stream frame.
  stream_.OnStreamFrame(frame);
}

}  // namespace
}  // namespace test
}  // namespace tools
}  // namespace net
<|endoftext|>