<commit_before>//
// Copyright 2020 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.
//
// TracePerf:
//   Performance test for ANGLE replaying traces.
//

#include <gtest/gtest.h>
#include "common/PackedEnums.h"
#include "common/system_utils.h"
#include "tests/perf_tests/ANGLEPerfTest.h"
#include "tests/perf_tests/DrawCallPerfParams.h"
#include "util/egl_loader_autogen.h"
#include "util/frame_capture_test_utils.h"
#include "util/png_utils.h"

#include "restricted_traces/restricted_traces_autogen.h"

#include <cassert>
#include <functional>
#include <sstream>

using namespace angle;
using namespace egl_platform;

namespace
{
struct TracePerfParams final : public RenderTestParams
{
    // Common default options
    TracePerfParams()
    {
        majorVersion = 3;
        minorVersion = 0;
        trackGpuTime = true;

        // Display the frame after every drawBenchmark invocation
        iterationsPerStep = 1;
    }

    std::string story() const override
    {
        std::stringstream strstr;
        strstr << RenderTestParams::story() << "_" << GetTraceInfo(testID).name;
        return strstr.str();
    }

    RestrictedTraceID testID;
};

std::ostream &operator<<(std::ostream &os, const TracePerfParams &params)
{
    os << params.backendAndStory().substr(1);
    return os;
}

class TracePerfTest : public ANGLERenderTest, public ::testing::WithParamInterface<TracePerfParams>
{
  public:
    TracePerfTest();

    void initializeBenchmark() override;
    void destroyBenchmark() override;
    void drawBenchmark() override;

    void onReplayFramebufferChange(GLenum target, GLuint framebuffer);

    uint32_t mStartFrame;
    uint32_t mEndFrame;

    double getHostTimeFromGLTime(GLint64 glTime);

  private:
    struct QueryInfo
    {
        GLuint beginTimestampQuery;
        GLuint endTimestampQuery;
        GLuint framebuffer;
    };

    struct TimeSample
    {
        GLint64 glTime;
        double hostTime;
    };

    void sampleTime();
    void saveScreenshot(const std::string &screenshotName) override;

    // For tracking RenderPass/FBO change timing.
    QueryInfo mCurrentQuery = {};
    std::vector<QueryInfo> mRunningQueries;
    std::vector<TimeSample> mTimeline;

    std::string mStartingDirectory;
};

TracePerfTest::TracePerfTest()
    : ANGLERenderTest("TracePerf", GetParam()), mStartFrame(0), mEndFrame(0)
{
    const TracePerfParams &param = GetParam();

    // TODO: http://anglebug.com/4533 This fails after the upgrade to the 26.20.100.7870 driver.
    if (IsWindows() && IsIntel() && param.getRenderer() == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE &&
        param.testID == RestrictedTraceID::manhattan_10)
    {
        mSkipTest = true;
    }

    // TODO: http://anglebug.com/4731 Fails on older Intel drivers. Passes in newer.
    if (IsWindows() && IsIntel() && param.driver != GLESDriverType::AngleEGL &&
        param.testID == RestrictedTraceID::angry_birds_2_1500)
    {
        mSkipTest = true;
    }

    // We already swap in TracePerfTest::drawBenchmark, no need to swap again in the harness.
    disableTestHarnessSwap();
}

void TracePerfTest::initializeBenchmark()
{
    const auto &params = GetParam();

    mStartingDirectory = angle::GetCWD().value();

    // To load the trace data path correctly we set the CWD to the executable dir.
    if (!IsAndroid())
    {
        std::string exeDir = angle::GetExecutableDirectory();
        angle::SetCWD(exeDir.c_str());
    }

    const TraceInfo &traceInfo = GetTraceInfo(params.testID);
    mStartFrame                = traceInfo.startFrame;
    mEndFrame                  = traceInfo.endFrame;
    SetBinaryDataDecompressCallback(params.testID, DecompressBinaryData);

    std::stringstream testDataDirStr;
    testDataDirStr << ANGLE_TRACE_DATA_DIR << "/" << traceInfo.name;
    std::string testDataDir = testDataDirStr.str();
    SetBinaryDataDir(params.testID, testDataDir.c_str());

    if (IsAndroid())
    {
        // On Android, set the orientation used by the app, based on width/height
        getWindow()->setOrientation(mTestParams.windowWidth, mTestParams.windowHeight);
    }

    // Potentially slow. Can load a lot of resources.
    SetupReplay(params.testID);
    glFinish();

    ASSERT_TRUE(mEndFrame > mStartFrame);

    getWindow()->setVisible(true);
}

#undef TRACE_TEST_CASE

void TracePerfTest::destroyBenchmark()
{
    // In order for the next test to load, restore the working directory
    angle::SetCWD(mStartingDirectory.c_str());
}

void TracePerfTest::sampleTime()
{
    if (mIsTimestampQueryAvailable)
    {
        GLint64 glTime;
        // glGetInteger64vEXT is exported by newer versions of the timer query extensions.
        // Unfortunately only the core EP is exposed by some desktop drivers (e.g. NVIDIA).
        if (glGetInteger64vEXT)
        {
            glGetInteger64vEXT(GL_TIMESTAMP_EXT, &glTime);
        }
        else
        {
            glGetInteger64v(GL_TIMESTAMP_EXT, &glTime);
        }
        mTimeline.push_back({glTime, angle::GetHostTimeSeconds()});
    }
}

void TracePerfTest::drawBenchmark()
{
    // Add a time sample from GL and the host.
    sampleTime();

    startGpuTimer();

    for (uint32_t frame = mStartFrame; frame <= mEndFrame; ++frame)
    {
        char frameName[32];
        sprintf(frameName, "Frame %u", frame);
        beginInternalTraceEvent(frameName);

        ReplayFrame(GetParam().testID, frame);
        getGLWindow()->swap();

        endInternalTraceEvent(frameName);
    }

    ResetReplay(GetParam().testID);

    // Process any running queries once per iteration.
    for (size_t queryIndex = 0; queryIndex < mRunningQueries.size();)
    {
        const QueryInfo &query = mRunningQueries[queryIndex];

        GLuint endResultAvailable = 0;
        glGetQueryObjectuivEXT(query.endTimestampQuery, GL_QUERY_RESULT_AVAILABLE,
                               &endResultAvailable);

        if (endResultAvailable == GL_TRUE)
        {
            char fboName[32];
            sprintf(fboName, "FBO %u", query.framebuffer);

            GLint64 beginTimestamp = 0;
            glGetQueryObjecti64vEXT(query.beginTimestampQuery, GL_QUERY_RESULT, &beginTimestamp);
            glDeleteQueriesEXT(1, &query.beginTimestampQuery);
            double beginHostTime = getHostTimeFromGLTime(beginTimestamp);
            beginGLTraceEvent(fboName, beginHostTime);

            GLint64 endTimestamp = 0;
            glGetQueryObjecti64vEXT(query.endTimestampQuery, GL_QUERY_RESULT, &endTimestamp);
            glDeleteQueriesEXT(1, &query.endTimestampQuery);
            double endHostTime = getHostTimeFromGLTime(endTimestamp);
            endGLTraceEvent(fboName, endHostTime);

            mRunningQueries.erase(mRunningQueries.begin() + queryIndex);
        }
        else
        {
            queryIndex++;
        }
    }

    stopGpuTimer();
}

// Converts a GL timestamp into a host-side CPU time aligned with "GetHostTimeSeconds".
// This check is necessary to line up sampled trace events in a consistent timeline.
// Uses a linear interpolation from a series of samples. We do a blocking call to sample
// both host and GL time once per swap. We then find the two closest GL timestamps and
// interpolate the host times between them to compute our result. If we are past the last
// GL timestamp we sample a new data point pair.
double TracePerfTest::getHostTimeFromGLTime(GLint64 glTime)
{
    // Find two samples to do a lerp.
    size_t firstSampleIndex = mTimeline.size() - 1;
    while (firstSampleIndex > 0)
    {
        if (mTimeline[firstSampleIndex].glTime < glTime)
        {
            break;
        }
        firstSampleIndex--;
    }

    // Add an extra sample if we're missing an ending sample.
    if (firstSampleIndex == mTimeline.size() - 1)
    {
        sampleTime();
    }

    const TimeSample &start = mTimeline[firstSampleIndex];
    const TimeSample &end   = mTimeline[firstSampleIndex + 1];

    // Note: we have observed in some odd cases later timestamps producing values that are
    // smaller than preceding timestamps. This bears further investigation.

    // Compute the scaling factor for the lerp.
    double glDelta = static_cast<double>(glTime - start.glTime);
    double glRange = static_cast<double>(end.glTime - start.glTime);
    double t       = glDelta / glRange;

    // Lerp(t1, t2, t)
    double hostRange = end.hostTime - start.hostTime;
    return mTimeline[firstSampleIndex].hostTime + hostRange * t;
}

// Triggered when the replay calls glBindFramebuffer.
void TracePerfTest::onReplayFramebufferChange(GLenum target, GLuint framebuffer)
{
    if (!mIsTimestampQueryAvailable)
        return;

    if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER)
        return;

    // We have at most one active timestamp query at a time. This code will end the current
    // query and immediately start a new one.
    if (mCurrentQuery.beginTimestampQuery != 0)
    {
        glGenQueriesEXT(1, &mCurrentQuery.endTimestampQuery);
        glQueryCounterEXT(mCurrentQuery.endTimestampQuery, GL_TIMESTAMP_EXT);
        mRunningQueries.push_back(mCurrentQuery);
        mCurrentQuery = {};
    }

    ASSERT(mCurrentQuery.beginTimestampQuery == 0);

    glGenQueriesEXT(1, &mCurrentQuery.beginTimestampQuery);
    glQueryCounterEXT(mCurrentQuery.beginTimestampQuery, GL_TIMESTAMP_EXT);
    mCurrentQuery.framebuffer = framebuffer;
}

void TracePerfTest::saveScreenshot(const std::string &screenshotName)
{
    // Render a single frame.
    RestrictedTraceID testID   = GetParam().testID;
    const TraceInfo &traceInfo = GetTraceInfo(testID);
    ReplayFrame(testID, traceInfo.startFrame);

    // RGBA 4-byte data.
    uint32_t pixelCount = mTestParams.windowWidth * mTestParams.windowHeight;
    std::vector<uint8_t> pixelData(pixelCount * 4);

    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glReadPixels(0, 0, mTestParams.windowWidth, mTestParams.windowHeight, GL_RGBA, GL_UNSIGNED_BYTE,
                 pixelData.data());

    // Convert to RGB and flip y.
    std::vector<uint8_t> rgbData(pixelCount * 3);
    for (EGLint y = 0; y < mTestParams.windowHeight; ++y)
    {
        for (EGLint x = 0; x < mTestParams.windowWidth; ++x)
        {
            EGLint srcPixel = x + y * mTestParams.windowWidth;
            EGLint dstPixel = x + (mTestParams.windowHeight - y - 1) * mTestParams.windowWidth;
            memcpy(&rgbData[dstPixel * 3], &pixelData[srcPixel * 4], 3);
        }
    }

    angle::SavePNGRGB(screenshotName.c_str(), "ANGLE Screenshot", mTestParams.windowWidth,
                      mTestParams.windowHeight, rgbData);

    // Finish the frame loop.
    for (uint32_t nextFrame = traceInfo.startFrame + 1; nextFrame < traceInfo.endFrame; ++nextFrame)
    {
        ReplayFrame(testID, nextFrame);
    }
    getGLWindow()->swap();
    glFinish();
}

TEST_P(TracePerfTest, Run)
{
    run();
}

TracePerfParams CombineTestID(const TracePerfParams &in, RestrictedTraceID id)
{
    const TraceInfo &traceInfo = GetTraceInfo(id);

    TracePerfParams out = in;
    out.testID          = id;
    out.windowWidth     = traceInfo.drawSurfaceWidth;
    out.windowHeight    = traceInfo.drawSurfaceHeight;
    return out;
}

using namespace params;
using P = TracePerfParams;

std::vector<P> gTestsWithID =
    CombineWithValues({P()}, AllEnums<RestrictedTraceID>(), CombineTestID);
std::vector<P> gTestsWithRenderer = CombineWithFuncs(gTestsWithID, {Vulkan<P>, Native<P>});
ANGLE_INSTANTIATE_TEST_ARRAY(TracePerfTest, gTestsWithRenderer);

}  // anonymous namespace
<commit_msg>Disable GPU time tracking in trace tests.<commit_after>//
// Copyright 2020 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.
//
// TracePerf:
//   Performance test for ANGLE replaying traces.
//

#include <gtest/gtest.h>
#include "common/PackedEnums.h"
#include "common/system_utils.h"
#include "tests/perf_tests/ANGLEPerfTest.h"
#include "tests/perf_tests/DrawCallPerfParams.h"
#include "util/egl_loader_autogen.h"
#include "util/frame_capture_test_utils.h"
#include "util/png_utils.h"

#include "restricted_traces/restricted_traces_autogen.h"

#include <cassert>
#include <functional>
#include <sstream>

using namespace angle;
using namespace egl_platform;

namespace
{
struct TracePerfParams final : public RenderTestParams
{
    // Common default options
    TracePerfParams()
    {
        majorVersion = 3;
        minorVersion = 0;

        // Tracking GPU time adds overhead to native traces. http://anglebug.com/4879
        trackGpuTime = false;

        // Display the frame after every drawBenchmark invocation
        iterationsPerStep = 1;
    }

    std::string story() const override
    {
        std::stringstream strstr;
        strstr << RenderTestParams::story() << "_" << GetTraceInfo(testID).name;
        return strstr.str();
    }

    RestrictedTraceID testID;
};

std::ostream &operator<<(std::ostream &os, const TracePerfParams &params)
{
    os << params.backendAndStory().substr(1);
    return os;
}

class TracePerfTest : public ANGLERenderTest, public ::testing::WithParamInterface<TracePerfParams>
{
  public:
    TracePerfTest();

    void initializeBenchmark() override;
    void destroyBenchmark() override;
    void drawBenchmark() override;

    void onReplayFramebufferChange(GLenum target, GLuint framebuffer);

    uint32_t mStartFrame;
    uint32_t mEndFrame;

    double getHostTimeFromGLTime(GLint64 glTime);

  private:
    struct QueryInfo
    {
        GLuint beginTimestampQuery;
        GLuint endTimestampQuery;
        GLuint framebuffer;
    };

    struct TimeSample
    {
        GLint64 glTime;
        double hostTime;
    };

    void sampleTime();
    void saveScreenshot(const std::string &screenshotName) override;

    // For tracking RenderPass/FBO change timing.
    QueryInfo mCurrentQuery = {};
    std::vector<QueryInfo> mRunningQueries;
    std::vector<TimeSample> mTimeline;

    std::string mStartingDirectory;
};

TracePerfTest::TracePerfTest()
    : ANGLERenderTest("TracePerf", GetParam()), mStartFrame(0), mEndFrame(0)
{
    const TracePerfParams &param = GetParam();

    // TODO: http://anglebug.com/4533 This fails after the upgrade to the 26.20.100.7870 driver.
    if (IsWindows() && IsIntel() && param.getRenderer() == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE &&
        param.testID == RestrictedTraceID::manhattan_10)
    {
        mSkipTest = true;
    }

    // TODO: http://anglebug.com/4731 Fails on older Intel drivers. Passes in newer.
    if (IsWindows() && IsIntel() && param.driver != GLESDriverType::AngleEGL &&
        param.testID == RestrictedTraceID::angry_birds_2_1500)
    {
        mSkipTest = true;
    }

    // We already swap in TracePerfTest::drawBenchmark, no need to swap again in the harness.
    disableTestHarnessSwap();
}

void TracePerfTest::initializeBenchmark()
{
    const auto &params = GetParam();

    mStartingDirectory = angle::GetCWD().value();

    // To load the trace data path correctly we set the CWD to the executable dir.
    if (!IsAndroid())
    {
        std::string exeDir = angle::GetExecutableDirectory();
        angle::SetCWD(exeDir.c_str());
    }

    const TraceInfo &traceInfo = GetTraceInfo(params.testID);
    mStartFrame                = traceInfo.startFrame;
    mEndFrame                  = traceInfo.endFrame;
    SetBinaryDataDecompressCallback(params.testID, DecompressBinaryData);

    std::stringstream testDataDirStr;
    testDataDirStr << ANGLE_TRACE_DATA_DIR << "/" << traceInfo.name;
    std::string testDataDir = testDataDirStr.str();
    SetBinaryDataDir(params.testID, testDataDir.c_str());

    if (IsAndroid())
    {
        // On Android, set the orientation used by the app, based on width/height
        getWindow()->setOrientation(mTestParams.windowWidth, mTestParams.windowHeight);
    }

    // Potentially slow. Can load a lot of resources.
    SetupReplay(params.testID);
    glFinish();

    ASSERT_TRUE(mEndFrame > mStartFrame);

    getWindow()->setVisible(true);
}

#undef TRACE_TEST_CASE

void TracePerfTest::destroyBenchmark()
{
    // In order for the next test to load, restore the working directory
    angle::SetCWD(mStartingDirectory.c_str());
}

void TracePerfTest::sampleTime()
{
    if (mIsTimestampQueryAvailable)
    {
        GLint64 glTime;
        // glGetInteger64vEXT is exported by newer versions of the timer query extensions.
        // Unfortunately only the core EP is exposed by some desktop drivers (e.g. NVIDIA).
        if (glGetInteger64vEXT)
        {
            glGetInteger64vEXT(GL_TIMESTAMP_EXT, &glTime);
        }
        else
        {
            glGetInteger64v(GL_TIMESTAMP_EXT, &glTime);
        }
        mTimeline.push_back({glTime, angle::GetHostTimeSeconds()});
    }
}

void TracePerfTest::drawBenchmark()
{
    // Add a time sample from GL and the host.
    sampleTime();

    startGpuTimer();

    for (uint32_t frame = mStartFrame; frame <= mEndFrame; ++frame)
    {
        char frameName[32];
        sprintf(frameName, "Frame %u", frame);
        beginInternalTraceEvent(frameName);

        ReplayFrame(GetParam().testID, frame);
        getGLWindow()->swap();

        endInternalTraceEvent(frameName);
    }

    ResetReplay(GetParam().testID);

    // Process any running queries once per iteration.
    for (size_t queryIndex = 0; queryIndex < mRunningQueries.size();)
    {
        const QueryInfo &query = mRunningQueries[queryIndex];

        GLuint endResultAvailable = 0;
        glGetQueryObjectuivEXT(query.endTimestampQuery, GL_QUERY_RESULT_AVAILABLE,
                               &endResultAvailable);

        if (endResultAvailable == GL_TRUE)
        {
            char fboName[32];
            sprintf(fboName, "FBO %u", query.framebuffer);

            GLint64 beginTimestamp = 0;
            glGetQueryObjecti64vEXT(query.beginTimestampQuery, GL_QUERY_RESULT, &beginTimestamp);
            glDeleteQueriesEXT(1, &query.beginTimestampQuery);
            double beginHostTime = getHostTimeFromGLTime(beginTimestamp);
            beginGLTraceEvent(fboName, beginHostTime);

            GLint64 endTimestamp = 0;
            glGetQueryObjecti64vEXT(query.endTimestampQuery, GL_QUERY_RESULT, &endTimestamp);
            glDeleteQueriesEXT(1, &query.endTimestampQuery);
            double endHostTime = getHostTimeFromGLTime(endTimestamp);
            endGLTraceEvent(fboName, endHostTime);

            mRunningQueries.erase(mRunningQueries.begin() + queryIndex);
        }
        else
        {
            queryIndex++;
        }
    }

    stopGpuTimer();
}

// Converts a GL timestamp into a host-side CPU time aligned with "GetHostTimeSeconds".
// This check is necessary to line up sampled trace events in a consistent timeline.
// Uses a linear interpolation from a series of samples. We do a blocking call to sample
// both host and GL time once per swap. We then find the two closest GL timestamps and
// interpolate the host times between them to compute our result. If we are past the last
// GL timestamp we sample a new data point pair.
double TracePerfTest::getHostTimeFromGLTime(GLint64 glTime)
{
    // Find two samples to do a lerp.
    size_t firstSampleIndex = mTimeline.size() - 1;
    while (firstSampleIndex > 0)
    {
        if (mTimeline[firstSampleIndex].glTime < glTime)
        {
            break;
        }
        firstSampleIndex--;
    }

    // Add an extra sample if we're missing an ending sample.
    if (firstSampleIndex == mTimeline.size() - 1)
    {
        sampleTime();
    }

    const TimeSample &start = mTimeline[firstSampleIndex];
    const TimeSample &end   = mTimeline[firstSampleIndex + 1];

    // Note: we have observed in some odd cases later timestamps producing values that are
    // smaller than preceding timestamps. This bears further investigation.

    // Compute the scaling factor for the lerp.
    double glDelta = static_cast<double>(glTime - start.glTime);
    double glRange = static_cast<double>(end.glTime - start.glTime);
    double t       = glDelta / glRange;

    // Lerp(t1, t2, t)
    double hostRange = end.hostTime - start.hostTime;
    return mTimeline[firstSampleIndex].hostTime + hostRange * t;
}

// Triggered when the replay calls glBindFramebuffer.
void TracePerfTest::onReplayFramebufferChange(GLenum target, GLuint framebuffer)
{
    if (!mIsTimestampQueryAvailable)
        return;

    if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER)
        return;

    // We have at most one active timestamp query at a time. This code will end the current
    // query and immediately start a new one.
    if (mCurrentQuery.beginTimestampQuery != 0)
    {
        glGenQueriesEXT(1, &mCurrentQuery.endTimestampQuery);
        glQueryCounterEXT(mCurrentQuery.endTimestampQuery, GL_TIMESTAMP_EXT);
        mRunningQueries.push_back(mCurrentQuery);
        mCurrentQuery = {};
    }

    ASSERT(mCurrentQuery.beginTimestampQuery == 0);

    glGenQueriesEXT(1, &mCurrentQuery.beginTimestampQuery);
    glQueryCounterEXT(mCurrentQuery.beginTimestampQuery, GL_TIMESTAMP_EXT);
    mCurrentQuery.framebuffer = framebuffer;
}

void TracePerfTest::saveScreenshot(const std::string &screenshotName)
{
    // Render a single frame.
    RestrictedTraceID testID   = GetParam().testID;
    const TraceInfo &traceInfo = GetTraceInfo(testID);
    ReplayFrame(testID, traceInfo.startFrame);

    // RGBA 4-byte data.
    uint32_t pixelCount = mTestParams.windowWidth * mTestParams.windowHeight;
    std::vector<uint8_t> pixelData(pixelCount * 4);

    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glReadPixels(0, 0, mTestParams.windowWidth, mTestParams.windowHeight, GL_RGBA, GL_UNSIGNED_BYTE,
                 pixelData.data());

    // Convert to RGB and flip y.
    std::vector<uint8_t> rgbData(pixelCount * 3);
    for (EGLint y = 0; y < mTestParams.windowHeight; ++y)
    {
        for (EGLint x = 0; x < mTestParams.windowWidth; ++x)
        {
            EGLint srcPixel = x + y * mTestParams.windowWidth;
            EGLint dstPixel = x + (mTestParams.windowHeight - y - 1) * mTestParams.windowWidth;
            memcpy(&rgbData[dstPixel * 3], &pixelData[srcPixel * 4], 3);
        }
    }

    angle::SavePNGRGB(screenshotName.c_str(), "ANGLE Screenshot", mTestParams.windowWidth,
                      mTestParams.windowHeight, rgbData);

    // Finish the frame loop.
    for (uint32_t nextFrame = traceInfo.startFrame + 1; nextFrame < traceInfo.endFrame; ++nextFrame)
    {
        ReplayFrame(testID, nextFrame);
    }
    getGLWindow()->swap();
    glFinish();
}

TEST_P(TracePerfTest, Run)
{
    run();
}

TracePerfParams CombineTestID(const TracePerfParams &in, RestrictedTraceID id)
{
    const TraceInfo &traceInfo = GetTraceInfo(id);

    TracePerfParams out = in;
    out.testID          = id;
    out.windowWidth     = traceInfo.drawSurfaceWidth;
    out.windowHeight    = traceInfo.drawSurfaceHeight;
    return out;
}

using namespace params;
using P = TracePerfParams;

std::vector<P> gTestsWithID =
    CombineWithValues({P()}, AllEnums<RestrictedTraceID>(), CombineTestID);
std::vector<P> gTestsWithRenderer = CombineWithFuncs(gTestsWithID, {Vulkan<P>, Native<P>});
ANGLE_INSTANTIATE_TEST_ARRAY(TracePerfTest, gTestsWithRenderer);

}  // anonymous namespace
<|endoftext|>


<commit_before>/*  This file is part of the KDE project.

Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).

This library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2.1 or 3 of the License.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this library.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "streamreader.h"

#include <QtCore/QDebug>
#define d qDebug() << Q_FUNC_INFO << ": "

QT_BEGIN_NAMESPACE
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
namespace Phonon
{
namespace Gstreamer
{

StreamReader::StreamReader(const Phonon::MediaSource &source, MediaObject *parent)
    : m_pos(0)
    , m_size(0)
    , m_eos(false)
    , m_seekable(false)
    , m_mediaObject(parent)
{
    connectToSource(source);
}

int StreamReader::currentBufferSize() const
{
    d << m_buffer.size();
    return m_buffer.size();
}

void StreamReader::writeData(const QByteArray &data) {
    d << "getting ze data and other plunder";
    QMutexLocker locker(&m_mutex);

    m_buffer.append(data);

    m_waitingForData.wakeAll();

#warning enoughData sometimes locks any furhter needata?
//    if (m_mediaObject->state() != Phonon::BufferingState &&
//        m_mediaObject->state() != Phonon::LoadingState) {
//        d << "we haz had enuogh, kthxbai!";
//        enoughData();
//    }
}

void StreamReader::setCurrentPos(qint64 pos)
{
    QMutexLocker locker(&m_mutex);

    m_pos = pos;
    seekStream(pos);
    m_buffer.clear();
}

quint64 StreamReader::currentPos() const
{
    return m_pos;
}

GstFlowReturn StreamReader::read(quint64 pos, int length, char *buffer)
{
    QMutexLocker locker(&m_mutex);

    if (currentPos() != pos) {
        if (!streamSeekable()) {
            return GST_FLOW_NOT_SUPPORTED;
        }
#warning ret something
        setCurrentPos(pos);
    }

    while (currentBufferSize() < length) {
        d << "whiling";
        int oldSize = currentBufferSize();
        needData();

        m_waitingForData.wait(&m_mutex);

        if (oldSize == currentBufferSize()) {
            // We didn't get any data.
            if (m_eos) {
                return GST_FLOW_UNEXPECTED;
            } else {
                return GST_FLOW_ERROR;
            }
        }
    }
//    enoughData();

    d << "filling up that stinky old buffer";
    qMemCopy(buffer, m_buffer.data(), length);
    m_pos += length;
    //truncate the buffer
    m_buffer = m_buffer.mid(length);
    return GST_FLOW_OK;
}

void StreamReader::endOfData()
{
    d << "out of the data!!!";
    QMutexLocker locker(&m_mutex);
    m_eos = true;
    m_waitingForData.wakeAll();
}

void StreamReader::start()
{
    d;
    QMutexLocker locker(&m_mutex);
    m_buffer.clear();
    m_eos = false;
    m_pos = 0;
    m_seekable = false;
    m_size = 0;
    reset();
}

void StreamReader::stop()
{
#ifdef __GNUC__
#warning implications of stop on still working read????
#endif
    d << "stopping!";
    enoughData();
//    m_waitingForData.wakeAll();
}

void StreamReader::unlock()
{
    QMutexLocker locker(&m_mutex);
    d << "lock lock I shall unlock...";
//    enoughData();
//    m_waitingForData.wakeAll();
}

void StreamReader::unlockStop()
{
    QMutexLocker locker(&m_mutex);
}

void StreamReader::setStreamSize(qint64 newSize) {
    d << "setting der streamsize to - " << newSize;
    m_size = newSize;
}

qint64 StreamReader::streamSize() const {
    return m_size;
}

void StreamReader::setStreamSeekable(bool seekable) {
    d << seekable;
    m_seekable = seekable;
}

bool StreamReader::streamSeekable() const {
    d << m_seekable;
    return false;
    return m_seekable;
}

}
}
#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM

QT_END_NAMESPACE
<commit_msg>stop and unlock appropriately, lockup after enoughData remains though :S<commit_after>/*  This file is part of the KDE project.

Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).

This library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2.1 or 3 of the License.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this library.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "streamreader.h"

#include <QtCore/QDebug>
#define d qDebug() << Q_FUNC_INFO << ": "

QT_BEGIN_NAMESPACE
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
namespace Phonon
{
namespace Gstreamer
{

StreamReader::StreamReader(const Phonon::MediaSource &source, MediaObject *parent)
    : m_pos(0)
    , m_size(0)
    , m_eos(false)
    , m_seekable(false)
    , m_mediaObject(parent)
{
    connectToSource(source);
}

int StreamReader::currentBufferSize() const
{
    d << m_buffer.size();
    return m_buffer.size();
}

void StreamReader::writeData(const QByteArray &data) {
    d << "getting ze data and other plunder";
    QMutexLocker locker(&m_mutex);

    m_buffer.append(data);

    m_waitingForData.wakeAll();

#warning enoughData sometimes locks any furhter needata?
//    if (m_mediaObject->state() != Phonon::BufferingState &&
//        m_mediaObject->state() != Phonon::LoadingState) {
//        d << "we haz had enuogh, kthxbai!";
//        enoughData();
//    }
}

void StreamReader::setCurrentPos(qint64 pos)
{
    QMutexLocker locker(&m_mutex);

    m_pos = pos;
    seekStream(pos);
    m_buffer.clear();
}

quint64 StreamReader::currentPos() const
{
    return m_pos;
}

GstFlowReturn StreamReader::read(quint64 pos, int length, char *buffer)
{
    QMutexLocker locker(&m_mutex);

    if (currentPos() != pos) {
        if (!streamSeekable()) {
            return GST_FLOW_NOT_SUPPORTED;
        }
#warning ret something
        setCurrentPos(pos);
    }

    while (currentBufferSize() < length) {
        d << "whiling";
        int oldSize = currentBufferSize();
        needData();

        m_waitingForData.wait(&m_mutex);

        if (oldSize == currentBufferSize()) {
            // We didn't get any data.
            if (m_eos) {
                return GST_FLOW_UNEXPECTED;
            } else {
                return GST_FLOW_ERROR;
            }
        }
    }
//    enoughData();

    d << "filling up that stinky old buffer";
    qMemCopy(buffer, m_buffer.data(), length);
    m_pos += length;
    //truncate the buffer
    m_buffer = m_buffer.mid(length);
    return GST_FLOW_OK;
}

void StreamReader::endOfData()
{
    d << "out of the data!!!";
    QMutexLocker locker(&m_mutex);
    m_eos = true;
    m_waitingForData.wakeAll();
}

void StreamReader::start()
{
    d;
    QMutexLocker locker(&m_mutex);
    m_buffer.clear();
    m_eos = false;
    m_pos = 0;
    m_seekable = false;
    m_size = 0;
    reset();
}

void StreamReader::stop()
{
#ifdef __GNUC__
#warning implications of stop on still working read????
#endif
    d << "stopping!";
    enoughData();
    m_waitingForData.wakeAll();
}

void StreamReader::unlock()
{
    QMutexLocker locker(&m_mutex);
    d << "lock lock I shall unlock...";
    enoughData();
    m_waitingForData.wakeAll();
}

void StreamReader::unlockStop()
{
    QMutexLocker locker(&m_mutex);
}

void StreamReader::setStreamSize(qint64 newSize) {
    d << "setting der streamsize to - " << newSize;
    m_size = newSize;
}

qint64 StreamReader::streamSize() const {
    return m_size;
}

void StreamReader::setStreamSeekable(bool seekable) {
    d << seekable;
    m_seekable = seekable;
}

bool StreamReader::streamSeekable() const {
    d << m_seekable;
    return false;
    return m_seekable;
}

}
}
#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM

QT_END_NAMESPACE
<|endoftext|>


<commit_before>/*
Highly Optimized Object-oriented Many-particle Dynamics -- Blue Edition
(HOOMD-blue) Open Source Software License Copyright 2008, 2009 Ames Laboratory
Iowa State University and The Regents of the University of Michigan All rights
reserved.

HOOMD-blue may contain modifications ("Contributions") provided, and to which
copyright is held, by various Contributors who have granted The Regents of the
University of Michigan the right to modify and/or distribute such Contributions.

Redistribution and use of HOOMD-blue, 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 holder nor the names of HOOMD-blue's
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.

Disclaimer

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND/OR
ANY WARRANTIES THAT THIS SOFTWARE IS FREE OF INFRINGEMENT ARE DISCLAIMED.

IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
*/

// $Id: TwoStepNVEGPU.cc 2331 2009-11-19 15:30:00Z ndtrung $
// $URL: https://codeblue.umich.edu/hoomd-blue/svn/branches/rigid-bodies/src/updaters_gpu/TwoStepNVERigidGPU.cc $
// Maintainer: joaander

#ifdef WIN32
#pragma warning( push )
#pragma warning( disable : 4244 )
#endif

#include <boost/python.hpp>
using namespace boost::python;
#include <boost/bind.hpp>
using namespace boost;

#include "TwoStepNVERigidGPU.h"
#include "TwoStepNVERigidGPU.cuh"

/*! \file TwoStepNVERigidGPU.h
    \brief Contains code for the TwoStepNVERigidGPU class
*/

/*! \param sysdef SystemDefinition this method will act on. Must not be NULL.
    \param group The group of particles this integration method is to work on
*/
TwoStepNVERigidGPU::TwoStepNVERigidGPU(boost::shared_ptr<SystemDefinition> sysdef,
                             boost::shared_ptr<ParticleGroup> group)
    : TwoStepNVERigid(sysdef, group)
    {
    // only one GPU is supported
    if (exec_conf.gpu.size() != 1)
        {
        cerr << endl << "***Error! Creating a TwoStepNVEGPU with 0 or more than one GPUs" << endl << endl;
        throw std::runtime_error("Error initializing TwoStepNVEGPU");
        }
    }

/*! \param timestep Current time step
    \post Particle positions are moved forward to timestep+1 and velocities to timestep+1/2 per the velocity verlet
          method.
*/
void TwoStepNVERigidGPU::integrateStepOne(unsigned int timestep)
    {
    // profile this step
    if (m_prof)
        m_prof->push(exec_conf, "NVE step 1");

    if (m_first_step)
        {
        setup();
        m_first_step = false;
        }

    // access all the needed data
    vector<gpu_pdata_arrays>& d_pdata = m_pdata->acquireReadWriteGPU();
    gpu_boxsize box = m_pdata->getBoxGPU();
    ArrayHandle< unsigned int > d_index_array(m_group->getIndexArray(), access_location::device, access_mode::read);
    unsigned int group_size = m_group->getIndexArray().getNumElements();

    // get the rigid data from SystemDefinition
    boost::shared_ptr<RigidData> rigid_data = m_sysdef->getRigidData();

	ArrayHandle<Scalar> body_mass_handle(rigid_data->getBodyMass(), access_location::device, access_mode::read);
	ArrayHandle<Scalar4> moment_inertia_handle(rigid_data->getMomentInertia(), access_location::device, access_mode::read);
	ArrayHandle<Scalar4> com_handle(rigid_data->getCOM(), access_location::device, access_mode::readwrite);
    ArrayHandle<Scalar4> vel_handle(rigid_data->getVel(), access_location::device, access_mode::readwrite);
    ArrayHandle<Scalar4> angvel_handle(rigid_data->getAngVel(), access_location::device, access_mode::readwrite);
    ArrayHandle<Scalar4> angmom_handle(rigid_data->getAngMom(), access_location::device, access_mode::readwrite);
    ArrayHandle<Scalar4> orientation_handle(rigid_data->getOrientation(), access_location::device, access_mode::readwrite);
    ArrayHandle<Scalar4> ex_space_handle(rigid_data->getExSpace(), access_location::device, access_mode::readwrite);
    ArrayHandle<Scalar4> ey_space_handle(rigid_data->getEySpace(), access_location::device, access_mode::readwrite);
    ArrayHandle<Scalar4> ez_space_handle(rigid_data->getEzSpace(), access_location::device, access_mode::readwrite);
    ArrayHandle<int> body_imagex_handle(rigid_data->getBodyImagex(), access_location::device, access_mode::readwrite);
    ArrayHandle<int> body_imagey_handle(rigid_data->getBodyImagey(), access_location::device, access_mode::readwrite);
    ArrayHandle<int> body_imagez_handle(rigid_data->getBodyImagez(), access_location::device, access_mode::readwrite);
    ArrayHandle<Scalar4> particle_pos_handle(rigid_data->getParticlePos(), access_location::device, access_mode::read);
    ArrayHandle<unsigned int> particle_indices_handle(rigid_data->getParticleIndices(), access_location::device, access_mode::read);
    ArrayHandle<Scalar4> force_handle(rigid_data->getForce(), access_location::device, access_mode::read);
    ArrayHandle<Scalar4> torque_handle(rigid_data->getTorque(), access_location::device, access_mode::read);

    gpu_rigid_data_arrays d_rdata;
    d_rdata.n_bodies = rigid_data->getNumBodies();
    d_rdata.nmax = rigid_data->getNmax();
    d_rdata.local_beg = 0;
    d_rdata.local_num = d_rdata.n_bodies;
    d_rdata.body_mass = body_mass_handle.data;
    d_rdata.moment_inertia = moment_inertia_handle.data;
    d_rdata.com = com_handle.data;
    d_rdata.vel = vel_handle.data;
    d_rdata.angvel = angvel_handle.data;
    d_rdata.angmom = angmom_handle.data;
    d_rdata.orientation = orientation_handle.data;
    d_rdata.ex_space = ex_space_handle.data;
    d_rdata.ey_space = ey_space_handle.data;
    d_rdata.ez_space = ez_space_handle.data;
    d_rdata.body_imagex = body_imagex_handle.data;
    d_rdata.body_imagey = body_imagey_handle.data;
    d_rdata.body_imagez = body_imagez_handle.data;
    d_rdata.particle_pos = particle_pos_handle.data;
    d_rdata.particle_indices = particle_indices_handle.data;
    d_rdata.force = force_handle.data;
    d_rdata.torque = torque_handle.data;

    // perform the update on the GPU
    exec_conf.tagAll(__FILE__, __LINE__);
    exec_conf.gpu[0]->call(bind(gpu_nve_rigid_step_one,
                                d_pdata[0],
                                d_rdata,
								d_index_array.data,
								group_size,
								box,
								m_deltaT));

    m_pdata->release();

    // done profiling
    if (m_prof)
        m_prof->pop(exec_conf);
    }

/*! \param timestep Current time step
    \post particle velocities are moved forward to timestep+1 on the GPU
*/
void TwoStepNVERigidGPU::integrateStepTwo(unsigned int timestep)
    {
    const GPUArray< Scalar4 >& net_force = m_pdata->getNetForce();

    // profile this step
    if (m_prof)
        m_prof->push(exec_conf, "NVE step 2");

    vector<gpu_pdata_arrays>& d_pdata = m_pdata->acquireReadWriteGPU();
    gpu_boxsize box = m_pdata->getBoxGPU();
    ArrayHandle<Scalar4> d_net_force(net_force, access_location::device, access_mode::read);
    ArrayHandle< unsigned int > d_index_array(m_group->getIndexArray(), access_location::device, access_mode::read);
    unsigned int group_size = m_group->getIndexArray().getNumElements();

    // get the rigid data from SystemDefinition
    boost::shared_ptr<RigidData> rigid_data = m_sysdef->getRigidData();

    ArrayHandle<Scalar> body_mass_handle(rigid_data->getBodyMass(), access_location::device, access_mode::read);
    ArrayHandle<Scalar4> moment_inertia_handle(rigid_data->getMomentInertia(), access_location::device, access_mode::read);
    ArrayHandle<Scalar4> com_handle(rigid_data->getCOM(), access_location::device, access_mode::read);
    ArrayHandle<Scalar4> vel_handle(rigid_data->getVel(), access_location::device, access_mode::readwrite);
    ArrayHandle<Scalar4> angvel_handle(rigid_data->getAngVel(), access_location::device, access_mode::readwrite);
    ArrayHandle<Scalar4> angmom_handle(rigid_data->getAngMom(), access_location::device, access_mode::readwrite);
    ArrayHandle<Scalar4> ex_space_handle(rigid_data->getExSpace(), access_location::device, access_mode::read);
    ArrayHandle<Scalar4> ey_space_handle(rigid_data->getEySpace(), access_location::device, access_mode::read);
    ArrayHandle<Scalar4> ez_space_handle(rigid_data->getEzSpace(), access_location::device, access_mode::read);
    ArrayHandle<Scalar4> particle_pos_handle(rigid_data->getParticlePos(), access_location::device, access_mode::read);
    ArrayHandle<unsigned int> particle_indices_handle(rigid_data->getParticleIndices(), access_location::device, access_mode::read);
    ArrayHandle<Scalar4> force_handle(rigid_data->getForce(), access_location::device, access_mode::readwrite);
    ArrayHandle<Scalar4> torque_handle(rigid_data->getTorque(), access_location::device, access_mode::readwrite);

    gpu_rigid_data_arrays d_rdata;
    d_rdata.n_bodies = rigid_data->getNumBodies();
    d_rdata.nmax = rigid_data->getNmax();
    d_rdata.local_beg = 0;
    d_rdata.local_num = d_rdata.n_bodies;
    d_rdata.body_mass = body_mass_handle.data;
    d_rdata.moment_inertia = moment_inertia_handle.data;
	d_rdata.com = com_handle.data;
    d_rdata.vel = vel_handle.data;
    d_rdata.angvel = angvel_handle.data;
    d_rdata.angmom = angmom_handle.data;
    d_rdata.ex_space = ex_space_handle.data;
    d_rdata.ey_space = ey_space_handle.data;
    d_rdata.ez_space = ez_space_handle.data;
    d_rdata.particle_pos = particle_pos_handle.data;
    d_rdata.particle_indices = particle_indices_handle.data;
    d_rdata.force = force_handle.data;
    d_rdata.torque = torque_handle.data;

	// perform the update on the GPU
    exec_conf.tagAll(__FILE__, __LINE__);
    exec_conf.gpu[0]->call(bind(gpu_nve_rigid_step_two,
								d_pdata[0],
                                d_rdata,
								d_index_array.data,
								group_size,
                                d_net_force.data,
                                box,
								m_deltaT,
                                m_zero_force));

    m_pdata->release();

    // done profiling
    if (m_prof)
        m_prof->pop(exec_conf);
    }

void export_TwoStepNVERigidGPU()
    {
    class_<TwoStepNVERigidGPU, boost::shared_ptr<TwoStepNVERigidGPU>, bases<TwoStepNVERigid>, boost::noncopyable>
        ("TwoStepNVERigidGPU", init< boost::shared_ptr<SystemDefinition>, boost::shared_ptr<ParticleGroup> >())
        ;
    }

#ifdef WIN32
#pragma warning( pop )
#endif

<commit_msg>update two-step NVE rigid body integrator on GPU<commit_after>/*
Highly Optimized Object-oriented Many-particle Dynamics -- Blue Edition
(HOOMD-blue) Open Source Software License Copyright 2008, 2009 Ames Laboratory
Iowa State University and The Regents of the University of Michigan All rights
reserved.

HOOMD-blue may contain modifications ("Contributions") provided, and to which
copyright is held, by various Contributors who have granted The Regents of the
University of Michigan the right to modify and/or distribute such Contributions.

Redistribution and use of HOOMD-blue, 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 holder nor the names of HOOMD-blue's
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.

Disclaimer

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND/OR
ANY WARRANTIES THAT THIS SOFTWARE IS FREE OF INFRINGEMENT ARE DISCLAIMED.

IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
*/

// $Id: TwoStepNVEGPU.cc 2331 2009-11-19 15:30:00Z ndtrung $
// $URL: https://codeblue.umich.edu/hoomd-blue/svn/branches/rigid-bodies/src/updaters_gpu/TwoStepNVERigidGPU.cc $
// Maintainer: joaander

#ifdef WIN32
#pragma warning( push )
#pragma warning( disable : 4244 )
#endif

#include <boost/python.hpp>
using namespace boost::python;
#include <boost/bind.hpp>
using namespace boost;

#include "TwoStepNVERigidGPU.h"
#include "TwoStepNVERigidGPU.cuh"

/*! \file TwoStepNVERigidGPU.h
    \brief Contains code for the TwoStepNVERigidGPU class
*/

/*! \param sysdef SystemDefinition this method will act on. Must not be NULL.
    \param group The group of particles this integration method is to work on
*/
TwoStepNVERigidGPU::TwoStepNVERigidGPU(boost::shared_ptr<SystemDefinition> sysdef,
                             boost::shared_ptr<ParticleGroup> group)
    : TwoStepNVERigid(sysdef, group)
    {
    // only one GPU is supported
    if (exec_conf.gpu.size() != 1)
        {
        cerr << endl << "***Error! Creating a TwoStepNVEGPU with 0 or more than one GPUs" << endl << endl;
        throw std::runtime_error("Error initializing TwoStepNVEGPU");
        }
    }

/*! \param timestep Current time step
    \post Particle positions are moved forward to timestep+1 and velocities to timestep+1/2 per the velocity verlet
          method.
*/
void TwoStepNVERigidGPU::integrateStepOne(unsigned int timestep)
    {
    if (m_first_step)
        {
        setup();
        m_first_step = false;
        }

    // profile this step
    if (m_prof)
        m_prof->push(exec_conf, "NVE rigid step 1");

    // access all the needed data
    vector<gpu_pdata_arrays>& d_pdata = m_pdata->acquireReadWriteGPU();
    gpu_boxsize box = m_pdata->getBoxGPU();
    ArrayHandle< unsigned int > d_index_array(m_group->getIndexArray(), access_location::device, access_mode::read);
    unsigned int group_size = m_group->getIndexArray().getNumElements();

    // get the rigid data from SystemDefinition
    boost::shared_ptr<RigidData> rigid_data = m_sysdef->getRigidData();

	ArrayHandle<Scalar> body_mass_handle(rigid_data->getBodyMass(), access_location::device, access_mode::read);
	ArrayHandle<Scalar4> moment_inertia_handle(rigid_data->getMomentInertia(), access_location::device, access_mode::read);
	ArrayHandle<Scalar4> com_handle(rigid_data->getCOM(), access_location::device, access_mode::readwrite);
    ArrayHandle<Scalar4> vel_handle(rigid_data->getVel(), access_location::device, access_mode::readwrite);
    ArrayHandle<Scalar4> angvel_handle(rigid_data->getAngVel(), access_location::device, access_mode::readwrite);
    ArrayHandle<Scalar4> angmom_handle(rigid_data->getAngMom(), access_location::device, access_mode::readwrite);
    ArrayHandle<Scalar4> orientation_handle(rigid_data->getOrientation(), access_location::device, access_mode::readwrite);
    ArrayHandle<Scalar4> ex_space_handle(rigid_data->getExSpace(), access_location::device, access_mode::readwrite);
    ArrayHandle<Scalar4> ey_space_handle(rigid_data->getEySpace(), access_location::device, access_mode::readwrite);
    ArrayHandle<Scalar4> ez_space_handle(rigid_data->getEzSpace(), access_location::device, access_mode::readwrite);
    ArrayHandle<int> body_imagex_handle(rigid_data->getBodyImagex(), access_location::device, access_mode::readwrite);
    ArrayHandle<int> body_imagey_handle(rigid_data->getBodyImagey(), access_location::device, access_mode::readwrite);
    ArrayHandle<int> body_imagez_handle(rigid_data->getBodyImagez(), access_location::device, access_mode::readwrite);
    ArrayHandle<Scalar4> particle_pos_handle(rigid_data->getParticlePos(), access_location::device, access_mode::read);
    ArrayHandle<unsigned int> particle_indices_handle(rigid_data->getParticleIndices(), access_location::device, access_mode::read);
    ArrayHandle<Scalar4> force_handle(rigid_data->getForce(), access_location::device, access_mode::read);
    ArrayHandle<Scalar4> torque_handle(rigid_data->getTorque(), access_location::device, access_mode::read);

    gpu_rigid_data_arrays d_rdata;
    d_rdata.n_bodies = rigid_data->getNumBodies();
    d_rdata.nmax = rigid_data->getNmax();
    d_rdata.local_beg = 0;
    d_rdata.local_num = d_rdata.n_bodies;
    d_rdata.body_mass = body_mass_handle.data;
    d_rdata.moment_inertia = moment_inertia_handle.data;
    d_rdata.com = com_handle.data;
    d_rdata.vel = vel_handle.data;
    d_rdata.angvel = angvel_handle.data;
    d_rdata.angmom = angmom_handle.data;
    d_rdata.orientation = orientation_handle.data;
    d_rdata.ex_space = ex_space_handle.data;
    d_rdata.ey_space = ey_space_handle.data;
    d_rdata.ez_space = ez_space_handle.data;
    d_rdata.body_imagex = body_imagex_handle.data;
    d_rdata.body_imagey = body_imagey_handle.data;
    d_rdata.body_imagez = body_imagez_handle.data;
    d_rdata.particle_pos = particle_pos_handle.data;
    d_rdata.particle_indices = particle_indices_handle.data;
    d_rdata.force = force_handle.data;
    d_rdata.torque = torque_handle.data;

    // perform the update on the GPU
    exec_conf.tagAll(__FILE__, __LINE__);
    exec_conf.gpu[0]->call(bind(gpu_nve_rigid_step_one,
                                d_pdata[0],
                                d_rdata,
								d_index_array.data,
								group_size,
								box,
								m_deltaT));

    m_pdata->release();

    // done profiling
    if (m_prof)
        m_prof->pop(exec_conf);
    }

/*! \param timestep Current time step
    \post particle velocities are moved forward to timestep+1 on the GPU
*/
void TwoStepNVERigidGPU::integrateStepTwo(unsigned int timestep)
    {
    const GPUArray< Scalar4 >& net_force = m_pdata->getNetForce();

    // profile this step
    if (m_prof)
        m_prof->push(exec_conf, "NVE rigid step 2");

    vector<gpu_pdata_arrays>& d_pdata = m_pdata->acquireReadWriteGPU();
    gpu_boxsize box = m_pdata->getBoxGPU();
    ArrayHandle<Scalar4> d_net_force(net_force, access_location::device, access_mode::read);
    ArrayHandle< unsigned int > d_index_array(m_group->getIndexArray(), access_location::device, access_mode::read);
    unsigned int group_size = m_group->getIndexArray().getNumElements();

    // get the rigid data from SystemDefinition
    boost::shared_ptr<RigidData> rigid_data = m_sysdef->getRigidData();

    ArrayHandle<Scalar> body_mass_handle(rigid_data->getBodyMass(), access_location::device, access_mode::read);
    ArrayHandle<Scalar4> moment_inertia_handle(rigid_data->getMomentInertia(), access_location::device, access_mode::read);
    ArrayHandle<Scalar4> com_handle(rigid_data->getCOM(), access_location::device, access_mode::read);
    ArrayHandle<Scalar4> vel_handle(rigid_data->getVel(), access_location::device, access_mode::readwrite);
    ArrayHandle<Scalar4> angvel_handle(rigid_data->getAngVel(), access_location::device, access_mode::readwrite);
    ArrayHandle<Scalar4> angmom_handle(rigid_data->getAngMom(), access_location::device, access_mode::readwrite);
    ArrayHandle<Scalar4> ex_space_handle(rigid_data->getExSpace(), access_location::device, access_mode::read);
    ArrayHandle<Scalar4> ey_space_handle(rigid_data->getEySpace(), access_location::device, access_mode::read);
    ArrayHandle<Scalar4> ez_space_handle(rigid_data->getEzSpace(), access_location::device, access_mode::read);
    ArrayHandle<Scalar4> particle_pos_handle(rigid_data->getParticlePos(), access_location::device, access_mode::read);
    ArrayHandle<unsigned int> particle_indices_handle(rigid_data->getParticleIndices(), access_location::device, access_mode::read);
    ArrayHandle<Scalar4> force_handle(rigid_data->getForce(), access_location::device, access_mode::readwrite);
    ArrayHandle<Scalar4> torque_handle(rigid_data->getTorque(), access_location::device, access_mode::readwrite);

    gpu_rigid_data_arrays d_rdata;
    d_rdata.n_bodies = rigid_data->getNumBodies();
    d_rdata.nmax = rigid_data->getNmax();
    d_rdata.local_beg = 0;
    d_rdata.local_num = d_rdata.n_bodies;
    d_rdata.body_mass = body_mass_handle.data;
    d_rdata.moment_inertia = moment_inertia_handle.data;
	d_rdata.com = com_handle.data;
    d_rdata.vel = vel_handle.data;
    d_rdata.angvel = angvel_handle.data;
    d_rdata.angmom = angmom_handle.data;
    d_rdata.ex_space = ex_space_handle.data;
    d_rdata.ey_space = ey_space_handle.data;
    d_rdata.ez_space = ez_space_handle.data;
    d_rdata.particle_pos = particle_pos_handle.data;
    d_rdata.particle_indices = particle_indices_handle.data;
    d_rdata.force = force_handle.data;
    d_rdata.torque = torque_handle.data;

	// perform the update on the GPU
    exec_conf.tagAll(__FILE__, __LINE__);
    exec_conf.gpu[0]->call(bind(gpu_nve_rigid_step_two,
								d_pdata[0],
                                d_rdata,
								d_index_array.data,
								group_size,
                                d_net_force.data,
                                box,
								m_deltaT,
                                m_zero_force));

    m_pdata->release();

    // done profiling
    if (m_prof)
        m_prof->pop(exec_conf);
    }

void export_TwoStepNVERigidGPU()
    {
    class_<TwoStepNVERigidGPU, boost::shared_ptr<TwoStepNVERigidGPU>, bases<TwoStepNVERigid>, boost::noncopyable>
        ("TwoStepNVERigidGPU", init< boost::shared_ptr<SystemDefinition>, boost::shared_ptr<ParticleGroup> >())
        ;
    }

#ifdef WIN32
#pragma warning( pop )
#endif

<|endoftext|>


<commit_before>/*
 * This file is a part of Xpiks - cross platform application for
 * keywording and uploading images for microstocks
 * Copyright (C) 2014-2018 Taras Kushnir <kushnirTV@gmail.com>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "updatehelpers.h"
#include <QProcess>
#include <QStringList>
#include <QDir>
#include <QCoreApplication>
#include <QFileInfo>
#include "../Common/defines.h"

#ifdef Q_OS_OSX

void launchOSXdmg(const QString &dmgPath) {
    QStringList arguments;
    arguments << dmgPath;

    QProcess::startDetached("open", arguments);
}

#endif

#ifdef Q_OS_WIN

QString getLogFilenameForMinistaller() {
    QString time = QDateTime::currentDateTimeUtc().toString("ddMMyyyy-hhmmss-zzz");
    QString logFilename = QString("ministaller-%1.log").arg(time);
    return logFilename;
}

void launchWindowsInstaller(Common::ISystemEnvironment &environment, const QString &pathToUpdate) {
    LOG_DEBUG << "#";
    QString ministallerPath = environment.filepath("ministaller.exe");

    if (!QFileInfo(ministallerPath).exists()) {
        LOG_WARNING << "Updater not found!" << ministallerPath;
        return;
    }

    QString installerLogName = getLogFilenameForMinistaller();
    QString installerLogPath = environment.fileInDir(installerLogName, "logs");
    QStringList arguments;
    arguments << "-force-update" << "-gui" <<
                 "-install-path" << environment.root() <<
                 "-l" << installerLogPath <<
                 "-launch-exe" << "Xpiks.exe" <<
                 "-package-path" << pathToUpdate <<
                 "-stdout";

    QProcess::startDetached(ministallerPath, arguments);
}

#endif

namespace Helpers {
    void installUpdate(Common::ISystemEnvironment &environment, const QString &updatePath) {
#if defined(Q_OS_OSX)
        launchOSXdmg(updatePath);
#elif defined(Q_OS_WIN)
        launchWindowsInstaller(environment, updatePath);
#endif
    }
}
<commit_msg>Fixes for env improvement in Windows<commit_after>/*
 * This file is a part of Xpiks - cross platform application for
 * keywording and uploading images for microstocks
 * Copyright (C) 2014-2018 Taras Kushnir <kushnirTV@gmail.com>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "updatehelpers.h"
#include <QProcess>
#include <QStringList>
#include <QDir>
#include <QCoreApplication>
#include <QFileInfo>
#include "../Common/defines.h"

#ifdef Q_OS_OSX

void launchOSXdmg(const QString &dmgPath) {
    QStringList arguments;
    arguments << dmgPath;

    QProcess::startDetached("open", arguments);
}

#endif

#ifdef Q_OS_WIN

QString getLogFilenameForMinistaller() {
    QString time = QDateTime::currentDateTimeUtc().toString("ddMMyyyy-hhmmss-zzz");
    QString logFilename = QString("ministaller-%1.log").arg(time);
    return logFilename;
}

void launchWindowsInstaller(Common::ISystemEnvironment &environment, const QString &pathToUpdate) {
    LOG_DEBUG << "#";
    QString ministallerPath = environment.path({"ministaller.exe"});

    if (!QFileInfo(ministallerPath).exists()) {
        LOG_WARNING << "Updater not found!" << ministallerPath;
        return;
    }

    QString installerLogName = getLogFilenameForMinistaller();
    QString installerLogPath = environment.path({"logs", installerLogName});
    QStringList arguments;
    arguments << "-force-update" << "-gui" <<
                 "-install-path" << environment.root() <<
                 "-l" << installerLogPath <<
                 "-launch-exe" << "Xpiks.exe" <<
                 "-package-path" << pathToUpdate <<
                 "-stdout";

    QProcess::startDetached(ministallerPath, arguments);
}

#endif

namespace Helpers {
    void installUpdate(Common::ISystemEnvironment &environment, const QString &updatePath) {
#if defined(Q_OS_OSX)
        launchOSXdmg(updatePath);
#elif defined(Q_OS_WIN)
        launchWindowsInstaller(environment, updatePath);
#endif
    }
}
<|endoftext|>


<commit_before>/*
  Qore Programming Language Qt4 Module

  Copyright 2009 Qore Technologies sro

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

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

#include <QByteArray>

#include "qoresmokeglobal.h"
#include "qoreqtdynamicmethod.h"
#include "commonqoremethod.h"

int QoreQtDynamicMethod::identifyTypes(SmokeTypeList &typeList, const char *sig, const char *p, ExceptionSink *xsink) {
    //printd(0, "QoreQtDynamicMethod::identifyTypes sig=%s p=%s\n", sig, p);
    while (*p && isblank(*p))
        ++p;
    if (*p != ')')
        while (*p) {
            const char *e = p + 1;
            char paren = 0;
            while (paren || (*e != ')' && *e != ',')) {
                assert(*e);
                switch (*e) {
                case '<':
                case '(':
                case '[':
                    if (!paren)
                        paren = *e;
                    break;
                case '>':
                case ')':
                case ']':
                    if (*e == paren)
                        paren = 0;
                    break;
                }
                ++e;
            }
            addType(typeList, p, e - p, sig, xsink);
            if (*e == ')')
                break;
            p = e + 1;
        }
    return *xsink ? -1 : 0;
}

int QoreQtDynamicMethod::addType(SmokeTypeList &typeList, const char *b, int len, const char *sig, ExceptionSink *xsink) {
    QByteArray tmp(b, len);
    QString tn(tmp);
    tn = tn.simplified();
    if (tn.endsWith(" &"))
        tn.replace(" &", "&");
    if (tn.endsWith(" *"))
        tn.replace(" *", "*");
    //printd(0, "QoreQtDynamicMethod::addType() processing type '%s'\n", tn.constData());

    Smoke::Type t;
    t.classId = -1;

    if (tn == "int") {
        t.name = "int";
        t.flags = Smoke::t_int | Smoke::tf_stack;
    } else if (tn == "bool") {
        t.name = "bool";
        t.flags = Smoke::t_bool | Smoke::tf_stack;
    } else if (tn == "uint") {
        t.name = "uint";
        t.flags = Smoke::t_uint | Smoke::tf_stack;
    } else if (tn == "long") {
        t.name = "long";
        t.flags = Smoke::t_long | Smoke::tf_stack;
    } else if (tn == "ulong") {
        t.name = "ulong";
        t.flags = Smoke::t_ulong | Smoke::tf_stack;
    } else if (tn == "double") {
        t.name = "double";
        t.flags = Smoke::t_double | Smoke::tf_stack;
    } else if (tn == "char*" ) {
        t.name = "char*";
        t.flags = Smoke::t_voidp | Smoke::tf_ptr;
    } else if (tn == "qreal") {
        t.name = "qreal";
        t.flags = Smoke::t_double | Smoke::tf_stack;
    } else if (tn.contains("QString")) {
        t.name = "QString&";
        t.flags = Smoke::t_voidp | Smoke::tf_ref;
    }
    // everything else should be pointer to object
    else {
        // TODO/FIXME: there should be a better way! But it looks like it is
        // not implemented in Smoke
        bool found = false;
        Smoke::Type st;
        for (int i = 0; i < qt_Smoke->numTypes; ++i) {
            st = qt_Smoke->types[i];
            if (tn == st.name) {
                //printd(0, "QoreQtDynamicMethod::addType() found object/ref to %s\n", st.name);
                t.name = st.name;
                t.flags = st.flags;
                t.classId = st.classId;
                found = true;
                break;
            }
        }
        if (!found) {
            xsink->raiseException("DYNAMIC-METHOD-ERROR", "cannot handle argument type '%s' in '%s'", tn.constData(), sig);
            return -1;
        }
    }

    typeList.push_back(t);
    return 0;
}

void QoreQtDynamicMethod::qtToQore(const Smoke::Type &t, void *arg, QoreListNode *args) {
    assert(t.name);
    Smoke::StackItem si;

    int typ = t.flags & Smoke::tf_ref;
    assert(typ);

    if (typ == Smoke::tf_ref && !strcmp(t.name, "QString&"))
        si.s_voidp = arg;
    else
        switch (t.flags & Smoke::tf_elem) {
        case Smoke::t_voidp:
            si.s_voidp = arg;
            break;
        case Smoke::t_bool:
            si.s_bool = * reinterpret_cast<bool*>(arg);
            break;
        case Smoke::t_int:
            si.s_int = * reinterpret_cast<int*>(arg);
            break;
        case Smoke::t_uint:
            si.s_uint = * reinterpret_cast<uint*>(arg);
            break;
        case Smoke::t_long:
            si.s_long = * reinterpret_cast<long*>(arg);
            break;
        case Smoke::t_ulong:
            si.s_ulong = * reinterpret_cast<ulong*>(arg);
            break;
        case Smoke::t_double:
            si.s_double = * reinterpret_cast<double*>(arg);
            break;
        case Smoke::t_float:
            si.s_float = * reinterpret_cast<float*>(arg);
            break;
        case Smoke::t_enum:
            si.s_enum = * reinterpret_cast<int*>(arg);
            break;
        case Smoke::t_class:
	   //printd(0, "QoreQtDynamicMethod::qtToQore() type=%s flags=0x%x, const=%s type=0x%x arg=%p\n", t.name, t.flags, t.flags & 0x40 ? "true" : "false", t.flags & 0x30, arg);
	   si.s_class = t.flags & Smoke::tf_ptr ? *((void **)arg) : arg;
	   //si.s_class = arg;
            break;

        default:
	   //printd(0, "QoreQtDynamicMethod::qtToQore type=%s flags=%d\n", t.name, t.flags);
            Q_ASSERT_X(false, "sig/slot", "missing qt to qore handling");
        }

//     if ((t.flags & Smoke::tf_elem) == Smoke::t_bool) {
//         bool *ptr = reinterpret_cast<bool *>(arg);
//         args->push(get_bool_node(*ptr));
//     } else if ((t.flags & Smoke::tf_elem) == Smoke::t_int) {
//         int *ptr = reinterpret_cast<int *>(arg);
//         args->push(new QoreBigIntNode(*ptr));
//     } else
//         assert(false);

    ExceptionSink xsink;
    AbstractQoreNode *newNode = Marshalling::stackToQore(t, si, &xsink);
    printd(0, "QoreQtDynamicMethod::qtToQore() type: %s s_class=%p rv=%p\n", t.name, si.s_class, newNode);
    if (!newNode)
        xsink.handleExceptions();
    args->push(newNode);
}

static void doDefaultValue(const Smoke::Type &t, Smoke::StackItem &si, ExceptionSink *xsink) {
#ifdef DEBUG
   int tid = t.flags & Smoke::tf_elem;
   int flags = t.flags & 0x30;
   //bool iconst = t.flags & Smoke::tf_const;

   //printd(0, "qtType.flags=%x const=%d tid=%d name=%s\n", flags, iconst, tid, t.name);

   assert(tid == Smoke::t_class);
   assert(flags == Smoke::tf_stack);
#endif

   // find and execute constructor
   CommonQoreMethod cqm(0, 0, t.name, t.name, 0, xsink);

   si.s_class = cqm.callConstructor();
}

void QoreQtDynamicMethod::qoreToQt(ExceptionSink *xsink, const Smoke::Type &qtType, Smoke::StackItem &si, void *&ptr, void *&save, const AbstractQoreNode *val, const char *cname, const char *mname, int index, bool value_required) {
    save = 0;
    ptr = 0;
//     printd(0, "qoreToQt() ptr=%p save=%p, val=%p (%s) typename=%s\n", ptr, save, val, val ? val->getTypeName() : "n/a", qtType.name);

    //QByteArray bname(qtType.name);
    if (CommonQoreMethod::qoreToStackStatic(xsink, si, cname, mname, qtType, val, index) == -1) {

       // setup default value on stack if required (ex: slot return value), otherwise return
       if (value_required)
	  doDefaultValue(qtType, si, xsink);
       else
	  return;
    }

    switch (qtType.flags & Smoke::tf_elem) {
    case Smoke::t_voidp:
        save = si.s_voidp;
        break;
    case Smoke::t_bool:
        save = /*(void *)*/&si.s_bool;
        break;
    case Smoke::t_char:
        save = /*(void *)*/&si.s_char;
        break;
    case Smoke::t_uchar:
        save = /*(void *)*/&si.s_uchar;
        break;
    case Smoke::t_short:
        save = /*(void *)*/&si.s_short;
        break;
    case Smoke::t_ushort:
        save = /*(void *)*/&si.s_ushort;
        break;
    case Smoke::t_int:
        save = /*(void *)*/&si.s_int;
        break;
    case Smoke::t_uint:
        save = /*(void *)*/&si.s_uint;
        break;
    case Smoke::t_long:
        save = /*(void *)*/&si.s_long;
        break;
    case Smoke::t_ulong:
        save = /*(void *)*/&si.s_ulong;
        break;
    case Smoke::t_float:
        save = /*(void *)*/&si.s_float;
        break;
    case Smoke::t_double:
        save = /*(void *)*/&si.s_double;
        break;
    case Smoke::t_enum:
        save = /*(void *)*/&si.s_enum;
        break;
    case Smoke::t_class:
        save = si.s_class;
        break;
    default:
        Q_ASSERT_X(false, "sig/slot", "missing qore to qt handling");
    }
    ptr = save;
}

void QoreQtDynamicMethod::qoreToQtDirect(const Smoke::Type &qtType, void *&ptr, const AbstractQoreNode *val, const char *cname, const char *mname) {
    //printd(0, "qoreToQtDirect() ptr=%p val=%p (%s)\n", ptr, val, val ? val->getTypeName() : "n/a");
    void * save;
    Smoke::StackItem si;
    ExceptionSink xsink;
    qoreToQt(&xsink, qtType, si, ptr, save, val, cname, mname, -1, true);
}

QoreQtDynamicSlot::QoreQtDynamicSlot(const QoreObject *qo, const QoreMethod *meth, const char *sig, ExceptionSink *xsink) : qore_obj(const_cast<QoreObject *>(qo)), method(meth) {
    returnType.name = 0;

    //printd(5, "QoreQtDynamicSlot::QoreQtDynamicSlot() registering method '%s'\n", meth->getName());

    const char *p = strchr(sig, '(');
    if (!p)
       return;
    ++p;
    while (*p && isblank(*p))
        ++p;
    if (*p != ')')
        identifyAndAddTypes(sig, p, xsink);
}

void QoreQtDynamicSlot::call(QoreObject *self, void **arguments) const {
    ExceptionSink xsink;

    //printd(0, "QoreQtDynamicSlot::call(self=%p, arguments=%p) %s() num_args=%d\n", self, arguments, method->getName(), typeList.size());
    // create Qore argument list
    ReferenceHolder<QoreListNode> args(typeList.empty() ? 0 : new QoreListNode, &xsink);
    for (int i = 0, e = typeList.size(); i < e; ++i) {
       printd(0, "%s() arg %d: %s %p\n", method->getName(), i + 1, typeList[i].name, arguments[i + 1]);
       qtToQore(typeList[i], arguments[i + 1], *args);
    }

    // call Qore user method
    ReferenceHolder<AbstractQoreNode> rv(qore_obj->evalMethod(*method, *args, &xsink), &xsink);

    // process return value
    if (returnType.name)
        qoreToQtDirect(returnType, arguments[0], *rv, qore_obj->getClassName(), method->getName());
}

QoreQtDynamicSignal::QoreQtDynamicSignal(const char *sig, ExceptionSink *xsink) {
    const char *p = strchr(sig, '(');

    if (!p) {
        xsink->raiseException("DYNAMIC-SIGNAL-ERROR", "invalid signal signature '%s'", sig);
        return;
    }
    ++p;

    identifyAndAddTypes(sig, p, xsink);
}

void QoreQtDynamicSignal::emitSignal(QObject *obj, int id, const QoreListNode *args, ExceptionSink *xsink) {
    int num_args = typeList.size();
    void *sig_args[num_args + 1];
    void *save_args[num_args];
    Smoke::StackItem si[num_args];

    // set return value to 0
    sig_args[0] = 0;

    // iterate through signal parameters to build argument list
    for (int i = 0; i < num_args; ++i) {
        // get argument QoreNode
        const AbstractQoreNode *n = args ? args->retrieve_entry(i + 1) : 0;

        qoreToQt(xsink, typeList[i], si[i], sig_args[i + 1], save_args[i], n, "QObject", "emit", i + 1);
	if (*xsink)
	   return;
    }
    QMetaObject::activate(obj, id, id, sig_args);

    // iterate through signal parameters to delete temporary values
    //for (int i = 0; i < num_args; ++i)
    // type_list[i]->del_arg(save_args[i]);
}

<commit_msg>fixed typo in last commit regarding signal/slot args<commit_after>/*
  Qore Programming Language Qt4 Module

  Copyright 2009 Qore Technologies sro

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

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

#include <QByteArray>

#include "qoresmokeglobal.h"
#include "qoreqtdynamicmethod.h"
#include "commonqoremethod.h"

int QoreQtDynamicMethod::identifyTypes(SmokeTypeList &typeList, const char *sig, const char *p, ExceptionSink *xsink) {
    //printd(0, "QoreQtDynamicMethod::identifyTypes sig=%s p=%s\n", sig, p);
    while (*p && isblank(*p))
        ++p;
    if (*p != ')')
        while (*p) {
            const char *e = p + 1;
            char paren = 0;
            while (paren || (*e != ')' && *e != ',')) {
                assert(*e);
                switch (*e) {
                case '<':
                case '(':
                case '[':
                    if (!paren)
                        paren = *e;
                    break;
                case '>':
                case ')':
                case ']':
                    if (*e == paren)
                        paren = 0;
                    break;
                }
                ++e;
            }
            addType(typeList, p, e - p, sig, xsink);
            if (*e == ')')
                break;
            p = e + 1;
        }
    return *xsink ? -1 : 0;
}

int QoreQtDynamicMethod::addType(SmokeTypeList &typeList, const char *b, int len, const char *sig, ExceptionSink *xsink) {
    QByteArray tmp(b, len);
    QString tn(tmp);
    tn = tn.simplified();
    if (tn.endsWith(" &"))
        tn.replace(" &", "&");
    if (tn.endsWith(" *"))
        tn.replace(" *", "*");
    //printd(0, "QoreQtDynamicMethod::addType() processing type '%s'\n", tn.constData());

    Smoke::Type t;
    t.classId = -1;

    if (tn == "int") {
        t.name = "int";
        t.flags = Smoke::t_int | Smoke::tf_stack;
    } else if (tn == "bool") {
        t.name = "bool";
        t.flags = Smoke::t_bool | Smoke::tf_stack;
    } else if (tn == "uint") {
        t.name = "uint";
        t.flags = Smoke::t_uint | Smoke::tf_stack;
    } else if (tn == "long") {
        t.name = "long";
        t.flags = Smoke::t_long | Smoke::tf_stack;
    } else if (tn == "ulong") {
        t.name = "ulong";
        t.flags = Smoke::t_ulong | Smoke::tf_stack;
    } else if (tn == "double") {
        t.name = "double";
        t.flags = Smoke::t_double | Smoke::tf_stack;
    } else if (tn == "char*" ) {
        t.name = "char*";
        t.flags = Smoke::t_voidp | Smoke::tf_ptr;
    } else if (tn == "qreal") {
        t.name = "qreal";
        t.flags = Smoke::t_double | Smoke::tf_stack;
    } else if (tn.contains("QString")) {
        t.name = "QString&";
        t.flags = Smoke::t_voidp | Smoke::tf_ref;
    }
    // everything else should be pointer to object
    else {
        // TODO/FIXME: there should be a better way! But it looks like it is
        // not implemented in Smoke
        bool found = false;
        Smoke::Type st;
        for (int i = 0; i < qt_Smoke->numTypes; ++i) {
            st = qt_Smoke->types[i];
            if (tn == st.name) {
                //printd(0, "QoreQtDynamicMethod::addType() found object/ref to %s\n", st.name);
                t.name = st.name;
                t.flags = st.flags;
                t.classId = st.classId;
                found = true;
                break;
            }
        }
        if (!found) {
            xsink->raiseException("DYNAMIC-METHOD-ERROR", "cannot handle argument type '%s' in '%s'", tn.constData(), sig);
            return -1;
        }
    }

    typeList.push_back(t);
    return 0;
}

void QoreQtDynamicMethod::qtToQore(const Smoke::Type &t, void *arg, QoreListNode *args) {
    assert(t.name);
    Smoke::StackItem si;

    int typ = t.flags & Smoke::tf_ref;
    assert(typ);

    if (typ == Smoke::tf_ref && !strcmp(t.name, "QString&"))
        si.s_voidp = arg;
    else
        switch (t.flags & Smoke::tf_elem) {
        case Smoke::t_voidp:
            si.s_voidp = arg;
            break;
        case Smoke::t_bool:
            si.s_bool = * reinterpret_cast<bool*>(arg);
            break;
        case Smoke::t_int:
            si.s_int = * reinterpret_cast<int*>(arg);
            break;
        case Smoke::t_uint:
            si.s_uint = * reinterpret_cast<uint*>(arg);
            break;
        case Smoke::t_long:
            si.s_long = * reinterpret_cast<long*>(arg);
            break;
        case Smoke::t_ulong:
            si.s_ulong = * reinterpret_cast<ulong*>(arg);
            break;
        case Smoke::t_double:
            si.s_double = * reinterpret_cast<double*>(arg);
            break;
        case Smoke::t_float:
            si.s_float = * reinterpret_cast<float*>(arg);
            break;
        case Smoke::t_enum:
            si.s_enum = * reinterpret_cast<int*>(arg);
            break;
        case Smoke::t_class:
	   printd(0, "QoreQtDynamicMethod::qtToQore() type=%s flags=0x%x, const=%s type=0x%x arg=%p\n", t.name, t.flags, t.flags & 0x40 ? "true" : "false", t.flags & 0x30, arg);
	   si.s_class = typ == Smoke::tf_ptr ? *((void **)arg) : arg;
	   //si.s_class = arg;
            break;

        default:
	   //printd(0, "QoreQtDynamicMethod::qtToQore type=%s flags=%d\n", t.name, t.flags);
            Q_ASSERT_X(false, "sig/slot", "missing qt to qore handling");
        }

//     if ((t.flags & Smoke::tf_elem) == Smoke::t_bool) {
//         bool *ptr = reinterpret_cast<bool *>(arg);
//         args->push(get_bool_node(*ptr));
//     } else if ((t.flags & Smoke::tf_elem) == Smoke::t_int) {
//         int *ptr = reinterpret_cast<int *>(arg);
//         args->push(new QoreBigIntNode(*ptr));
//     } else
//         assert(false);

    ExceptionSink xsink;
    AbstractQoreNode *newNode = Marshalling::stackToQore(t, si, &xsink);
    printd(0, "QoreQtDynamicMethod::qtToQore() type: %s s_class=%p rv=%p\n", t.name, si.s_class, newNode);
    if (!newNode)
        xsink.handleExceptions();
    args->push(newNode);
}

static void doDefaultValue(const Smoke::Type &t, Smoke::StackItem &si, ExceptionSink *xsink) {
#ifdef DEBUG
   int tid = t.flags & Smoke::tf_elem;
   int flags = t.flags & 0x30;
   //bool iconst = t.flags & Smoke::tf_const;

   //printd(0, "qtType.flags=%x const=%d tid=%d name=%s\n", flags, iconst, tid, t.name);

   assert(tid == Smoke::t_class);
   assert(flags == Smoke::tf_stack);
#endif

   // find and execute constructor
   CommonQoreMethod cqm(0, 0, t.name, t.name, 0, xsink);

   si.s_class = cqm.callConstructor();
}

void QoreQtDynamicMethod::qoreToQt(ExceptionSink *xsink, const Smoke::Type &qtType, Smoke::StackItem &si, void *&ptr, void *&save, const AbstractQoreNode *val, const char *cname, const char *mname, int index, bool value_required) {
    save = 0;
    ptr = 0;
//     printd(0, "qoreToQt() ptr=%p save=%p, val=%p (%s) typename=%s\n", ptr, save, val, val ? val->getTypeName() : "n/a", qtType.name);

    //QByteArray bname(qtType.name);
    if (CommonQoreMethod::qoreToStackStatic(xsink, si, cname, mname, qtType, val, index) == -1) {

       // setup default value on stack if required (ex: slot return value), otherwise return
       if (value_required)
	  doDefaultValue(qtType, si, xsink);
       else
	  return;
    }

    switch (qtType.flags & Smoke::tf_elem) {
    case Smoke::t_voidp:
        save = si.s_voidp;
        break;
    case Smoke::t_bool:
        save = /*(void *)*/&si.s_bool;
        break;
    case Smoke::t_char:
        save = /*(void *)*/&si.s_char;
        break;
    case Smoke::t_uchar:
        save = /*(void *)*/&si.s_uchar;
        break;
    case Smoke::t_short:
        save = /*(void *)*/&si.s_short;
        break;
    case Smoke::t_ushort:
        save = /*(void *)*/&si.s_ushort;
        break;
    case Smoke::t_int:
        save = /*(void *)*/&si.s_int;
        break;
    case Smoke::t_uint:
        save = /*(void *)*/&si.s_uint;
        break;
    case Smoke::t_long:
        save = /*(void *)*/&si.s_long;
        break;
    case Smoke::t_ulong:
        save = /*(void *)*/&si.s_ulong;
        break;
    case Smoke::t_float:
        save = /*(void *)*/&si.s_float;
        break;
    case Smoke::t_double:
        save = /*(void *)*/&si.s_double;
        break;
    case Smoke::t_enum:
        save = /*(void *)*/&si.s_enum;
        break;
    case Smoke::t_class:
        save = si.s_class;
        break;
    default:
        Q_ASSERT_X(false, "sig/slot", "missing qore to qt handling");
    }
    ptr = save;
}

void QoreQtDynamicMethod::qoreToQtDirect(const Smoke::Type &qtType, void *&ptr, const AbstractQoreNode *val, const char *cname, const char *mname) {
    //printd(0, "qoreToQtDirect() ptr=%p val=%p (%s)\n", ptr, val, val ? val->getTypeName() : "n/a");
    void * save;
    Smoke::StackItem si;
    ExceptionSink xsink;
    qoreToQt(&xsink, qtType, si, ptr, save, val, cname, mname, -1, true);
}

QoreQtDynamicSlot::QoreQtDynamicSlot(const QoreObject *qo, const QoreMethod *meth, const char *sig, ExceptionSink *xsink) : qore_obj(const_cast<QoreObject *>(qo)), method(meth) {
    returnType.name = 0;

    //printd(5, "QoreQtDynamicSlot::QoreQtDynamicSlot() registering method '%s'\n", meth->getName());

    const char *p = strchr(sig, '(');
    if (!p)
       return;
    ++p;
    while (*p && isblank(*p))
        ++p;
    if (*p != ')')
        identifyAndAddTypes(sig, p, xsink);
}

void QoreQtDynamicSlot::call(QoreObject *self, void **arguments) const {
    ExceptionSink xsink;

    //printd(0, "QoreQtDynamicSlot::call(self=%p, arguments=%p) %s() num_args=%d\n", self, arguments, method->getName(), typeList.size());
    // create Qore argument list
    ReferenceHolder<QoreListNode> args(typeList.empty() ? 0 : new QoreListNode, &xsink);
    for (int i = 0, e = typeList.size(); i < e; ++i) {
       printd(0, "%s() arg %d: %s %p\n", method->getName(), i + 1, typeList[i].name, arguments[i + 1]);
       qtToQore(typeList[i], arguments[i + 1], *args);
    }

    // call Qore user method
    ReferenceHolder<AbstractQoreNode> rv(qore_obj->evalMethod(*method, *args, &xsink), &xsink);

    // process return value
    if (returnType.name)
        qoreToQtDirect(returnType, arguments[0], *rv, qore_obj->getClassName(), method->getName());
}

QoreQtDynamicSignal::QoreQtDynamicSignal(const char *sig, ExceptionSink *xsink) {
    const char *p = strchr(sig, '(');

    if (!p) {
        xsink->raiseException("DYNAMIC-SIGNAL-ERROR", "invalid signal signature '%s'", sig);
        return;
    }
    ++p;

    identifyAndAddTypes(sig, p, xsink);
}

void QoreQtDynamicSignal::emitSignal(QObject *obj, int id, const QoreListNode *args, ExceptionSink *xsink) {
    int num_args = typeList.size();
    void *sig_args[num_args + 1];
    void *save_args[num_args];
    Smoke::StackItem si[num_args];

    // set return value to 0
    sig_args[0] = 0;

    // iterate through signal parameters to build argument list
    for (int i = 0; i < num_args; ++i) {
        // get argument QoreNode
        const AbstractQoreNode *n = args ? args->retrieve_entry(i + 1) : 0;

        qoreToQt(xsink, typeList[i], si[i], sig_args[i + 1], save_args[i], n, "QObject", "emit", i + 1);
	if (*xsink)
	   return;
    }
    QMetaObject::activate(obj, id, id, sig_args);

    // iterate through signal parameters to delete temporary values
    //for (int i = 0; i < num_args; ++i)
    // type_list[i]->del_arg(save_args[i]);
}

<|endoftext|>


<commit_before>#ifndef G2_FIELD_CORE_INCLUDE_FIELD_CONSTANTS_HH_
#define G2_FIELD_CORE_INCLUDE_FIELD_CONSTANTS_HH_

/*===========================================================================*\

author: Matthias W. Smith
email:  mwsmith2@uw.edu
file:   field_constants.hh

about:  A header file for constant parameters used across field team
        software.

\*===========================================================================*/

// NMR literals
#define NMR_NUM_FIXED_PROBES 378
#define NMR_FID_LENGTH_ONLINE 100000
#define NMR_FID_LENGTH_RECORD 10000
#define NMR_KHZ_TO_PPM 61790.0 * 1.0e-6
#define NMR_SAMPLE_PERIOD 0.0001

//Trolley literals
#define TRLY_NMR_LENGTH 24000
#define TRLY_BARCODE_LENGTH 3000 //ALL CHANNELS
#define TRLY_BARCODE_CHANNELS 6
#define TRLY_MONITOR_LENGTH 3000

namespace g2field {

// General constants
constexpr double kMagicRadius = 7112.0;
constexpr double kPoleGapZ = 180.0;

// NMR constants
constexpr int kNmrNumFixedProbes = NMR_NUM_FIXED_PROBES;
constexpr int kNmrFidLengthOnline = NMR_FID_LENGTH_ONLINE;
constexpr int kNmrFidLengthRecord = NMR_FID_LENGTH_RECORD;
constexpr double kNmrKhzToPpm = NMR_KHZ_TO_PPM;
constexpr double kNmrSamplePeriod = NMR_SAMPLE_PERIOD;

// Trolley constants
constexpr int kNumTrolleyProbes = 17;
constexpr double kTrolleyRadius = 3.5;

} // ::g2field

#endif
<commit_msg>adding root include<commit_after>#ifndef G2_FIELD_CORE_INCLUDE_FIELD_CONSTANTS_HH_
#define G2_FIELD_CORE_INCLUDE_FIELD_CONSTANTS_HH_

/*===========================================================================*\

author: Matthias W. Smith
email:  mwsmith2@uw.edu
file:   field_constants.hh

about:  A header file for constant parameters used across field team
        software.

\*===========================================================================*/

#include "TROOT.h"

// NMR literals
#define NMR_NUM_FIXED_PROBES 378
#define NMR_FID_LENGTH_ONLINE 100000
#define NMR_FID_LENGTH_RECORD 10000
#define NMR_KHZ_TO_PPM 61790.0 * 1.0e-6
#define NMR_SAMPLE_PERIOD 0.0001

//Trolley literals
#define TRLY_NMR_LENGTH 24000
#define TRLY_BARCODE_LENGTH 3000 //ALL CHANNELS
#define TRLY_BARCODE_CHANNELS 6
#define TRLY_MONITOR_LENGTH 3000

namespace g2field {

// General constants
constexpr double kMagicRadius = 7112.0;
constexpr double kPoleGapZ = 180.0;

// NMR constants
constexpr int kNmrNumFixedProbes = NMR_NUM_FIXED_PROBES;
constexpr int kNmrFidLengthOnline = NMR_FID_LENGTH_ONLINE;
constexpr int kNmrFidLengthRecord = NMR_FID_LENGTH_RECORD;
constexpr double kNmrKhzToPpm = NMR_KHZ_TO_PPM;
constexpr double kNmrSamplePeriod = NMR_SAMPLE_PERIOD;

// Trolley constants
constexpr int kNumTrolleyProbes = 17;
constexpr double kTrolleyRadius = 3.5;

} // ::g2field

#endif
<|endoftext|>