<commit_before>/*
 * Copyright (C) 2016 Florent Revest <revestflo@gmail.com>
 * All rights reserved.
 *
 * You may use this file under the terms of BSD license as follows:
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the author nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "flatmeshnode.h"

#include <math.h>

#include <QScreen>
#include <QElapsedTimer>

/* Used to compute a triangle color from its distance to the center */
static inline QColor interpolateColors(const QColor& color1, const QColor& color2, qreal ratio)
{
    /* Linear scale is too harsh, this looks better. This is not supposed to be called very often */
    ratio = pow(ratio, 1.7);
    if (ratio>1) ratio=1;

    int r = color1.red()*(1-ratio) + color2.red()*ratio;
    int g = color1.green()*(1-ratio) + color2.green()*ratio;
    int b = color1.blue()*(1-ratio) + color2.blue()*ratio;

    return QColor(r, g, b);
}

FlatMeshNode::FlatMeshNode(QQuickWindow *window, QRectF boundingRect)
    : QSGSimpleRectNode(boundingRect, Qt::transparent),
      m_animationState(0), m_window(window), m_animated(true)
{
    connect(window, SIGNAL(afterRendering()), this, SLOT(maybeAnimate()));

    connect(window, SIGNAL(widthChanged(int)), this, SLOT(generateGrid()));
    connect(window, SIGNAL(heightChanged(int)), this, SLOT(generateGrid()));

    srand(time(NULL));
    generateGrid();

    for(int y = 0; y < NUM_POINTS_Y-1; y++) {
        for(int x = 0; x < NUM_POINTS_X-1; x++) {
            for(int n = 0; n < 2; n++) {
                QSGGeometryNode *triangle = new QSGGeometryNode();

                QSGFlatColorMaterial *color = new QSGFlatColorMaterial;
                triangle->setOpaqueMaterial(color);

                QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 3);
                triangle->setGeometry(geometry);

                appendChildNode(triangle);
            }
        }
    }

    maybeAnimate();
}

void FlatMeshNode::updateColors()
{
    int centerX = m_unitWidth*((NUM_POINTS_X-2)/2);
    int centerY = m_unitHeight*((NUM_POINTS_Y-2)/2);
    int radius = rect().width()*0.6;

    QSGGeometryNode *triangle = static_cast<QSGGeometryNode *>(firstChild());
    for(int y = 0; y < NUM_POINTS_Y-1; y++) {
        for(int x = 0; x < NUM_POINTS_X-1; x++) {
            for(int n = 0; n < 2; n++) {
                QSGFlatColorMaterial *color = static_cast<QSGFlatColorMaterial *>(triangle->opaqueMaterial());
                color->setColor(interpolateColors(m_centerColor, m_outerColor,
                                sqrt(pow(m_points[y*NUM_POINTS_Y+x].centerX-centerX, 2) + pow(m_points[y*NUM_POINTS_Y+x].centerY-centerY, 2))/radius));
                triangle->setOpaqueMaterial(color);

                triangle->markDirty(QSGNode::DirtyMaterial);
                triangle = static_cast<QSGGeometryNode *>(triangle->nextSibling());
            }
        }
    }
}

void FlatMeshNode::setCenterColor(QColor c)
{
    if (c == m_centerColor)
        return;
    m_centerColor = c;
    updateColors();
}

void FlatMeshNode::setOuterColor(QColor c)
{
    if (c == m_outerColor)
        return;
    m_outerColor = c;
    updateColors();
}

/* When the size changes, regenerate a grid of points that serves as a base for further operations */
void FlatMeshNode::generateGrid()
{
    m_unitWidth = rect().width()/(NUM_POINTS_X-2);
    m_unitHeight = rect().height()/(NUM_POINTS_Y-2);

    for(int y = 0; y < NUM_POINTS_Y; y++) {
        for(int x = 0; x < NUM_POINTS_X; x++) {
            Point *point = &m_points[y*NUM_POINTS_Y+x];
            point->centerX = m_unitWidth*x;
            point->centerY = m_unitHeight*y;

            if(x != 0 && x != (NUM_POINTS_X-1)) {
                point->animOriginX = point->centerX + rand()%m_unitWidth - m_unitWidth/2;
                point->animEndX = point->centerX + rand()%m_unitWidth - m_unitWidth/2;
            }
            else
                point->animEndX = point->animOriginX = point->centerX;

            if(y != 0 && y != (NUM_POINTS_Y-1)) {
                point->animOriginY = point->centerY + rand()%m_unitHeight - m_unitHeight/2;
                point->animEndY = point->centerY + rand()%m_unitHeight - m_unitHeight/2;
            }
            else
                point->animEndY = point->animOriginY = point->centerY;
        }
    }
}

void FlatMeshNode::setAnimated(bool animated)
{
    m_animated = animated;
}

void FlatMeshNode::maybeAnimate()
{
    static QElapsedTimer t;
    bool firstFrame = false;
    if(!t.isValid()) {
        t.start();
        firstFrame = true;
    }
    if (firstFrame || (m_animated && t.restart() >= 100)) {
        m_animationState += 0.03;

        /* Interpolate all points positions according to the animationState */
        for(int i = 0; i < NUM_POINTS_X*NUM_POINTS_Y; i++) {
            Point *p = &m_points[i];

            p->currentPos.x = p->animOriginX + (p->animEndX-p->animOriginX)*m_animationState;
            p->currentPos.y = p->animOriginY + (p->animEndY-p->animOriginY)*m_animationState;
        }

        /* Update all triangles' geometries according to the new points position */
        qreal lastCenterX = m_unitWidth*(NUM_POINTS_X-1);
        qreal lastcenterY = m_unitHeight*(NUM_POINTS_Y-1);
        QSGGeometryNode *triangle = static_cast<QSGGeometryNode *>(firstChild());
        for(int i = 0; i < NUM_POINTS_X*NUM_POINTS_Y; i++) {
            if(m_points[i].centerX != lastCenterX && m_points[i].centerY != lastcenterY) {
                int random = rand()%2;
                for(int n = 0; n < 2; n++) {
                    QSGGeometry::Point2D *v = triangle->geometry()->vertexDataAsPoint2D();
                    if(random) {
                        if(n) {
                            v[0] = m_points[i].currentPos;
                            v[1] = m_points[i+NUM_POINTS_X].currentPos;
                            v[2] = m_points[i+NUM_POINTS_X+1].currentPos;
                        } else {
                            v[0] = m_points[i].currentPos;
                            v[1] = m_points[i+1].currentPos;
                            v[2] = m_points[i+NUM_POINTS_X+1].currentPos;
                        }
                    } else {
                        if(n) {
                            v[0] = m_points[i].currentPos;
                            v[1] = m_points[i+NUM_POINTS_X].currentPos;
                            v[2] = m_points[i+1].currentPos;
                        } else {
                            v[0] = m_points[i+NUM_POINTS_X].currentPos;
                            v[1] = m_points[i+1].currentPos;
                            v[2] = m_points[i+NUM_POINTS_X+1].currentPos;
                        }
                    }
                    triangle->markDirty(QSGNode::DirtyGeometry);
                    triangle = static_cast<QSGGeometryNode *>(triangle->nextSibling());
                }
            }
        }

        /* Regenerate a set of animation end points when the animation is finished */
        if(m_animationState >= 1.0) {
            m_animationState = 0.0;

            for(int y = 0; y < NUM_POINTS_Y; y++) {
                for(int x = 0; x < NUM_POINTS_X; x++) {
                    Point *point = &m_points[y*NUM_POINTS_Y+x];

                    if(x != 0 && x != (NUM_POINTS_X-1)) {
                        point->animOriginX = point->animEndX;
                        point->animEndX = point->centerX + rand()%m_unitWidth - m_unitWidth/2;
                    }
                    if(y != 0 && y != (NUM_POINTS_Y-1)) {
                        point->animOriginY = point->animEndY;
                        point->animEndY = point->centerY + rand()%m_unitHeight - m_unitHeight/2;
                    }
                }
            }
        }
    }
}
<commit_msg>Suppress a compilation warning because of variables initialization order<commit_after>/*
 * Copyright (C) 2016 Florent Revest <revestflo@gmail.com>
 * All rights reserved.
 *
 * You may use this file under the terms of BSD license as follows:
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the author nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "flatmeshnode.h"

#include <math.h>

#include <QScreen>
#include <QElapsedTimer>

/* Used to compute a triangle color from its distance to the center */
static inline QColor interpolateColors(const QColor& color1, const QColor& color2, qreal ratio)
{
    /* Linear scale is too harsh, this looks better. This is not supposed to be called very often */
    ratio = pow(ratio, 1.7);
    if (ratio>1) ratio=1;

    int r = color1.red()*(1-ratio) + color2.red()*ratio;
    int g = color1.green()*(1-ratio) + color2.green()*ratio;
    int b = color1.blue()*(1-ratio) + color2.blue()*ratio;

    return QColor(r, g, b);
}

FlatMeshNode::FlatMeshNode(QQuickWindow *window, QRectF boundingRect)
    : QSGSimpleRectNode(boundingRect, Qt::transparent),
      m_animationState(0), m_animated(true), m_window(window)
{
    connect(window, SIGNAL(afterRendering()), this, SLOT(maybeAnimate()));

    connect(window, SIGNAL(widthChanged(int)), this, SLOT(generateGrid()));
    connect(window, SIGNAL(heightChanged(int)), this, SLOT(generateGrid()));

    srand(time(NULL));
    generateGrid();

    for(int y = 0; y < NUM_POINTS_Y-1; y++) {
        for(int x = 0; x < NUM_POINTS_X-1; x++) {
            for(int n = 0; n < 2; n++) {
                QSGGeometryNode *triangle = new QSGGeometryNode();

                QSGFlatColorMaterial *color = new QSGFlatColorMaterial;
                triangle->setOpaqueMaterial(color);

                QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 3);
                triangle->setGeometry(geometry);

                appendChildNode(triangle);
            }
        }
    }

    maybeAnimate();
}

void FlatMeshNode::updateColors()
{
    int centerX = m_unitWidth*((NUM_POINTS_X-2)/2);
    int centerY = m_unitHeight*((NUM_POINTS_Y-2)/2);
    int radius = rect().width()*0.6;

    QSGGeometryNode *triangle = static_cast<QSGGeometryNode *>(firstChild());
    for(int y = 0; y < NUM_POINTS_Y-1; y++) {
        for(int x = 0; x < NUM_POINTS_X-1; x++) {
            for(int n = 0; n < 2; n++) {
                QSGFlatColorMaterial *color = static_cast<QSGFlatColorMaterial *>(triangle->opaqueMaterial());
                color->setColor(interpolateColors(m_centerColor, m_outerColor,
                                sqrt(pow(m_points[y*NUM_POINTS_Y+x].centerX-centerX, 2) + pow(m_points[y*NUM_POINTS_Y+x].centerY-centerY, 2))/radius));
                triangle->setOpaqueMaterial(color);

                triangle->markDirty(QSGNode::DirtyMaterial);
                triangle = static_cast<QSGGeometryNode *>(triangle->nextSibling());
            }
        }
    }
}

void FlatMeshNode::setCenterColor(QColor c)
{
    if (c == m_centerColor)
        return;
    m_centerColor = c;
    updateColors();
}

void FlatMeshNode::setOuterColor(QColor c)
{
    if (c == m_outerColor)
        return;
    m_outerColor = c;
    updateColors();
}

/* When the size changes, regenerate a grid of points that serves as a base for further operations */
void FlatMeshNode::generateGrid()
{
    m_unitWidth = rect().width()/(NUM_POINTS_X-2);
    m_unitHeight = rect().height()/(NUM_POINTS_Y-2);

    for(int y = 0; y < NUM_POINTS_Y; y++) {
        for(int x = 0; x < NUM_POINTS_X; x++) {
            Point *point = &m_points[y*NUM_POINTS_Y+x];
            point->centerX = m_unitWidth*x;
            point->centerY = m_unitHeight*y;

            if(x != 0 && x != (NUM_POINTS_X-1)) {
                point->animOriginX = point->centerX + rand()%m_unitWidth - m_unitWidth/2;
                point->animEndX = point->centerX + rand()%m_unitWidth - m_unitWidth/2;
            }
            else
                point->animEndX = point->animOriginX = point->centerX;

            if(y != 0 && y != (NUM_POINTS_Y-1)) {
                point->animOriginY = point->centerY + rand()%m_unitHeight - m_unitHeight/2;
                point->animEndY = point->centerY + rand()%m_unitHeight - m_unitHeight/2;
            }
            else
                point->animEndY = point->animOriginY = point->centerY;
        }
    }
}

void FlatMeshNode::setAnimated(bool animated)
{
    m_animated = animated;
}

void FlatMeshNode::maybeAnimate()
{
    static QElapsedTimer t;
    bool firstFrame = false;
    if(!t.isValid()) {
        t.start();
        firstFrame = true;
    }
    if (firstFrame || (m_animated && t.restart() >= 100)) {
        m_animationState += 0.03;

        /* Interpolate all points positions according to the animationState */
        for(int i = 0; i < NUM_POINTS_X*NUM_POINTS_Y; i++) {
            Point *p = &m_points[i];

            p->currentPos.x = p->animOriginX + (p->animEndX-p->animOriginX)*m_animationState;
            p->currentPos.y = p->animOriginY + (p->animEndY-p->animOriginY)*m_animationState;
        }

        /* Update all triangles' geometries according to the new points position */
        qreal lastCenterX = m_unitWidth*(NUM_POINTS_X-1);
        qreal lastcenterY = m_unitHeight*(NUM_POINTS_Y-1);
        QSGGeometryNode *triangle = static_cast<QSGGeometryNode *>(firstChild());
        for(int i = 0; i < NUM_POINTS_X*NUM_POINTS_Y; i++) {
            if(m_points[i].centerX != lastCenterX && m_points[i].centerY != lastcenterY) {
                int random = rand()%2;
                for(int n = 0; n < 2; n++) {
                    QSGGeometry::Point2D *v = triangle->geometry()->vertexDataAsPoint2D();
                    if(random) {
                        if(n) {
                            v[0] = m_points[i].currentPos;
                            v[1] = m_points[i+NUM_POINTS_X].currentPos;
                            v[2] = m_points[i+NUM_POINTS_X+1].currentPos;
                        } else {
                            v[0] = m_points[i].currentPos;
                            v[1] = m_points[i+1].currentPos;
                            v[2] = m_points[i+NUM_POINTS_X+1].currentPos;
                        }
                    } else {
                        if(n) {
                            v[0] = m_points[i].currentPos;
                            v[1] = m_points[i+NUM_POINTS_X].currentPos;
                            v[2] = m_points[i+1].currentPos;
                        } else {
                            v[0] = m_points[i+NUM_POINTS_X].currentPos;
                            v[1] = m_points[i+1].currentPos;
                            v[2] = m_points[i+NUM_POINTS_X+1].currentPos;
                        }
                    }
                    triangle->markDirty(QSGNode::DirtyGeometry);
                    triangle = static_cast<QSGGeometryNode *>(triangle->nextSibling());
                }
            }
        }

        /* Regenerate a set of animation end points when the animation is finished */
        if(m_animationState >= 1.0) {
            m_animationState = 0.0;

            for(int y = 0; y < NUM_POINTS_Y; y++) {
                for(int x = 0; x < NUM_POINTS_X; x++) {
                    Point *point = &m_points[y*NUM_POINTS_Y+x];

                    if(x != 0 && x != (NUM_POINTS_X-1)) {
                        point->animOriginX = point->animEndX;
                        point->animEndX = point->centerX + rand()%m_unitWidth - m_unitWidth/2;
                    }
                    if(y != 0 && y != (NUM_POINTS_Y-1)) {
                        point->animOriginY = point->animEndY;
                        point->animEndY = point->centerY + rand()%m_unitHeight - m_unitHeight/2;
                    }
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>/* mbed Microcontroller Library
 * Copyright (c) 2017 ARM Limited
 *
 * 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 "mbed.h"
#include "greentea-client/test_env.h"
#include "unity.h"
#include "utest.h"
#include "rtos.h"

using namespace utest::v1;

#define TEST_DELAY_MS 50
#define TEST_DELAY2_MS 30
#define TEST_DELAY_MS_DELTA 5
#define TEST_RESTART_DELAY_MS 10

#if TEST_RESTART_DELAY_MS >= TEST_DELAY_MS
#error invalid TEST_RESTART_DELAY_MS value
#endif

void timer_callback(void const *arg)
{
    Semaphore *sem = (Semaphore *) arg;
    sem->release();
}

/* In order to successfully run this test suite when compiled with --profile=debug
 * error() has to be redefined as noop.
 *
 * RtosTimer calls RTX API which uses Event Recorder functionality. When compiled
 * with MBED_TRAP_ERRORS_ENABLED=1 (set in debug profile) EvrRtxTimerError() calls error()
 * which aborts test program.
 */
#if defined(MBED_TRAP_ERRORS_ENABLED) && MBED_TRAP_ERRORS_ENABLED
void error(const char* format, ...) {
    (void) format;
}
#endif

/** Test one-shot not restarted when elapsed
 *
 * Given a one-shot timer
 * When the timer is started
 *     and given time elapses
 * Then timer stops
 *     and elapsed time matches given delay
 *     and timer stays stopped
 */
void test_oneshot_not_restarted()
{
    Semaphore sem(1);
    RtosTimer timer(mbed::callback(timer_callback, (void const *) &sem), osTimerOnce);
    osStatus stat = timer.stop();
    TEST_ASSERT_EQUAL(osErrorResource, stat);

    Timer t;
    sem.wait(0);
    stat = timer.start(TEST_DELAY_MS);
    t.start();
    TEST_ASSERT_EQUAL(osOK, stat);

    int32_t slots = sem.wait(TEST_DELAY_MS + TEST_DELAY_MS_DELTA);
    t.stop();
    TEST_ASSERT_EQUAL(1, slots);
    TEST_ASSERT_INT_WITHIN(TEST_DELAY_MS_DELTA * 1000, TEST_DELAY_MS * 1000, t.read_us());

    slots = sem.wait(TEST_DELAY_MS + TEST_DELAY_MS_DELTA);
    TEST_ASSERT_EQUAL(0, slots);

    stat = timer.stop();
    TEST_ASSERT_EQUAL(osErrorResource, stat);
}

/** Test periodic repeats continuously
 *
 * Given a periodic timer
 * When timer is started
 *     and given time elapses
 * Then timer repeats its operation
 * When timer is stopped
 * Then timer stops operation
 */
void test_periodic_repeats()
{
    Semaphore sem(1);
    RtosTimer timer(mbed::callback(timer_callback, (void const *) &sem), osTimerPeriodic);
    osStatus stat = timer.stop();
    TEST_ASSERT_EQUAL(osErrorResource, stat);

    Timer t;
    sem.wait(0);
    stat = timer.start(TEST_DELAY_MS);
    t.start();
    TEST_ASSERT_EQUAL(osOK, stat);

    int32_t slots = sem.wait(TEST_DELAY_MS + TEST_DELAY_MS_DELTA);
    int t1 = t.read_us();
    TEST_ASSERT_EQUAL(1, slots);
    TEST_ASSERT_INT_WITHIN(TEST_DELAY_MS_DELTA * 1000, TEST_DELAY_MS * 1000, t1);

    slots = sem.wait(TEST_DELAY_MS + TEST_DELAY_MS_DELTA);
    t.stop();
    TEST_ASSERT_EQUAL(1, slots);
    TEST_ASSERT_INT_WITHIN(TEST_DELAY_MS_DELTA * 1000, TEST_DELAY_MS * 1000, t.read_us() - t1);

    stat = timer.stop();
    TEST_ASSERT_EQUAL(osOK, stat);

    slots = sem.wait(TEST_DELAY_MS + TEST_DELAY_MS_DELTA);
    TEST_ASSERT_EQUAL(0, slots);

    stat = timer.stop();
    TEST_ASSERT_EQUAL(osErrorResource, stat);
}

/** Test timer can be restarted
 *
 * Given a one-shot timer
 * When the timer is started
 *     and @a start is called again before given time elapses
 *     and given time elapses
 * Then timer stops
 *     and elapsed time is greater than original delay
 */
void test_restart()
{
    Semaphore sem(1);
    RtosTimer timer(mbed::callback(timer_callback, (void const *) &sem), osTimerOnce);
    osStatus stat = timer.stop();
    TEST_ASSERT_EQUAL(osErrorResource, stat);

    Timer t;
    sem.wait(0);
    stat = timer.start(TEST_DELAY_MS);
    t.start();
    TEST_ASSERT_EQUAL(osOK, stat);

    int32_t slots = sem.wait(TEST_RESTART_DELAY_MS);
    TEST_ASSERT_EQUAL(0, slots);

    stat = timer.start(TEST_DELAY_MS);
    TEST_ASSERT_EQUAL(osOK, stat);

    slots = sem.wait(TEST_DELAY_MS + TEST_DELAY_MS_DELTA);
    t.stop();
    TEST_ASSERT_EQUAL(1, slots);
    TEST_ASSERT_INT_WITHIN(TEST_DELAY_MS_DELTA * 1000, (TEST_DELAY_MS + TEST_RESTART_DELAY_MS) * 1000, t.read_us());

    stat = timer.stop();
    TEST_ASSERT_EQUAL(osErrorResource, stat);
}

/** Test timer can be started again
 *
 * Given a one-shot timer
 * When the timer is started
 *     and given time elapses
 * Then timer stops
 * When the timer is started again
 *     and given time elapses
 * Then timer stops again
 */
void test_start_again()
{
    Semaphore sem(1);
    RtosTimer timer(mbed::callback(timer_callback, (void const *) &sem), osTimerOnce);
    osStatus stat = timer.stop();
    TEST_ASSERT_EQUAL(osErrorResource, stat);

    sem.wait(0);
    stat = timer.start(TEST_DELAY_MS);
    TEST_ASSERT_EQUAL(osOK, stat);

    int32_t slots = sem.wait(TEST_DELAY_MS + TEST_DELAY_MS_DELTA);
    TEST_ASSERT_EQUAL(1, slots);

    stat = timer.stop();
    TEST_ASSERT_EQUAL(osErrorResource, stat);

    stat = timer.start(TEST_DELAY_MS);
    TEST_ASSERT_EQUAL(osOK, stat);

    slots = sem.wait(TEST_DELAY_MS + TEST_DELAY_MS_DELTA);
    TEST_ASSERT_EQUAL(1, slots);

    stat = timer.stop();
    TEST_ASSERT_EQUAL(osErrorResource, stat);
}

/** Test timer restart updates delay
 *
 * Given a one-shot timer
 * When the timer is started
 *     and @a start is called again with a different delay before given time elapses
 *     and updated delay elapses
 * Then timer stops
 *     and time elapsed since the second @a start call matches updated delay
 */
void test_restart_updates_delay()
{
    Semaphore sem(1);
    RtosTimer timer(mbed::callback(timer_callback, (void const *) &sem), osTimerOnce);
    osStatus stat = timer.stop();
    TEST_ASSERT_EQUAL(osErrorResource, stat);

    sem.wait(0);
    stat = timer.start(TEST_DELAY_MS);
    TEST_ASSERT_EQUAL(osOK, stat);

    int32_t slots = sem.wait(TEST_RESTART_DELAY_MS);
    TEST_ASSERT_EQUAL(0, slots);

    Timer t;
    stat = timer.start(TEST_DELAY2_MS);
    t.start();
    TEST_ASSERT_EQUAL(osOK, stat);

    slots = sem.wait(TEST_DELAY2_MS + TEST_DELAY_MS_DELTA);
    t.stop();
    TEST_ASSERT_EQUAL(1, slots);
    TEST_ASSERT_INT_WITHIN(TEST_DELAY_MS_DELTA * 1000, TEST_DELAY2_MS * 1000, t.read_us());

    stat = timer.stop();
    TEST_ASSERT_EQUAL(osErrorResource, stat);
}

/** Test timer is created in stopped state
 *
 * Given a one-shot timer
 * When the timer has not been started
 * Then the timer is stopped
 */
void test_created_stopped()
{
    RtosTimer timer(mbed::callback(timer_callback, (void const *) NULL), osTimerOnce);
    osStatus stat = timer.stop();
    TEST_ASSERT_EQUAL(osErrorResource, stat);
}

/** Test one-shot can be stopped
 *
 * Given a one-shot timer
 * When the timer is started
 *     and timer is stopped while still running
 * Then timer stops operation
 */
void test_stop()
{
    Semaphore sem(1);
    RtosTimer timer(mbed::callback(timer_callback, (void const *) &sem), osTimerOnce);
    osStatus stat = timer.stop();
    TEST_ASSERT_EQUAL(osErrorResource, stat);

    sem.wait(0);
    stat = timer.start(TEST_DELAY_MS);
    TEST_ASSERT_EQUAL(osOK, stat);

    int32_t slots = sem.wait(TEST_RESTART_DELAY_MS);
    TEST_ASSERT_EQUAL(0, slots);

    stat = timer.stop();
    TEST_ASSERT_EQUAL(osOK, stat);

    slots = sem.wait(TEST_DELAY_MS + TEST_DELAY_MS_DELTA);
    TEST_ASSERT_EQUAL(0, slots);

    stat = timer.stop();
    TEST_ASSERT_EQUAL(osErrorResource, stat);
}

/** Test timer started with infinite delay
 *
 * Given a one-shot timer
 * When the timer is started with @a osWaitForever delay
 * Then @a start return status is @a osOK
 */
void test_wait_forever()
{
    RtosTimer timer(mbed::callback(timer_callback, (void const *) NULL), osTimerOnce);

    osStatus stat = timer.start(osWaitForever);
    TEST_ASSERT_EQUAL(osOK, stat);

    stat = timer.stop();
    TEST_ASSERT_EQUAL(osOK, stat);
}

/** Test timer started with zero delay
 *
 * Given a one-shot timer
 * When the timer is started with 0 delay
 * Then @a start return status is @a osErrorParameter
 */
void test_no_wait()
{
    RtosTimer timer(mbed::callback(timer_callback, (void const *) NULL), osTimerOnce);

    osStatus stat = timer.start(0);
    TEST_ASSERT_EQUAL(osErrorParameter, stat);

    stat = timer.stop();
    TEST_ASSERT_EQUAL(osErrorResource, stat);
}

void timer_isr_call(void const *arg)
{
    RtosTimer *timer = (RtosTimer *) arg;
    osStatus stat = timer->start(TEST_DELAY_MS);
    TEST_ASSERT_EQUAL(osErrorISR, stat);

    stat = timer->stop();
    TEST_ASSERT_EQUAL(osErrorISR, stat);
}

/** Test timer method calls from an ISR fail
 *
 * Given a one-shot timer
 * When a timer method is called from an ISR
 * Then method return status is @a osErrorISR
 */
void test_isr_calls_fail()
{
    RtosTimer timer(mbed::callback(timer_callback, (void const *) NULL), osTimerOnce);

    Ticker ticker;
    ticker.attach(mbed::callback(timer_isr_call, (void const *) &timer), (float) TEST_DELAY_MS / 1000.0);

    wait_ms(TEST_DELAY_MS + TEST_DELAY_MS_DELTA);
}

utest::v1::status_t test_setup(const size_t number_of_cases)
{
    GREENTEA_SETUP(5, "default_auto");
    return verbose_test_setup_handler(number_of_cases);
}

Case cases[] = {
    Case("Test one-shot not restarted when elapsed", test_oneshot_not_restarted),
    Case("Test periodic repeats continuously", test_periodic_repeats),
    Case("Test timer can be restarted while running", test_restart),
    Case("Test stopped timer can be started again", test_start_again),
    Case("Test restart changes timeout", test_restart_updates_delay),
    Case("Test can be stopped", test_stop),
    Case("Test timer is created in stopped state", test_created_stopped),
    Case("Test timer started with infinite delay", test_wait_forever),
    Case("Test timer started with zero delay", test_no_wait),
    Case("Test calls from ISR fail", test_isr_calls_fail)
};

Specification specification(test_setup, cases);

int main()
{
    return !Harness::run(specification);
}
<commit_msg>Tests: RTOS: RtosTimer: Refactor for readability<commit_after>/* mbed Microcontroller Library
 * Copyright (c) 2017 ARM Limited
 *
 * 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 "mbed.h"
#include "greentea-client/test_env.h"
#include "unity.h"
#include "utest.h"
#include "rtos.h"

using namespace utest::v1;

#define DELAY_MS 50
#define DELTA_MS 5
#define RESTART_DELAY_MS 10
#define DELAY2_MS 30

#if RESTART_DELAY_MS >= DELAY_MS
#error invalid RESTART_DELAY_MS value
#endif

class Stopwatch: public Timer {
private:
    Semaphore _sem;

public:
    Stopwatch() :
            Timer(), _sem(1)
    {
    }

    ~Stopwatch()
    {
    }

    void start(void)
    {
        _sem.wait(0);
        Timer::start();
    }

    void stop(void)
    {
        Timer::stop();
        _sem.release();
    }

    int32_t wait_until_stopped(uint32_t millisec = osWaitForever)
    {
        core_util_critical_section_enter();
        int running = _running;
        core_util_critical_section_exit();
        if (!running) {
            return 1;
        }
        return _sem.wait(millisec);
    }
};

void sem_callback(Semaphore *sem)
{
    sem->release();
}

/* In order to successfully run this test suite when compiled with --profile=debug
 * error() has to be redefined as noop.
 *
 * RtosTimer calls RTX API which uses Event Recorder functionality. When compiled
 * with MBED_TRAP_ERRORS_ENABLED=1 (set in debug profile) EvrRtxTimerError() calls error()
 * which aborts test program.
 */
#if defined(MBED_TRAP_ERRORS_ENABLED) && MBED_TRAP_ERRORS_ENABLED
void error(const char* format, ...)
{
    (void) format;
}
#endif

/** Test one-shot not restarted when elapsed
 *
 * Given a one-shot RtosTimer
 * When the timer is started
 *     and given time elapses
 * Then timer stops
 *     and elapsed time matches given delay
 *     and timer stays stopped
 */
void test_oneshot_not_restarted()
{
    Stopwatch stopwatch;
    RtosTimer rtostimer(mbed::callback(&stopwatch, &Stopwatch::stop), osTimerOnce);

    stopwatch.start();
    osStatus status = rtostimer.start(DELAY_MS);
    TEST_ASSERT_EQUAL(osOK, status);

    int32_t slots = stopwatch.wait_until_stopped();
    TEST_ASSERT_EQUAL(1, slots);
    TEST_ASSERT_INT_WITHIN(DELTA_MS, DELAY_MS, stopwatch.read_ms());
    stopwatch.start();

    slots = stopwatch.wait_until_stopped(DELAY_MS + DELTA_MS);
    TEST_ASSERT_EQUAL(0, slots);
    status = rtostimer.stop();
    TEST_ASSERT_EQUAL(osErrorResource, status);
}

/** Test periodic repeats continuously
 *
 * Given a periodic RtosTimer
 * When timer is started
 *     and given time elapses
 * Then timer repeats its operation
 * When timer is stopped
 * Then timer stops operation
 */
void test_periodic_repeats()
{
    Stopwatch stopwatch;
    RtosTimer rtostimer(mbed::callback(&stopwatch, &Stopwatch::stop), osTimerPeriodic);

    stopwatch.start();
    osStatus status = rtostimer.start(DELAY_MS);
    TEST_ASSERT_EQUAL(osOK, status);

    int32_t slots = stopwatch.wait_until_stopped();
    int t1 = stopwatch.read_ms();
    stopwatch.reset();
    stopwatch.start();
    TEST_ASSERT_EQUAL(1, slots);
    TEST_ASSERT_INT_WITHIN(DELTA_MS, DELAY_MS, t1);

    slots = stopwatch.wait_until_stopped();
    TEST_ASSERT_EQUAL(1, slots);
    TEST_ASSERT_INT_WITHIN(DELTA_MS, DELAY_MS, stopwatch.read_ms());
    stopwatch.start();

    status = rtostimer.stop();
    TEST_ASSERT_EQUAL(osOK, status);

    slots = stopwatch.wait_until_stopped(DELAY_MS + DELTA_MS);
    TEST_ASSERT_EQUAL(0, slots);
    status = rtostimer.stop();
    TEST_ASSERT_EQUAL(osErrorResource, status);
}

/** Test timer can be started again
 *
 * Given a one-shot Rtosimer
 * When the timer is started
 *     and given time elapses
 * Then timer stops
 * When the timer is started again
 *     and given time elapses
 * Then timer stops again
 */
void test_start_again()
{
    Semaphore sem(0, 1);
    RtosTimer rtostimer(mbed::callback(sem_callback, &sem), osTimerOnce);

    osStatus status = rtostimer.start(DELAY_MS);
    TEST_ASSERT_EQUAL(osOK, status);

    int32_t slots = sem.wait(DELAY_MS + DELTA_MS);
    TEST_ASSERT_EQUAL(1, slots);

    status = rtostimer.stop();
    TEST_ASSERT_EQUAL(osErrorResource, status);

    status = rtostimer.start(DELAY_MS);
    TEST_ASSERT_EQUAL(osOK, status);

    slots = sem.wait(DELAY_MS + DELTA_MS);
    TEST_ASSERT_EQUAL(1, slots);

    status = rtostimer.stop();
    TEST_ASSERT_EQUAL(osErrorResource, status);
}

/** Test timer restart updates delay
 *
 * Given a one-shot RtosTimer
 * When the timer is started
 *     and @a start is called again with a different delay before given time elapses
 *     and updated delay elapses
 * Then timer stops
 *     and time elapsed since the second @a start call matches updated delay
 */
void test_restart_updates_delay()
{
    Stopwatch stopwatch;
    RtosTimer rtostimer(mbed::callback(&stopwatch, &Stopwatch::stop), osTimerOnce);

    stopwatch.start();
    osStatus status = rtostimer.start(DELAY_MS);
    TEST_ASSERT_EQUAL(osOK, status);

    int32_t slots = stopwatch.wait_until_stopped(RESTART_DELAY_MS);
    TEST_ASSERT_EQUAL(0, slots);

    stopwatch.reset();
    stopwatch.start();
    status = rtostimer.start(DELAY2_MS);
    TEST_ASSERT_EQUAL(osOK, status);

    slots = stopwatch.wait_until_stopped();
    TEST_ASSERT_EQUAL(1, slots);
    TEST_ASSERT_INT_WITHIN(DELTA_MS, DELAY2_MS, stopwatch.read_ms());

    status = rtostimer.stop();
    TEST_ASSERT_EQUAL(osErrorResource, status);
}

/** Test timer is created in stopped state
 *
 * Given a one-shot RtosTimer
 * When the timer has not been started
 * Then the timer is stopped
 */
void test_created_stopped()
{
    RtosTimer rtostimer(mbed::callback(sem_callback, (Semaphore *) NULL), osTimerOnce);
    osStatus status = rtostimer.stop();
    TEST_ASSERT_EQUAL(osErrorResource, status);
}

/** Test one-shot can be stopped
 *
 * Given a one-shot RtosTimer
 * When the timer is started
 *     and timer is stopped while still running
 * Then timer stops operation
 */
void test_stop()
{
    Semaphore sem(0, 1);
    RtosTimer rtostimer(mbed::callback(sem_callback, &sem), osTimerOnce);

    osStatus status = rtostimer.start(DELAY_MS);
    TEST_ASSERT_EQUAL(osOK, status);

    int32_t slots = sem.wait(RESTART_DELAY_MS);
    TEST_ASSERT_EQUAL(0, slots);

    status = rtostimer.stop();
    TEST_ASSERT_EQUAL(osOK, status);

    slots = sem.wait(DELAY_MS + DELTA_MS);
    TEST_ASSERT_EQUAL(0, slots);

    status = rtostimer.stop();
    TEST_ASSERT_EQUAL(osErrorResource, status);
}

/** Test timer started with infinite delay
 *
 * Given a one-shot RtosTimer
 * When the timer is started with @a osWaitForever delay
 * Then @a start return status is @a osOK
 */
void test_wait_forever()
{
    RtosTimer rtostimer(mbed::callback(sem_callback, (Semaphore *) NULL), osTimerOnce);

    osStatus status = rtostimer.start(osWaitForever);
    TEST_ASSERT_EQUAL(osOK, status);

    status = rtostimer.stop();
    TEST_ASSERT_EQUAL(osOK, status);
}

/** Test timer started with zero delay
 *
 * Given a one-shot RtosTimer
 * When the timer is started with 0 delay
 * Then @a start return status is @a osErrorParameter
 */
void test_no_wait()
{
    RtosTimer rtostimer(mbed::callback(sem_callback, (Semaphore *) NULL), osTimerOnce);

    osStatus status = rtostimer.start(0);
    TEST_ASSERT_EQUAL(osErrorParameter, status);

    status = rtostimer.stop();
    TEST_ASSERT_EQUAL(osErrorResource, status);
}

void rtostimer_isr_call(RtosTimer *rtostimer)
{
    osStatus status = rtostimer->start(DELAY_MS);
    TEST_ASSERT_EQUAL(osErrorISR, status);

    status = rtostimer->stop();
    TEST_ASSERT_EQUAL(osErrorISR, status);
}

/** Test timer method calls from an ISR fail
 *
 * Given a one-shot RtosTimer
 * When a timer method is called from an ISR
 * Then method return status is @a osErrorISR
 */
void test_isr_calls_fail()
{
    RtosTimer rtostimer(mbed::callback(sem_callback, (Semaphore *) NULL), osTimerOnce);

    Ticker ticker;
    ticker.attach(mbed::callback(rtostimer_isr_call, &rtostimer), (float) DELAY_MS / 1000.0);

    wait_ms(DELAY_MS + DELTA_MS);
}

utest::v1::status_t test_setup(const size_t number_of_cases)
{
    GREENTEA_SETUP(5, "default_auto");
    return verbose_test_setup_handler(number_of_cases);
}

Case cases[] = {
    Case("One-shot not restarted when elapsed", test_oneshot_not_restarted),
    Case("Periodic repeats continuously", test_periodic_repeats),
    Case("Stopped timer can be started again", test_start_again),
    Case("Restart changes timeout", test_restart_updates_delay),
    Case("Timer can be stopped", test_stop),
    Case("Timer is created in stopped state", test_created_stopped),
    Case("Timer started with infinite delay", test_wait_forever),
    Case("Timer started with zero delay", test_no_wait),
    Case("Calls from ISR fail", test_isr_calls_fail)
};

Specification specification(test_setup, cases);

int main()
{
    return !Harness::run(specification);
}
<|endoftext|>


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

#include <Urho3D/Core/CoreEvents.h>
#include <Urho3D/Engine/Engine.h>
#include <Urho3D/Graphics/Camera.h>
#include <Urho3D/Graphics/Graphics.h>
#include <Urho3D/Graphics/Model.h>
#include <Urho3D/Graphics/Octree.h>
#include <Urho3D/Graphics/RenderPath.h>
#include <Urho3D/Graphics/StaticModel.h>
#include <Urho3D/Graphics/Zone.h>
#include <Urho3D/Input/Input.h>
#include <Urho3D/Resource/ResourceCache.h>
#include <Urho3D/Scene/Scene.h>
#include <Urho3D/UI/Button.h>
#include <Urho3D/UI/Font.h>
#include <Urho3D/UI/Slider.h>
#include <Urho3D/UI/UI.h>
#include <Urho3D/UI/UIEvents.h>
#include <Urho3D/UI/Text.h>

#include "RenderingShowcase.h"

#include <Urho3D/DebugNew.h>

RenderingShowcase::RenderingShowcase(Context* context) : Sample(context)
{
    // All these scenes correspond to Scenes/RenderingShowcase_*.xml resources
    sceneNames_.push_back({ "0" });
    sceneNames_.push_back({ "2_Dynamic", "2_BakedDirect", "2_BakedIndirect", "2_BakedDirectIndirect" });
    // Keep 1 last because it may crash mobile browsers
    sceneNames_.push_back({ "1" });
}

void RenderingShowcase::Start()
{
    // Execute base class startup
    Sample::Start();

    // Create scene content
    CreateScene();
    SetupSelectedScene();

    // Create the UI content
    CreateInstructions();

    // Setup the viewport for displaying the scene
    SetupViewport();

    // Subscribe to global events for camera movement
    SubscribeToEvents();

    // Set the mouse mode to use in the sample
    Sample::InitMouseMode(MM_RELATIVE);
}

void RenderingShowcase::CreateInstructions()
{
    auto* cache = GetSubsystem<ResourceCache>();
    auto* ui = GetSubsystem<UI>();

    // Construct new Text object, set string to display and font to use
    auto* instructionText = ui->GetRoot()->CreateChild<Text>();
    instructionText->SetText("Press Tab to switch scene. Press Q to switch scene mode. \n"
        "Press F to toggle probe object. Use WASD keys and mouse to move.");
    instructionText->SetFont(cache->GetResource<Font>("Fonts/Anonymous Pro.ttf"), 15);
    instructionText->SetTextAlignment(HA_CENTER);

    // Position the text relative to the screen center
    instructionText->SetHorizontalAlignment(HA_CENTER);
    instructionText->SetVerticalAlignment(VA_CENTER);
    instructionText->SetPosition(0, ui->GetRoot()->GetHeight() / 4);
}

void RenderingShowcase::CreateScene()
{
    auto* cache = GetSubsystem<ResourceCache>();

    scene_ = MakeShared<Scene>(context_);
    cameraScene_ = MakeShared<Scene>(context_);

    // Create the camera (not included in the scene file)
    cameraNode_ = cameraScene_->CreateChild("Camera");
    cameraNode_->CreateComponent<Camera>();

    Node* probeObjectNode = cameraNode_->CreateChild();
    probeObjectNode->SetPosition({ 0.0f, 0.0f, 1.0f });
    probeObjectNode->SetScale(0.5f);

    probeObject_ = probeObjectNode->CreateComponent<StaticModel>();
    probeObject_->SetModel(cache->GetResource<Model>("Models/Teapot.mdl"));
    probeObject_->SetCastShadows(true);
    probeObject_->SetGlobalIlluminationType(GlobalIlluminationType::BlendLightProbes);
}

void RenderingShowcase::SetupSelectedScene(bool resetCamera)
{
    auto* cache = GetSubsystem<ResourceCache>();

    const bool isProbeObjectVisible = probeObject_->IsInOctree();

    if (isProbeObjectVisible)
        scene_->GetComponent<Octree>()->RemoveManualDrawable(probeObject_);

    // Load scene content prepared in the editor (XML format). GetFile() returns an open file from the resource system
    // which scene.LoadXML() will read
    const ea::string fileName = Format("Scenes/RenderingShowcase_{}.xml", sceneNames_[sceneIndex_][sceneMode_]);
    SharedPtr<File> file = cache->GetFile(fileName);
    scene_->LoadXML(*file);

    if (resetCamera)
    {
        cameraNode_->SetPosition({ 0.0f, 4.0f, 8.0f });
        cameraNode_->LookAt(Vector3::ZERO);

        yaw_ = cameraNode_->GetRotation().YawAngle();
        pitch_ = cameraNode_->GetRotation().PitchAngle();
    }

    if (isProbeObjectVisible)
        scene_->GetComponent<Octree>()->AddManualDrawable(probeObject_);
}

void RenderingShowcase::SetupViewport()
{
    auto* cache = GetSubsystem<ResourceCache>();
    auto* renderer = GetSubsystem<Renderer>();

    // Set up a viewport to the Renderer subsystem so that the 3D scene can be seen
    SharedPtr<Viewport> viewport(new Viewport(context_, scene_, cameraNode_->GetComponent<Camera>()));
    renderer->SetViewport(0, viewport);
}

void RenderingShowcase::SubscribeToEvents()
{
    // Subscribe HandleUpdate() function for camera motion
    SubscribeToEvent(E_UPDATE, URHO3D_HANDLER(RenderingShowcase, HandleUpdate));
}

void RenderingShowcase::MoveCamera(float timeStep)
{
    // Right mouse button controls mouse cursor visibility: hide when pressed
    auto* input = GetSubsystem<Input>();

    // Movement speed as world units per second
    const float MOVE_SPEED = 10.0f;
    // Mouse sensitivity as degrees per pixel
    const float MOUSE_SENSITIVITY = 0.1f;

    // Use this frame's mouse motion to adjust camera node yaw and pitch. Clamp the pitch between -90 and 90 degrees
    IntVector2 mouseMove = input->GetMouseMove();
    yaw_ += MOUSE_SENSITIVITY * mouseMove.x_;
    pitch_ += MOUSE_SENSITIVITY * mouseMove.y_;
    pitch_ = Clamp(pitch_, -90.0f, 90.0f);

    // Construct new orientation for the camera scene node from yaw and pitch. Roll is fixed to zero
    cameraNode_->SetRotation(Quaternion(pitch_, yaw_, 0.0f));

    // Read WASD keys and move the camera scene node to the corresponding direction if they are pressed
    if (input->GetKeyDown(KEY_W))
        cameraNode_->Translate(Vector3::FORWARD * MOVE_SPEED * timeStep);
    if (input->GetKeyDown(KEY_S))
        cameraNode_->Translate(Vector3::BACK * MOVE_SPEED * timeStep);
    if (input->GetKeyDown(KEY_A))
        cameraNode_->Translate(Vector3::LEFT * MOVE_SPEED * timeStep);
    if (input->GetKeyDown(KEY_D))
        cameraNode_->Translate(Vector3::RIGHT * MOVE_SPEED * timeStep);
}

void RenderingShowcase::HandleUpdate(StringHash eventType, VariantMap& eventData)
{
    using namespace Update;

    // Take the frame time step, which is stored as a float
    float timeStep = eventData[P_TIMESTEP].GetFloat();

    // Move the camera, scale movement with time step
    MoveCamera(timeStep);

    // Keep probe object orientation
    probeObject_->GetNode()->SetWorldRotation(Quaternion::IDENTITY);

    // Update scene
    auto* input = GetSubsystem<Input>();
    if (sceneNames_.size() > 1 && input->GetKeyPress(KEY_TAB))
    {
        sceneIndex_ = (sceneIndex_ + 1) % sceneNames_.size();
        sceneMode_ = 0;
        SetupSelectedScene();
    }

    // Update scene mode
    if (sceneNames_[sceneIndex_].size() > 1 && input->GetKeyPress(KEY_Q))
    {
        sceneMode_ = (sceneMode_ + 1) % sceneNames_[sceneIndex_].size();
        SetupSelectedScene(false);
    }

    // Update probe object
    if (input->GetKeyPress(KEY_F))
    {
        const bool isProbeObjectVisible = probeObject_->IsInOctree();
        auto* octree = scene_->GetComponent<Octree>();
        if (isProbeObjectVisible)
            octree->RemoveManualDrawable(probeObject_);
        else
            octree->AddManualDrawable(probeObject_);
    }
}
<commit_msg>Fix missing teapot in sample.<commit_after>//
// Copyright (c) 2008-2020 the Urho3D project.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

#include <Urho3D/Core/CoreEvents.h>
#include <Urho3D/Engine/Engine.h>
#include <Urho3D/Graphics/Camera.h>
#include <Urho3D/Graphics/Graphics.h>
#include <Urho3D/Graphics/Model.h>
#include <Urho3D/Graphics/Octree.h>
#include <Urho3D/Graphics/RenderPath.h>
#include <Urho3D/Graphics/StaticModel.h>
#include <Urho3D/Graphics/Zone.h>
#include <Urho3D/Input/Input.h>
#include <Urho3D/Resource/ResourceCache.h>
#include <Urho3D/Scene/Scene.h>
#include <Urho3D/UI/Button.h>
#include <Urho3D/UI/Font.h>
#include <Urho3D/UI/Slider.h>
#include <Urho3D/UI/UI.h>
#include <Urho3D/UI/UIEvents.h>
#include <Urho3D/UI/Text.h>

#include "RenderingShowcase.h"

#include <Urho3D/DebugNew.h>

RenderingShowcase::RenderingShowcase(Context* context) : Sample(context)
{
    // All these scenes correspond to Scenes/RenderingShowcase_*.xml resources
    sceneNames_.push_back({ "0" });
    sceneNames_.push_back({ "2_Dynamic", "2_BakedDirect", "2_BakedIndirect", "2_BakedDirectIndirect" });
    // Keep 1 last because it may crash mobile browsers
    sceneNames_.push_back({ "1" });
}

void RenderingShowcase::Start()
{
    // Execute base class startup
    Sample::Start();

    // Create scene content
    CreateScene();
    SetupSelectedScene();

    // Create the UI content
    CreateInstructions();

    // Setup the viewport for displaying the scene
    SetupViewport();

    // Subscribe to global events for camera movement
    SubscribeToEvents();

    // Set the mouse mode to use in the sample
    Sample::InitMouseMode(MM_RELATIVE);
}

void RenderingShowcase::CreateInstructions()
{
    auto* cache = GetSubsystem<ResourceCache>();
    auto* ui = GetSubsystem<UI>();

    // Construct new Text object, set string to display and font to use
    auto* instructionText = ui->GetRoot()->CreateChild<Text>();
    instructionText->SetText("Press Tab to switch scene. Press Q to switch scene mode. \n"
        "Press F to toggle probe object. Use WASD keys and mouse to move.");
    instructionText->SetFont(cache->GetResource<Font>("Fonts/Anonymous Pro.ttf"), 15);
    instructionText->SetTextAlignment(HA_CENTER);

    // Position the text relative to the screen center
    instructionText->SetHorizontalAlignment(HA_CENTER);
    instructionText->SetVerticalAlignment(VA_CENTER);
    instructionText->SetPosition(0, ui->GetRoot()->GetHeight() / 4);
}

void RenderingShowcase::CreateScene()
{
    auto* cache = GetSubsystem<ResourceCache>();

    scene_ = MakeShared<Scene>(context_);
    cameraScene_ = MakeShared<Scene>(context_);

    // Create the camera (not included in the scene file)
    cameraNode_ = cameraScene_->CreateChild("Camera");
    cameraNode_->CreateComponent<Camera>();

    Node* probeObjectNode = cameraNode_->CreateChild();
    probeObjectNode->SetPosition({ 0.0f, 0.0f, 1.0f });
    probeObjectNode->SetScale(0.5f);

    probeObject_ = probeObjectNode->CreateComponent<StaticModel>();
    probeObject_->SetModel(cache->GetResource<Model>("Models/TeaPot.mdl"));
    probeObject_->SetCastShadows(true);
    probeObject_->SetGlobalIlluminationType(GlobalIlluminationType::BlendLightProbes);
}

void RenderingShowcase::SetupSelectedScene(bool resetCamera)
{
    auto* cache = GetSubsystem<ResourceCache>();

    const bool isProbeObjectVisible = probeObject_->IsInOctree();

    if (isProbeObjectVisible)
        scene_->GetComponent<Octree>()->RemoveManualDrawable(probeObject_);

    // Load scene content prepared in the editor (XML format). GetFile() returns an open file from the resource system
    // which scene.LoadXML() will read
    const ea::string fileName = Format("Scenes/RenderingShowcase_{}.xml", sceneNames_[sceneIndex_][sceneMode_]);
    SharedPtr<File> file = cache->GetFile(fileName);
    scene_->LoadXML(*file);

    if (resetCamera)
    {
        cameraNode_->SetPosition({ 0.0f, 4.0f, 8.0f });
        cameraNode_->LookAt(Vector3::ZERO);

        yaw_ = cameraNode_->GetRotation().YawAngle();
        pitch_ = cameraNode_->GetRotation().PitchAngle();
    }

    if (isProbeObjectVisible)
        scene_->GetComponent<Octree>()->AddManualDrawable(probeObject_);
}

void RenderingShowcase::SetupViewport()
{
    auto* cache = GetSubsystem<ResourceCache>();
    auto* renderer = GetSubsystem<Renderer>();

    // Set up a viewport to the Renderer subsystem so that the 3D scene can be seen
    SharedPtr<Viewport> viewport(new Viewport(context_, scene_, cameraNode_->GetComponent<Camera>()));
    renderer->SetViewport(0, viewport);
}

void RenderingShowcase::SubscribeToEvents()
{
    // Subscribe HandleUpdate() function for camera motion
    SubscribeToEvent(E_UPDATE, URHO3D_HANDLER(RenderingShowcase, HandleUpdate));
}

void RenderingShowcase::MoveCamera(float timeStep)
{
    // Right mouse button controls mouse cursor visibility: hide when pressed
    auto* input = GetSubsystem<Input>();

    // Movement speed as world units per second
    const float MOVE_SPEED = 10.0f;
    // Mouse sensitivity as degrees per pixel
    const float MOUSE_SENSITIVITY = 0.1f;

    // Use this frame's mouse motion to adjust camera node yaw and pitch. Clamp the pitch between -90 and 90 degrees
    IntVector2 mouseMove = input->GetMouseMove();
    yaw_ += MOUSE_SENSITIVITY * mouseMove.x_;
    pitch_ += MOUSE_SENSITIVITY * mouseMove.y_;
    pitch_ = Clamp(pitch_, -90.0f, 90.0f);

    // Construct new orientation for the camera scene node from yaw and pitch. Roll is fixed to zero
    cameraNode_->SetRotation(Quaternion(pitch_, yaw_, 0.0f));

    // Read WASD keys and move the camera scene node to the corresponding direction if they are pressed
    if (input->GetKeyDown(KEY_W))
        cameraNode_->Translate(Vector3::FORWARD * MOVE_SPEED * timeStep);
    if (input->GetKeyDown(KEY_S))
        cameraNode_->Translate(Vector3::BACK * MOVE_SPEED * timeStep);
    if (input->GetKeyDown(KEY_A))
        cameraNode_->Translate(Vector3::LEFT * MOVE_SPEED * timeStep);
    if (input->GetKeyDown(KEY_D))
        cameraNode_->Translate(Vector3::RIGHT * MOVE_SPEED * timeStep);
}

void RenderingShowcase::HandleUpdate(StringHash eventType, VariantMap& eventData)
{
    using namespace Update;

    // Take the frame time step, which is stored as a float
    float timeStep = eventData[P_TIMESTEP].GetFloat();

    // Move the camera, scale movement with time step
    MoveCamera(timeStep);

    // Keep probe object orientation
    probeObject_->GetNode()->SetWorldRotation(Quaternion::IDENTITY);

    // Update scene
    auto* input = GetSubsystem<Input>();
    if (sceneNames_.size() > 1 && input->GetKeyPress(KEY_TAB))
    {
        sceneIndex_ = (sceneIndex_ + 1) % sceneNames_.size();
        sceneMode_ = 0;
        SetupSelectedScene();
    }

    // Update scene mode
    if (sceneNames_[sceneIndex_].size() > 1 && input->GetKeyPress(KEY_Q))
    {
        sceneMode_ = (sceneMode_ + 1) % sceneNames_[sceneIndex_].size();
        SetupSelectedScene(false);
    }

    // Update probe object
    if (input->GetKeyPress(KEY_F))
    {
        const bool isProbeObjectVisible = probeObject_->IsInOctree();
        auto* octree = scene_->GetComponent<Octree>();
        if (isProbeObjectVisible)
            octree->RemoveManualDrawable(probeObject_);
        else
            octree->AddManualDrawable(probeObject_);
    }
}
<|endoftext|>


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

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

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

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

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

#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include "itkExceptionObject.h"
#include <iostream>
#include "otbSVMKernels.h"
#include "otbSVMModel.h"

int otbSVMModelCopyGenericKernelTest( int argc, char* argv[] )
{
  typedef unsigned char                                   InputPixelType;
  typedef unsigned char                                   LabelPixelType;

  typedef otb::SVMModel< InputPixelType, LabelPixelType > ModelType;

  // Create the model to be copied
  ModelType::Pointer svmModel = ModelType::New();
  otb::RBFKernelFunctor lFunctor;
  svmModel->SetKernelFunctor(&lFunctor);
  svmModel->LoadModel(argv[1]);

  // Copy the model and print it
  ModelType::Pointer svmModelCopy;
  svmModelCopy = svmModel->GetCopy();
  svmModelCopy->SaveModel(argv[2]);

  return EXIT_SUCCESS;
}

<commit_msg>Qq modifs sur le test de copie du GenericKernelFunctor.<commit_after>/*=========================================================================

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

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

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

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

#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include "itkExceptionObject.h"
#include <iostream>
#include "otbSVMKernels.h"
#include "otbSVMModel.h"

int otbSVMModelCopyGenericKernelTest( int argc, char* argv[] )
{
  typedef unsigned char                                   InputPixelType;
  typedef unsigned char                                   LabelPixelType;

  typedef otb::SVMModel< InputPixelType, LabelPixelType > ModelType;

  // Create the model to be copied
  ModelType::Pointer svmModel = ModelType::New();
  otb::RBFKernelFunctor lFunctor;
  svmModel->SetKernelFunctor(&lFunctor);
  svmModel->LoadModel(argv[1]);

  // Copy the model and print it
  ModelType::Pointer svmModelCopy;
  svmModelCopy = svmModel->GetCopy();
  svmModelCopy->SaveModel(argv[2]);

  return EXIT_SUCCESS;
}

<|endoftext|>


<commit_before>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2012 Esteban Tovagliari.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Has to be first, to avoid redefinition warnings.
#include "Python.h"

// appleseed.python headers.
#include "unaligned_matrix44.h"

// appleseed.foundation headers.
#include "foundation/platform/python.h"

namespace bpy = boost::python;
using namespace foundation;

namespace detail
{
    template <typename T>
    UnalignedMatrix44<T>* construct_matrix_from_list(bpy::list l)
    {
        if (bpy::len(l) != 4 * 4)
        {
            PyErr_SetString(PyExc_RuntimeError, "Invalid list length given to appleseed.Matrix.__init__" );
            bpy::throw_error_already_set();
        }

        UnalignedMatrix44<T>* r = new UnalignedMatrix44<T>();

        for (unsigned i = 0; i < 4 * 4; ++i)
        {
            bpy::extract<T> ex(l[i]);
            if (!ex.check())
            {
                PyErr_SetString(PyExc_TypeError, "Incompatible type. Only floats." );
                bpy::throw_error_already_set();
            }

            (*r)[i] = ex();
        }

        return r;
    }

    template <typename T>
    struct matrix_indexer
    {
        static T get(const UnalignedMatrix44<T>& mat, bpy::tuple indices)
        {
            if (bpy::len(indices) != 2)
            {
                PyErr_SetString(PyExc_RuntimeError, "Invalid tuple length given to appleseed.Matrix.__get_item__" );
                bpy::throw_error_already_set();
            }

            int i, j;

            bpy::extract<int> ex0(indices[0]);
            if (!ex0.check())
            {
                PyErr_SetString(PyExc_TypeError, "Incompatible index type. Only ints." );
                bpy::throw_error_already_set();
            }
            else
                i = ex0();

            bpy::extract<int> ex1(indices[1]);
            if (!ex1.check())
            {
                PyErr_SetString(PyExc_TypeError, "Incompatible index type. Only ints." );
                bpy::throw_error_already_set();
            }
            else
                j = ex1();

            if (i < 0)
                i = 4 + i;

            if (j < 0)
                j = 4 + j;

            if (i >= 0 && i < 4 && j >= 0 && j < 4)
                return mat(i, j);

            PyErr_SetString(PyExc_IndexError, "Out of bounds access in appleseed.Matrix.__get_item__" );
            boost::python::throw_error_already_set();
            return T();
        }

        static void set(UnalignedMatrix44<T>& mat, bpy::tuple indices, const T v)
        {
            if (bpy::len(indices) != 2)
            {
                PyErr_SetString(PyExc_RuntimeError, "Invalid tuple length given to appleseed.Matrix.__set_item__" );
                bpy::throw_error_already_set();
            }

            int i, j;

            bpy::extract<int> ex0(indices[0]);
            if (!ex0.check())
            {
                PyErr_SetString(PyExc_TypeError, "Incompatible index type. Only ints." );
                bpy::throw_error_already_set();
            }
            else
                i = ex0();

            bpy::extract<int> ex1(indices[1]);
            if (!ex1.check())
            {
                PyErr_SetString(PyExc_TypeError, "Incompatible index type. Only ints." );
                bpy::throw_error_already_set();
            }
            else
                j = ex1();

            if (i < 0)
                i = 4 + i;

            if (j < 0)
                j = 4 + j;

            if (i >= 0 && i < 4 && j >= 0 && j < 4)
                mat(i, j) = v;
            else
            {
                PyErr_SetString(PyExc_IndexError, "Out of bounds access in appleseed.Matrix.__set_item__" );
                boost::python::throw_error_already_set();
            }
        }
    };

    template <class T>
    UnalignedMatrix44<T> transpose_matrix(const UnalignedMatrix44<T>& mat)
    {
        return UnalignedMatrix44<T>(transpose(mat.as_foundation_matrix()));
    }

    template <class T>
    bpy::tuple matrix_extract_euler_angles(const UnalignedMatrix44<T>& mat)
    {
        T yaw, pitch, roll;
        mat.as_foundation_matrix().extract_euler_angles(yaw, pitch, roll);
        return bpy::make_tuple(yaw, pitch, roll);
    }

    void bind_typed_matrix4_extra(bpy::class_<UnalignedMatrix44<float> >& X)
    {
        X.def(bpy::init<UnalignedMatrix44<double> >());
    }

    void bind_typed_matrix4_extra(bpy::class_<UnalignedMatrix44<double> >& X)
    {
        X.def(bpy::init<UnalignedMatrix44<float> >());
    }

    template <class T>
    void bind_typed_matrix4(const char* class_name)
    {
        UnalignedMatrix44<T> (*rot1)(T, T, T) = &UnalignedMatrix44<T>::rotation;
        UnalignedMatrix44<T> (*rot2)(const Vector<T,3>&, T) = &UnalignedMatrix44<T>::rotation;
        UnalignedMatrix44<T> (*rot3)(const Quaternion<T>&) = &UnalignedMatrix44<T>::rotation;

        bpy::class_<UnalignedMatrix44<T> > X(class_name);

        X.def("identity", &UnalignedMatrix44<T>::identity).staticmethod("identity")
         .def("translation", &UnalignedMatrix44<T>::translation).staticmethod("translation")
         .def("scaling", &UnalignedMatrix44<T>::scaling).staticmethod("scaling")
         .def("rotation_x", &UnalignedMatrix44<T>::rotation_x).staticmethod("rotation_x")
         .def("rotation_y", &UnalignedMatrix44<T>::rotation_y).staticmethod("rotation_y")
         .def("rotation_z", &UnalignedMatrix44<T>::rotation_z).staticmethod("rotation_z")
         .def("lookat", &UnalignedMatrix44<T>::lookat).staticmethod("lookat")
         .def("rotation", rot1).def("rotation", rot2).def("rotation", rot3).staticmethod("rotation")

         .def(bpy::init<T>())
         .def("__init__", bpy::make_constructor(&construct_matrix_from_list<T>))

         // operator[]
         .def("__getitem__", &matrix_indexer<T>::get)
         .def("__setitem__", &matrix_indexer<T>::set)

         .def("transpose", &transpose_matrix<T>)
         .def("inverse", &invert_matrix<T>)

         .def(bpy::self * bpy::self)
         .def(bpy::self * Vector<T,4>())

         // a bug in boost::python, this needs the extra self_ns qualification
         .def(bpy::self_ns::str(bpy::self))
         .def(bpy::self_ns::repr(bpy::self))

         .def("extract_matrix3", &UnalignedMatrix44<T>::extract_matrix3)
         .def("extract_translation", &UnalignedMatrix44<T>::extract_translation)
         ;

        bind_typed_matrix4_extra(X);
    }
}

void bind_matrix()
{
    detail::bind_typed_matrix4<float>("Matrix4f");
    detail::bind_typed_matrix4<double>("Matrix4d");
}
<commit_msg>minor style tweaks.<commit_after>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2012 Esteban Tovagliari.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Has to be first, to avoid redefinition warnings.
#include "Python.h"

// appleseed.python headers.
#include "unaligned_matrix44.h"

// appleseed.foundation headers.
#include "foundation/platform/python.h"

namespace bpy = boost::python;
using namespace foundation;

namespace detail
{
    template <typename T>
    UnalignedMatrix44<T>* construct_matrix_from_list(bpy::list l)
    {
        if (bpy::len(l) != 4 * 4)
        {
            PyErr_SetString(PyExc_RuntimeError, "Invalid list length given to appleseed.Matrix.__init__");
            bpy::throw_error_already_set();
        }

        UnalignedMatrix44<T>* r = new UnalignedMatrix44<T>();

        for (unsigned i = 0; i < 4 * 4; ++i)
        {
            bpy::extract<T> ex(l[i]);
            if (!ex.check())
            {
                PyErr_SetString(PyExc_TypeError, "Incompatible type. Only floats.");
                bpy::throw_error_already_set();
            }

            (*r)[i] = ex();
        }

        return r;
    }

    template <typename T>
    struct matrix_indexer
    {
        static T get(const UnalignedMatrix44<T>& mat, bpy::tuple indices)
        {
            if (bpy::len(indices) != 2)
            {
                PyErr_SetString(PyExc_RuntimeError, "Invalid tuple length given to appleseed.Matrix.__get_item__");
                bpy::throw_error_already_set();
            }

            int i, j;

            bpy::extract<int> ex0(indices[0]);
            if (!ex0.check())
            {
                PyErr_SetString(PyExc_TypeError, "Incompatible index type. Only ints.");
                bpy::throw_error_already_set();
            }
            else
                i = ex0();

            bpy::extract<int> ex1(indices[1]);
            if (!ex1.check())
            {
                PyErr_SetString(PyExc_TypeError, "Incompatible index type. Only ints.");
                bpy::throw_error_already_set();
            }
            else
                j = ex1();

            if (i < 0)
                i = 4 + i;

            if (j < 0)
                j = 4 + j;

            if (i >= 0 && i < 4 && j >= 0 && j < 4)
                return mat(i, j);

            PyErr_SetString(PyExc_IndexError, "Out of bounds access in appleseed.Matrix.__get_item__");
            boost::python::throw_error_already_set();
            return T();
        }

        static void set(UnalignedMatrix44<T>& mat, bpy::tuple indices, const T v)
        {
            if (bpy::len(indices) != 2)
            {
                PyErr_SetString(PyExc_RuntimeError, "Invalid tuple length given to appleseed.Matrix.__set_item__");
                bpy::throw_error_already_set();
            }

            int i, j;

            bpy::extract<int> ex0(indices[0]);
            if (!ex0.check())
            {
                PyErr_SetString(PyExc_TypeError, "Incompatible index type. Only ints.");
                bpy::throw_error_already_set();
            }
            else
                i = ex0();

            bpy::extract<int> ex1(indices[1]);
            if (!ex1.check())
            {
                PyErr_SetString(PyExc_TypeError, "Incompatible index type. Only ints.");
                bpy::throw_error_already_set();
            }
            else
                j = ex1();

            if (i < 0)
                i = 4 + i;

            if (j < 0)
                j = 4 + j;

            if (i >= 0 && i < 4 && j >= 0 && j < 4)
                mat(i, j) = v;
            else
            {
                PyErr_SetString(PyExc_IndexError, "Out of bounds access in appleseed.Matrix.__set_item__");
                boost::python::throw_error_already_set();
            }
        }
    };

    template <class T>
    UnalignedMatrix44<T> transpose_matrix(const UnalignedMatrix44<T>& mat)
    {
        return UnalignedMatrix44<T>(transpose(mat.as_foundation_matrix()));
    }

    template <class T>
    bpy::tuple matrix_extract_euler_angles(const UnalignedMatrix44<T>& mat)
    {
        T yaw, pitch, roll;
        mat.as_foundation_matrix().extract_euler_angles(yaw, pitch, roll);
        return bpy::make_tuple(yaw, pitch, roll);
    }

    void bind_typed_matrix4_extra(bpy::class_<UnalignedMatrix44<float> >& X)
    {
        X.def(bpy::init<UnalignedMatrix44<double> >());
    }

    void bind_typed_matrix4_extra(bpy::class_<UnalignedMatrix44<double> >& X)
    {
        X.def(bpy::init<UnalignedMatrix44<float> >());
    }

    template <class T>
    void bind_typed_matrix4(const char* class_name)
    {
        UnalignedMatrix44<T> (*rot1)(T, T, T) = &UnalignedMatrix44<T>::rotation;
        UnalignedMatrix44<T> (*rot2)(const Vector<T,3>&, T) = &UnalignedMatrix44<T>::rotation;
        UnalignedMatrix44<T> (*rot3)(const Quaternion<T>&) = &UnalignedMatrix44<T>::rotation;

        bpy::class_<UnalignedMatrix44<T> > X(class_name);

        X.def("identity", &UnalignedMatrix44<T>::identity).staticmethod("identity")
         .def("translation", &UnalignedMatrix44<T>::translation).staticmethod("translation")
         .def("scaling", &UnalignedMatrix44<T>::scaling).staticmethod("scaling")
         .def("rotation_x", &UnalignedMatrix44<T>::rotation_x).staticmethod("rotation_x")
         .def("rotation_y", &UnalignedMatrix44<T>::rotation_y).staticmethod("rotation_y")
         .def("rotation_z", &UnalignedMatrix44<T>::rotation_z).staticmethod("rotation_z")
         .def("lookat", &UnalignedMatrix44<T>::lookat).staticmethod("lookat")
         .def("rotation", rot1).def("rotation", rot2).def("rotation", rot3).staticmethod("rotation")

         .def(bpy::init<T>())
         .def("__init__", bpy::make_constructor(&construct_matrix_from_list<T>))

         // operator[]
         .def("__getitem__", &matrix_indexer<T>::get)
         .def("__setitem__", &matrix_indexer<T>::set)

         .def("transpose", &transpose_matrix<T>)
         .def("inverse", &invert_matrix<T>)

         .def(bpy::self * bpy::self)
         .def(bpy::self * Vector<T,4>())

         // a bug in boost::python, this needs the extra self_ns qualification
         .def(bpy::self_ns::str(bpy::self))
         .def(bpy::self_ns::repr(bpy::self))

         .def("extract_matrix3", &UnalignedMatrix44<T>::extract_matrix3)
         .def("extract_translation", &UnalignedMatrix44<T>::extract_translation)
         ;

        bind_typed_matrix4_extra(X);
    }
}

void bind_matrix()
{
    detail::bind_typed_matrix4<float>("Matrix4f");
    detail::bind_typed_matrix4<double>("Matrix4d");
}
<|endoftext|>


<commit_before>#pragma once

namespace Penciloid
{
template <typename T, const int SIZE>
class MiniVector
{
public:
	MiniVector<T, SIZE>() : loc(0) { }

	void push_back(T &data) { storage[loc++] = data; }
	void clear() { loc = 0; }
	int size() { return loc; }
	T &operator[](int i) { return storage[i]; }
	T* begin() { return storage; }
	T* end() { return &(storage[loc]); }

private:
	T storage[SIZE];
	int loc;
};

}
<commit_msg>Modify MiniVector (add const)<commit_after>#pragma once

namespace Penciloid
{
template <typename T, const int SIZE>
class MiniVector
{
public:
	MiniVector<T, SIZE>() : loc(0) { }

	void push_back(const T &data) { storage[loc++] = data; }
	void clear() { loc = 0; }
	int size() const { return loc; }
	T &operator[](int i) { return storage[i]; }
	T* begin() { return storage; }
	T* end() { return &(storage[loc]); }

private:
	T storage[SIZE];
	int loc;
};

}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2004 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef __ARCH_GENERIC_LINUX_THREADINFO_HH__
#define __ARCH_GENERIC_LINUX_THREADINFO_HH__

#include "cpu/thread_context.hh"
#include "sim/system.hh"

namespace Linux {

class ThreadInfo
{
  private:
    ThreadContext *tc;
    System *sys;
    Addr pcbb;

    template <typename T>
    bool
    get_data(const char *symbol, T &data)
    {
        auto &symtab = sys->workload->symtab(tc);
        auto it = symtab.find(symbol);
        if (it == symtab.end()) {
            warn_once("Unable to find kernel symbol %s\n", symbol);
            warn_once("Kernel not compiled with task_struct info; can't get "
                      "currently executing task/process/thread name/ids!\n");
            return false;
        }

        data = tc->getVirtProxy().read<T>(it->address, TheISA::GuestByteOrder);

        return true;
    }

  public:
    ThreadInfo(ThreadContext *_tc, Addr _pcbb = 0)
        : tc(_tc), sys(tc->getSystemPtr()), pcbb(_pcbb)
    {

    }
    ~ThreadInfo()
    {}

    inline Addr
    curThreadInfo()
    {
        if (!TheISA::CurThreadInfoImplemented)
            panic("curThreadInfo() not implemented for this ISA");

        Addr addr = pcbb;
        Addr sp;

        if (!addr)
            addr = tc->readMiscRegNoEffect(TheISA::CurThreadInfoReg);

        PortProxy &p = tc->getPhysProxy();
        p.readBlob(addr, &sp, sizeof(Addr));

        return sp & ~ULL(0x3fff);
    }

    inline Addr
    curTaskInfo(Addr thread_info = 0)
    {
        // Note that in Linux 4.10 the thread_info struct will no longer have a
        // pointer to the task_struct for arm64. See:
        // https://patchwork.kernel.org/patch/9333699/
        int32_t offset = 0;
        if (!get_data("thread_info_task", offset))
            return 0;

        if (!thread_info)
            thread_info = curThreadInfo();

        return tc->getVirtProxy().read<Addr>(thread_info + offset);
    }

    int32_t
    curTaskPIDFromTaskStruct(Addr task_struct) {
        int32_t offset = 0;
        if (!get_data("task_struct_pid", offset))
            return -1;

        return tc->getVirtProxy().read<int32_t>(task_struct + offset);
    }

    int32_t
    curTaskPID(Addr thread_info = 0)
    {
        return curTaskPIDFromTaskStruct(curTaskInfo(thread_info));
    }

    int32_t
    curTaskTGIDFromTaskStruct(Addr task_struct)
    {
        int32_t offset = 0;
        if (!get_data("task_struct_tgid", offset))
            return -1;

        return tc->getVirtProxy().read<int32_t>(task_struct + offset);
    }

    int32_t
    curTaskTGID(Addr thread_info = 0)
    {
        return curTaskTGIDFromTaskStruct(curTaskInfo(thread_info));
    }

    int64_t
    curTaskStartFromTaskStruct(Addr task_struct)
    {
        int32_t offset = 0;
        if (!get_data("task_struct_start_time", offset))
            return -1;

        // start_time is actually of type timespec, but if we just
        // grab the first long, we'll get the seconds out of it
        return tc->getVirtProxy().read<int64_t>(task_struct + offset);
    }

    int64_t
    curTaskStart(Addr thread_info = 0)
    {
        return curTaskStartFromTaskStruct(curTaskInfo(thread_info));
    }

    std::string
    curTaskNameFromTaskStruct(Addr task_struct)
    {
        int32_t offset = 0;
        int32_t size = 0;

        if (!get_data("task_struct_comm", offset))
            return "FailureIn_curTaskName";

        if (!get_data("task_struct_comm_size", size))
            return "FailureIn_curTaskName";

        char buffer[size + 1];
        tc->getVirtProxy().readString(buffer, task_struct + offset, size);

        return buffer;
    }

    std::string
    curTaskName(Addr thread_info = 0)
    {
        return curTaskNameFromTaskStruct(curTaskInfo(thread_info));
    }

    int32_t
    curTaskMmFromTaskStruct(Addr task_struct)
    {
        int32_t offset;
        if (!get_data("task_struct_mm", offset))
            return -1;

        return tc->getVirtProxy().read<int32_t>(task_struct + offset);
    }

    int32_t
    curTaskMm(Addr thread_info = 0)
    {
        return curTaskMmFromTaskStruct(curTaskInfo(thread_info));
    }
};

} // namespace Linux

#endif // __ARCH_GENERIC_LINUX_THREADINFO_HH__
<commit_msg>arch: Fix a small style issue in Linux::ThreadInfo.<commit_after>/*
 * Copyright (c) 2004 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef __ARCH_GENERIC_LINUX_THREADINFO_HH__
#define __ARCH_GENERIC_LINUX_THREADINFO_HH__

#include "cpu/thread_context.hh"
#include "sim/system.hh"

namespace Linux {

class ThreadInfo
{
  private:
    ThreadContext *tc;
    System *sys;
    Addr pcbb;

    template <typename T>
    bool
    get_data(const char *symbol, T &data)
    {
        auto &symtab = sys->workload->symtab(tc);
        auto it = symtab.find(symbol);
        if (it == symtab.end()) {
            warn_once("Unable to find kernel symbol %s\n", symbol);
            warn_once("Kernel not compiled with task_struct info; can't get "
                      "currently executing task/process/thread name/ids!\n");
            return false;
        }

        data = tc->getVirtProxy().read<T>(it->address, TheISA::GuestByteOrder);

        return true;
    }

  public:
    ThreadInfo(ThreadContext *_tc, Addr _pcbb = 0)
        : tc(_tc), sys(tc->getSystemPtr()), pcbb(_pcbb)
    {

    }
    ~ThreadInfo()
    {}

    inline Addr
    curThreadInfo()
    {
        if (!TheISA::CurThreadInfoImplemented)
            panic("curThreadInfo() not implemented for this ISA");

        Addr addr = pcbb;
        Addr sp;

        if (!addr)
            addr = tc->readMiscRegNoEffect(TheISA::CurThreadInfoReg);

        PortProxy &p = tc->getPhysProxy();
        p.readBlob(addr, &sp, sizeof(Addr));

        return sp & ~ULL(0x3fff);
    }

    inline Addr
    curTaskInfo(Addr thread_info = 0)
    {
        // Note that in Linux 4.10 the thread_info struct will no longer have a
        // pointer to the task_struct for arm64. See:
        // https://patchwork.kernel.org/patch/9333699/
        int32_t offset = 0;
        if (!get_data("thread_info_task", offset))
            return 0;

        if (!thread_info)
            thread_info = curThreadInfo();

        return tc->getVirtProxy().read<Addr>(thread_info + offset);
    }

    int32_t
    curTaskPIDFromTaskStruct(Addr task_struct)
    {
        int32_t offset = 0;
        if (!get_data("task_struct_pid", offset))
            return -1;

        return tc->getVirtProxy().read<int32_t>(task_struct + offset);
    }

    int32_t
    curTaskPID(Addr thread_info = 0)
    {
        return curTaskPIDFromTaskStruct(curTaskInfo(thread_info));
    }

    int32_t
    curTaskTGIDFromTaskStruct(Addr task_struct)
    {
        int32_t offset = 0;
        if (!get_data("task_struct_tgid", offset))
            return -1;

        return tc->getVirtProxy().read<int32_t>(task_struct + offset);
    }

    int32_t
    curTaskTGID(Addr thread_info = 0)
    {
        return curTaskTGIDFromTaskStruct(curTaskInfo(thread_info));
    }

    int64_t
    curTaskStartFromTaskStruct(Addr task_struct)
    {
        int32_t offset = 0;
        if (!get_data("task_struct_start_time", offset))
            return -1;

        // start_time is actually of type timespec, but if we just
        // grab the first long, we'll get the seconds out of it
        return tc->getVirtProxy().read<int64_t>(task_struct + offset);
    }

    int64_t
    curTaskStart(Addr thread_info = 0)
    {
        return curTaskStartFromTaskStruct(curTaskInfo(thread_info));
    }

    std::string
    curTaskNameFromTaskStruct(Addr task_struct)
    {
        int32_t offset = 0;
        int32_t size = 0;

        if (!get_data("task_struct_comm", offset))
            return "FailureIn_curTaskName";

        if (!get_data("task_struct_comm_size", size))
            return "FailureIn_curTaskName";

        char buffer[size + 1];
        tc->getVirtProxy().readString(buffer, task_struct + offset, size);

        return buffer;
    }

    std::string
    curTaskName(Addr thread_info = 0)
    {
        return curTaskNameFromTaskStruct(curTaskInfo(thread_info));
    }

    int32_t
    curTaskMmFromTaskStruct(Addr task_struct)
    {
        int32_t offset;
        if (!get_data("task_struct_mm", offset))
            return -1;

        return tc->getVirtProxy().read<int32_t>(task_struct + offset);
    }

    int32_t
    curTaskMm(Addr thread_info = 0)
    {
        return curTaskMmFromTaskStruct(curTaskInfo(thread_info));
    }
};

} // namespace Linux

#endif // __ARCH_GENERIC_LINUX_THREADINFO_HH__
<|endoftext|>


<commit_before>//
// Copyright (c) 2002-2010 The ANGLE 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.
//

#include "compiler/Initialize.h"
#include "compiler/ParseHelper.h"
#include "compiler/ShHandle.h"

static bool InitializeSymbolTable(
        const TBuiltInStrings& builtInStrings,
        EShLanguage language, EShSpec spec, const TBuiltInResource& resources,
        TInfoSink& infoSink, TSymbolTable& symbolTable)
{
    TIntermediate intermediate(infoSink);
    TExtensionBehavior extBehavior;
    TParseContext parseContext(symbolTable, extBehavior, intermediate, language, spec, infoSink);

    GlobalParseContext = &parseContext;

    setInitialState();

    assert(symbolTable.isEmpty());
    //
    // Parse the built-ins.  This should only happen once per
    // language symbol table.
    //
    // Push the symbol table to give it an initial scope.  This
    // push should not have a corresponding pop, so that built-ins
    // are preserved, and the test for an empty table fails.
    //
    symbolTable.push();

    //Initialize the Preprocessor
    if (InitPreprocessor())
    {
        infoSink.info.message(EPrefixInternalError,  "Unable to intialize the Preprocessor");
        return false;
    }

    for (TBuiltInStrings::const_iterator i = builtInStrings.begin(); i != builtInStrings.end(); ++i)
    {
        const char* builtInShaders[1];
        int builtInLengths[1];

        builtInShaders[0] = (*i).c_str();
        builtInLengths[0] = (int) (*i).size();

        if (PaParseStrings(builtInShaders, builtInLengths, 1, parseContext) != 0)
        {
            infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins");
            return false;
        }
    }

    IdentifyBuiltIns(language, spec, resources, symbolTable);

    FinalizePreprocessor();

    return true;
}

static void DefineExtensionMacros(const TExtensionBehavior& extBehavior)
{
    for (TExtensionBehavior::const_iterator iter = extBehavior.begin();
         iter != extBehavior.end(); ++iter) {
        PredefineIntMacro(iter->first.c_str(), 1);
    }
}

bool TCompiler::Init(const TBuiltInResource& resources)
{
    // Generate built-in symbol table.
    if (!InitBuiltInSymbolTable(resources))
        return false;

    InitExtensionBehavior(resources, extensionBehavior);
    return true;
}

bool TCompiler::compile(const char* const shaderStrings[],
                        const int numStrings,
                        int compileOptions)
{
    clearResults();

    if (numStrings == 0)
        return true;

    TIntermediate intermediate(infoSink);
    TParseContext parseContext(symbolTable, extensionBehavior, intermediate,
                               language, spec, infoSink);
    GlobalParseContext = &parseContext;
    setInitialState();

    // Initialize preprocessor.
    InitPreprocessor();
    DefineExtensionMacros(extensionBehavior);

    // We preserve symbols at the built-in level from compile-to-compile.
    // Start pushing the user-defined symbols at global level.
    symbolTable.push();
    if (!symbolTable.atGlobalLevel())
        infoSink.info.message(EPrefixInternalError, "Wrong symbol table level");

    // Parse shader.
    bool success =
        (PaParseStrings(shaderStrings, 0, numStrings, parseContext) == 0) &&
        (parseContext.treeRoot != NULL);
    if (success) {
        success = intermediate.postProcess(parseContext.treeRoot);

        if (success && (compileOptions & EShOptIntermediateTree))
            intermediate.outputTree(parseContext.treeRoot);

        if (success && (compileOptions & EShOptObjectCode))
            translate(parseContext.treeRoot);

        if (success && (compileOptions & EShOptAttribsUniforms))
            collectAttribsUniforms(parseContext.treeRoot);
    }

    // Cleanup memory.
    intermediate.remove(parseContext.treeRoot);
    // Ensure symbol table is returned to the built-in level,
    // throwing away all but the built-ins.
    while (!symbolTable.atBuiltInLevel())
        symbolTable.pop();
    FinalizePreprocessor();

    return success;
}

bool TCompiler::InitBuiltInSymbolTable(const TBuiltInResource& resources)
{
    TBuiltIns builtIns;

    builtIns.initialize(language, spec, resources);
    return InitializeSymbolTable(builtIns.getBuiltInStrings(), language, spec, resources, infoSink, symbolTable);
}

void TCompiler::clearResults()
{
    infoSink.info.erase();
    infoSink.obj.erase();
    infoSink.debug.erase();

    attribs.clear();
    uniforms.clear();
}

void TCompiler::collectAttribsUniforms(TIntermNode* root)
{
    CollectAttribsUniforms collect(attribs, uniforms);
    root->traverse(&collect);
}

<commit_msg>Built-in string for vertex shaders can be empty. Nicolas handled this case in r433 but r437 overwrote it. Review URL: http://codereview.appspot.com/2233046<commit_after>//
// Copyright (c) 2002-2010 The ANGLE 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.
//

#include "compiler/Initialize.h"
#include "compiler/ParseHelper.h"
#include "compiler/ShHandle.h"

static bool InitializeSymbolTable(
        const TBuiltInStrings& builtInStrings,
        EShLanguage language, EShSpec spec, const TBuiltInResource& resources,
        TInfoSink& infoSink, TSymbolTable& symbolTable)
{
    TIntermediate intermediate(infoSink);
    TExtensionBehavior extBehavior;
    TParseContext parseContext(symbolTable, extBehavior, intermediate, language, spec, infoSink);

    GlobalParseContext = &parseContext;

    setInitialState();

    assert(symbolTable.isEmpty());
    //
    // Parse the built-ins.  This should only happen once per
    // language symbol table.
    //
    // Push the symbol table to give it an initial scope.  This
    // push should not have a corresponding pop, so that built-ins
    // are preserved, and the test for an empty table fails.
    //
    symbolTable.push();

    //Initialize the Preprocessor
    if (InitPreprocessor())
    {
        infoSink.info.message(EPrefixInternalError,  "Unable to intialize the Preprocessor");
        return false;
    }

    for (TBuiltInStrings::const_iterator i = builtInStrings.begin(); i != builtInStrings.end(); ++i)
    {
        const char* builtInShaders = i->c_str();
        int builtInLengths = static_cast<int>(i->size());
        if (builtInLengths <= 0)
          continue;

        if (PaParseStrings(&builtInShaders, &builtInLengths, 1, parseContext) != 0)
        {
            infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins");
            return false;
        }
    }

    IdentifyBuiltIns(language, spec, resources, symbolTable);

    FinalizePreprocessor();

    return true;
}

static void DefineExtensionMacros(const TExtensionBehavior& extBehavior)
{
    for (TExtensionBehavior::const_iterator iter = extBehavior.begin();
         iter != extBehavior.end(); ++iter) {
        PredefineIntMacro(iter->first.c_str(), 1);
    }
}

bool TCompiler::Init(const TBuiltInResource& resources)
{
    // Generate built-in symbol table.
    if (!InitBuiltInSymbolTable(resources))
        return false;

    InitExtensionBehavior(resources, extensionBehavior);
    return true;
}

bool TCompiler::compile(const char* const shaderStrings[],
                        const int numStrings,
                        int compileOptions)
{
    clearResults();

    if (numStrings == 0)
        return true;

    TIntermediate intermediate(infoSink);
    TParseContext parseContext(symbolTable, extensionBehavior, intermediate,
                               language, spec, infoSink);
    GlobalParseContext = &parseContext;
    setInitialState();

    // Initialize preprocessor.
    InitPreprocessor();
    DefineExtensionMacros(extensionBehavior);

    // We preserve symbols at the built-in level from compile-to-compile.
    // Start pushing the user-defined symbols at global level.
    symbolTable.push();
    if (!symbolTable.atGlobalLevel())
        infoSink.info.message(EPrefixInternalError, "Wrong symbol table level");

    // Parse shader.
    bool success =
        (PaParseStrings(shaderStrings, 0, numStrings, parseContext) == 0) &&
        (parseContext.treeRoot != NULL);
    if (success) {
        success = intermediate.postProcess(parseContext.treeRoot);

        if (success && (compileOptions & EShOptIntermediateTree))
            intermediate.outputTree(parseContext.treeRoot);

        if (success && (compileOptions & EShOptObjectCode))
            translate(parseContext.treeRoot);

        if (success && (compileOptions & EShOptAttribsUniforms))
            collectAttribsUniforms(parseContext.treeRoot);
    }

    // Cleanup memory.
    intermediate.remove(parseContext.treeRoot);
    // Ensure symbol table is returned to the built-in level,
    // throwing away all but the built-ins.
    while (!symbolTable.atBuiltInLevel())
        symbolTable.pop();
    FinalizePreprocessor();

    return success;
}

bool TCompiler::InitBuiltInSymbolTable(const TBuiltInResource& resources)
{
    TBuiltIns builtIns;

    builtIns.initialize(language, spec, resources);
    return InitializeSymbolTable(builtIns.getBuiltInStrings(), language, spec, resources, infoSink, symbolTable);
}

void TCompiler::clearResults()
{
    infoSink.info.erase();
    infoSink.obj.erase();
    infoSink.debug.erase();

    attribs.clear();
    uniforms.clear();
}

void TCompiler::collectAttribsUniforms(TIntermNode* root)
{
    CollectAttribsUniforms collect(attribs, uniforms);
    root->traverse(&collect);
}

<|endoftext|>


<commit_before>// l2_fused_mv.cpp example program to demonstrate BLAS L2 Reproducible Matrix-Vector product
//
// Copyright (C) 2017-2018 Stillwater Supercomputing, Inc.
//
// This file is part of the universal numbers project, which is released under an MIT Open Source license.
#include "common.hpp"
#include <posit>
#include "blas_operators.hpp"

int main(int argc, char** argv)
try {
	const size_t nbits = 8;
	const size_t es = 0;
	const size_t vecSize = 32;

	int nrOfFailedTestCases = 0;

	return (nrOfFailedTestCases > 0 ? EXIT_FAILURE : EXIT_SUCCESS);
}
catch (char const* msg) {
	std::cerr << msg << std::endl;
	return EXIT_FAILURE;
}
catch (std::runtime_error& err) {
	std::cerr << err.what() << std::endl;
	return EXIT_FAILURE;
}
catch (...) {
	std::cerr << "Caught unknown exception" << std::endl;
	return EXIT_FAILURE;
}
<commit_msg>WIP: adding fused matvec example<commit_after>// l2_fused_mv.cpp example program to demonstrate BLAS L2 Reproducible Matrix-Vector product
//
// Copyright (C) 2017-2018 Stillwater Supercomputing, Inc.
//
// This file is part of the universal numbers project, which is released under an MIT Open Source license.
#include "common.hpp"
#include <posit>
#include "blas_operators.hpp"

int main(int argc, char** argv)
try {
	using namespace std;

	const size_t nbits = 8;
	const size_t es = 0;
	const size_t vecSize = 32;

	int nrOfFailedTestCases = 0;

	{
		vector<double> A = {
			1.0, 0.0, 0.0,
			0.0, 1.0, 0.0,
			0.0, 0.0, 1.0
		};
		vector<double> x = { DBL_EPSILON, DBL_EPSILON, DBL_EPSILON };
		vector<double> b(3);
		matvec(A, x, b);
		cout << setprecision(21);
		print(cout, 3, b, 1);
		cout << endl;
	}

	{
		// we can represent DBL_EPSILON with a 32-bit posit
		using posit_32_2 = sw::unum::posit<32, 2>;

		vector< posit_32_2 > A = {
			1.0, 0.0, 0.0,
			0.0, 1.0, 0.0,
			0.0, 0.0, 1.0
		};
		vector<posit_32_2> x = { DBL_EPSILON, DBL_EPSILON, DBL_EPSILON };
		vector<posit_32_2> b(3);
		matvec(A, x, b);
		print(cout, 3, b, 1);
		cout << endl;

	}

	return (nrOfFailedTestCases > 0 ? EXIT_FAILURE : EXIT_SUCCESS);
}
catch (char const* msg) {
	std::cerr << msg << std::endl;
	return EXIT_FAILURE;
}
catch (std::runtime_error& err) {
	std::cerr << err.what() << std::endl;
	return EXIT_FAILURE;
}
catch (...) {
	std::cerr << "Caught unknown exception" << std::endl;
	return EXIT_FAILURE;
}
<|endoftext|>