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

#include "base/basictypes.h"
#include "base/file_path.h"
#include "base/stringprintf.h"
#include "base/string_util.h"
#include "base/test/test_timeouts.h"
#include "base/threading/platform_thread.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/test_launcher_utils.h"
#include "chrome/test/ui/ui_layout_test.h"
#include "chrome/test/ui/ui_test.h"
#include "net/base/net_util.h"
#include "ui/gfx/gl/gl_implementation.h"

class MediaTest : public UITest {
 protected:
  virtual void SetUp() {
    EXPECT_TRUE(test_launcher_utils::OverrideGLImplementation(
        &launch_arguments_,
        gfx::kGLImplementationOSMesaName));

#if defined(OS_MACOSX)
    // Accelerated compositing does not work with OSMesa. AcceleratedSurface
    // assumes GL contexts are native.
    launch_arguments_.AppendSwitch(switches::kDisableAcceleratedCompositing);
#endif

    UITest::SetUp();
  }

  void PlayMedia(const char* tag, const char* media_file) {
    FilePath test_file(test_data_directory_);
    test_file = test_file.AppendASCII("media/player.html");

    GURL player_gurl = net::FilePathToFileURL(test_file);
    std::string url = base::StringPrintf(
        "%s?%s=%s", player_gurl.spec().c_str(), tag, media_file);

    NavigateToURL(GURL(url));

    // Allow the media file to be loaded.
    const std::wstring kPlaying = L"PLAYING";
    const std::wstring kFailed = L"FAILED";
    const std::wstring kError = L"ERROR";
    for (int i = 0; i < 10; ++i) {
      base::PlatformThread::Sleep(TestTimeouts::action_timeout_ms());
      const std::wstring& title = GetActiveTabTitle();
      if (title == kPlaying || title == kFailed ||
          StartsWith(title, kError, true))
        break;
    }

    EXPECT_EQ(kPlaying, GetActiveTabTitle());
  }

  void PlayAudio(const char* url) {
    PlayMedia("audio", url);
  }

  void PlayVideo(const char* url) {
    PlayMedia("video", url);
  }
};

TEST_F(MediaTest, VideoBearTheora) {
  PlayVideo("bear.ogv");
}

TEST_F(MediaTest, VideoBearSilentTheora) {
  PlayVideo("bear_silent.ogv");
}

TEST_F(MediaTest, VideoBearWebm) {
  PlayVideo("bear.webm");
}

TEST_F(MediaTest, VideoBearSilentWebm) {
  PlayVideo("bear_silent.webm");
}

#if defined(GOOGLE_CHROME_BUILD) || defined(USE_PROPRIETARY_CODECS)
TEST_F(MediaTest, VideoBearMp4) {
  PlayVideo("bear.mp4");
}

TEST_F(MediaTest, VideoBearSilentMp4) {
  PlayVideo("bear_silent.mp4");
}
#endif

TEST_F(MediaTest, VideoBearWav) {
  PlayVideo("bear.wav");
}

TEST_F(UILayoutTest, MediaUILayoutTest) {
  static const char* kResources[] = {
    "content",
    "media-file.js",
    "media-fullscreen.js",
    "video-paint-test.js",
    "video-played.js",
    "video-test.js",
  };

  static const char* kMediaTests[] = {
    "video-autoplay.html",
    // "video-loop.html", disabled due to 52887.
    "video-no-autoplay.html",
    // TODO(sergeyu): Add more tests here.
  };

  FilePath test_dir;
  FilePath media_test_dir;
  media_test_dir = media_test_dir.AppendASCII("media");
  InitializeForLayoutTest(test_dir, media_test_dir, kNoHttpPort);

  // Copy resources first.
  for (size_t i = 0; i < arraysize(kResources); ++i)
    AddResourceForLayoutTest(
        test_dir, media_test_dir.AppendASCII(kResources[i]));

  for (size_t i = 0; i < arraysize(kMediaTests); ++i)
    RunLayoutTest(kMediaTests[i], kNoHttpPort);
}
<commit_msg>Mark VideoBearTheora and VideoBearWav flaky on Mac.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/basictypes.h"
#include "base/file_path.h"
#include "base/stringprintf.h"
#include "base/string_util.h"
#include "base/test/test_timeouts.h"
#include "base/threading/platform_thread.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/test_launcher_utils.h"
#include "chrome/test/ui/ui_layout_test.h"
#include "chrome/test/ui/ui_test.h"
#include "net/base/net_util.h"
#include "ui/gfx/gl/gl_implementation.h"

class MediaTest : public UITest {
 protected:
  virtual void SetUp() {
    EXPECT_TRUE(test_launcher_utils::OverrideGLImplementation(
        &launch_arguments_,
        gfx::kGLImplementationOSMesaName));

#if defined(OS_MACOSX)
    // Accelerated compositing does not work with OSMesa. AcceleratedSurface
    // assumes GL contexts are native.
    launch_arguments_.AppendSwitch(switches::kDisableAcceleratedCompositing);
#endif

    UITest::SetUp();
  }

  void PlayMedia(const char* tag, const char* media_file) {
    FilePath test_file(test_data_directory_);
    test_file = test_file.AppendASCII("media/player.html");

    GURL player_gurl = net::FilePathToFileURL(test_file);
    std::string url = base::StringPrintf(
        "%s?%s=%s", player_gurl.spec().c_str(), tag, media_file);

    NavigateToURL(GURL(url));

    // Allow the media file to be loaded.
    const std::wstring kPlaying = L"PLAYING";
    const std::wstring kFailed = L"FAILED";
    const std::wstring kError = L"ERROR";
    for (int i = 0; i < 10; ++i) {
      base::PlatformThread::Sleep(TestTimeouts::action_timeout_ms());
      const std::wstring& title = GetActiveTabTitle();
      if (title == kPlaying || title == kFailed ||
          StartsWith(title, kError, true))
        break;
    }

    EXPECT_EQ(kPlaying, GetActiveTabTitle());
  }

  void PlayAudio(const char* url) {
    PlayMedia("audio", url);
  }

  void PlayVideo(const char* url) {
    PlayMedia("video", url);
  }
};

#if defined(OS_MACOSX)
// http://crbug.com/84170 - VideoBearTheora and VideoBearWav are flaky on Mac.
#define MAYBE_VideoBearTheora FLAKY_VideoBearTheora
#define MAYBE_VideoBearWav FLAKY_VideoBearWav
#else
#define MAYBE_VideoBearTheora VideoBearTheora
#define MAYBE_VideoBearWav  VideoBearWav
#endif

TEST_F(MediaTest, MAYBE_VideoBearTheora) {
  PlayVideo("bear.ogv");
}

TEST_F(MediaTest, VideoBearSilentTheora) {
  PlayVideo("bear_silent.ogv");
}

TEST_F(MediaTest, VideoBearWebm) {
  PlayVideo("bear.webm");
}

TEST_F(MediaTest, VideoBearSilentWebm) {
  PlayVideo("bear_silent.webm");
}

#if defined(GOOGLE_CHROME_BUILD) || defined(USE_PROPRIETARY_CODECS)
TEST_F(MediaTest, VideoBearMp4) {
  PlayVideo("bear.mp4");
}

TEST_F(MediaTest, VideoBearSilentMp4) {
  PlayVideo("bear_silent.mp4");
}
#endif

TEST_F(MediaTest, MAYBE_VideoBearWav) {
  PlayVideo("bear.wav");
}

TEST_F(UILayoutTest, MediaUILayoutTest) {
  static const char* kResources[] = {
    "content",
    "media-file.js",
    "media-fullscreen.js",
    "video-paint-test.js",
    "video-played.js",
    "video-test.js",
  };

  static const char* kMediaTests[] = {
    "video-autoplay.html",
    // "video-loop.html", disabled due to 52887.
    "video-no-autoplay.html",
    // TODO(sergeyu): Add more tests here.
  };

  FilePath test_dir;
  FilePath media_test_dir;
  media_test_dir = media_test_dir.AppendASCII("media");
  InitializeForLayoutTest(test_dir, media_test_dir, kNoHttpPort);

  // Copy resources first.
  for (size_t i = 0; i < arraysize(kResources); ++i)
    AddResourceForLayoutTest(
        test_dir, media_test_dir.AppendASCII(kResources[i]));

  for (size_t i = 0; i < arraysize(kMediaTests); ++i)
    RunLayoutTest(kMediaTests[i], kNoHttpPort);
}
<|endoftext|>


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

#include "base/file_util.h"
#include "base/path_service.h"
#include "build/build_config.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/ui/ui_test.h"
#include "net/base/net_util.h"
#include "net/url_request/url_request_unittest.h"
#include "webkit/glue/plugins/plugin_switches.h"

namespace {

// Platform-specific filename relative to the chrome executable.
#if defined(OS_WIN)
const wchar_t library_name[] = L"ppapi_tests.dll";
#elif defined(OS_MACOSX)
const char library_name[] = "ppapi_tests.plugin";
#elif defined(OS_POSIX)
const char library_name[] = "libppapi_tests.so";
#endif

}  // namespace

class PPAPITest : public UITest {
 public:
  PPAPITest() {
    // Append the switch to register the pepper plugin.
    // library name = <out dir>/<test_name>.<library_extension>
    // MIME type = application/x-ppapi-<test_name>
    FilePath plugin_dir;
    PathService::Get(base::DIR_EXE, &plugin_dir);

    FilePath plugin_lib = plugin_dir.Append(library_name);
    EXPECT_TRUE(file_util::PathExists(plugin_lib));

#if defined(OS_WIN)
    std::wstring pepper_plugin = plugin_lib.value();
#else
    std::wstring pepper_plugin = UTF8ToWide(plugin_lib.value());
#endif
    pepper_plugin.append(L";application/x-ppapi-tests");
    launch_arguments_.AppendSwitchWithValue(switches::kRegisterPepperPlugins,
                                            pepper_plugin);

    // The test sends us the result via a cookie.
    launch_arguments_.AppendSwitch(switches::kEnableFileCookies);

    // Some stuff is hung off of the testing interface which is not enabled
    // by default.
    launch_arguments_.AppendSwitch(switches::kEnablePepperTesting);
  }

  void RunTest(const std::string& test_case) {
    FilePath test_path;
    PathService::Get(base::DIR_SOURCE_ROOT, &test_path);
    test_path = test_path.Append(FILE_PATH_LITERAL("third_party"));
    test_path = test_path.Append(FILE_PATH_LITERAL("ppapi"));
    test_path = test_path.Append(FILE_PATH_LITERAL("tests"));
    test_path = test_path.Append(FILE_PATH_LITERAL("test_case.html"));

    // Sanity check the file name.
    EXPECT_TRUE(file_util::PathExists(test_path));

    GURL::Replacements replacements;
    replacements.SetQuery(test_case.c_str(),
                          url_parse::Component(0, test_case.size()));
    GURL test_url = net::FilePathToFileURL(test_path);
    RunTestURL(test_url.ReplaceComponents(replacements));
  }

  void RunTestViaHTTP(const std::string& test_case) {
    const wchar_t kDocRoot[] = L"third_party/ppapi/tests";
    scoped_refptr<HTTPTestServer> server(
        HTTPTestServer::CreateServer(kDocRoot));
    ASSERT_TRUE(server);
    RunTestURL(server->TestServerPage("files/test_case.html?" + test_case));
  }

 private:
  void RunTestURL(const GURL& test_url) {
    scoped_refptr<TabProxy> tab(GetActiveTab());
    ASSERT_TRUE(tab.get());
    ASSERT_TRUE(tab->NavigateToURL(test_url));
    std::string escaped_value =
        WaitUntilCookieNonEmpty(tab.get(), test_url,
            "COMPLETION_COOKIE", action_max_timeout_ms());
    EXPECT_STREQ("PASS", escaped_value.c_str());
  }
};

#if defined(OS_MACOSX)
// TODO(brettw) this fails on Mac for unknown reasons.
TEST_F(PPAPITest, DISABLED_DeviceContext2D) {
#else
TEST_F(PPAPITest, DeviceContext2D) {
#endif
  RunTest("DeviceContext2D");
}

#if defined(OS_MACOSX)
// TODO(brettw) this fails on Mac for unknown reasons.
TEST_F(PPAPITest, DISABLED_ImageData) {
#else
TEST_F(PPAPITest, ImageData) {
#endif
  RunTest("ImageData");
}

TEST_F(PPAPITest, Buffer) {
  RunTest("Buffer");
}

TEST_F(PPAPITest, URLLoader) {
  RunTestViaHTTP("URLLoader");
}

TEST_F(PPAPITest, PaintAgggregator) {
  RunTestViaHTTP("PaintAggregator");
}

// http://crbug.com/48544
#if defined(OS_LINUX)
// TODO(jabdelmalek) this fails on Linux for unknown reasons.
TEST_F(PPAPITest, FAILS_Scrollbar) {
#else
TEST_F(PPAPITest, Scrollbar) {
#endif
  RunTest("Scrollbar");
}
<commit_msg>GTTF: Flip PPAPITest.Scrollbar from FAILS to FLAKY on Linux, because it is flaky.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/file_util.h"
#include "base/path_service.h"
#include "build/build_config.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/ui/ui_test.h"
#include "net/base/net_util.h"
#include "net/url_request/url_request_unittest.h"
#include "webkit/glue/plugins/plugin_switches.h"

namespace {

// Platform-specific filename relative to the chrome executable.
#if defined(OS_WIN)
const wchar_t library_name[] = L"ppapi_tests.dll";
#elif defined(OS_MACOSX)
const char library_name[] = "ppapi_tests.plugin";
#elif defined(OS_POSIX)
const char library_name[] = "libppapi_tests.so";
#endif

}  // namespace

class PPAPITest : public UITest {
 public:
  PPAPITest() {
    // Append the switch to register the pepper plugin.
    // library name = <out dir>/<test_name>.<library_extension>
    // MIME type = application/x-ppapi-<test_name>
    FilePath plugin_dir;
    PathService::Get(base::DIR_EXE, &plugin_dir);

    FilePath plugin_lib = plugin_dir.Append(library_name);
    EXPECT_TRUE(file_util::PathExists(plugin_lib));

#if defined(OS_WIN)
    std::wstring pepper_plugin = plugin_lib.value();
#else
    std::wstring pepper_plugin = UTF8ToWide(plugin_lib.value());
#endif
    pepper_plugin.append(L";application/x-ppapi-tests");
    launch_arguments_.AppendSwitchWithValue(switches::kRegisterPepperPlugins,
                                            pepper_plugin);

    // The test sends us the result via a cookie.
    launch_arguments_.AppendSwitch(switches::kEnableFileCookies);

    // Some stuff is hung off of the testing interface which is not enabled
    // by default.
    launch_arguments_.AppendSwitch(switches::kEnablePepperTesting);
  }

  void RunTest(const std::string& test_case) {
    FilePath test_path;
    PathService::Get(base::DIR_SOURCE_ROOT, &test_path);
    test_path = test_path.Append(FILE_PATH_LITERAL("third_party"));
    test_path = test_path.Append(FILE_PATH_LITERAL("ppapi"));
    test_path = test_path.Append(FILE_PATH_LITERAL("tests"));
    test_path = test_path.Append(FILE_PATH_LITERAL("test_case.html"));

    // Sanity check the file name.
    EXPECT_TRUE(file_util::PathExists(test_path));

    GURL::Replacements replacements;
    replacements.SetQuery(test_case.c_str(),
                          url_parse::Component(0, test_case.size()));
    GURL test_url = net::FilePathToFileURL(test_path);
    RunTestURL(test_url.ReplaceComponents(replacements));
  }

  void RunTestViaHTTP(const std::string& test_case) {
    const wchar_t kDocRoot[] = L"third_party/ppapi/tests";
    scoped_refptr<HTTPTestServer> server(
        HTTPTestServer::CreateServer(kDocRoot));
    ASSERT_TRUE(server);
    RunTestURL(server->TestServerPage("files/test_case.html?" + test_case));
  }

 private:
  void RunTestURL(const GURL& test_url) {
    scoped_refptr<TabProxy> tab(GetActiveTab());
    ASSERT_TRUE(tab.get());
    ASSERT_TRUE(tab->NavigateToURL(test_url));
    std::string escaped_value =
        WaitUntilCookieNonEmpty(tab.get(), test_url,
            "COMPLETION_COOKIE", action_max_timeout_ms());
    EXPECT_STREQ("PASS", escaped_value.c_str());
  }
};

#if defined(OS_MACOSX)
// TODO(brettw) this fails on Mac for unknown reasons.
TEST_F(PPAPITest, DISABLED_DeviceContext2D) {
#else
TEST_F(PPAPITest, DeviceContext2D) {
#endif
  RunTest("DeviceContext2D");
}

#if defined(OS_MACOSX)
// TODO(brettw) this fails on Mac for unknown reasons.
TEST_F(PPAPITest, DISABLED_ImageData) {
#else
TEST_F(PPAPITest, ImageData) {
#endif
  RunTest("ImageData");
}

TEST_F(PPAPITest, Buffer) {
  RunTest("Buffer");
}

TEST_F(PPAPITest, URLLoader) {
  RunTestViaHTTP("URLLoader");
}

TEST_F(PPAPITest, PaintAgggregator) {
  RunTestViaHTTP("PaintAggregator");
}

#if defined(OS_LINUX)
// Flaky, http://crbug.com/48544.
TEST_F(PPAPITest, FLAKY_Scrollbar) {
#else
TEST_F(PPAPITest, Scrollbar) {
#endif
  RunTest("Scrollbar");
}
<|endoftext|>


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

#include "base/file_util.h"
#include "base/path_service.h"
#include "build/build_config.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/ui/ui_test.h"
#include "net/base/net_util.h"
#include "net/test/test_server.h"
#include "webkit/glue/plugins/plugin_switches.h"

namespace {

// Platform-specific filename relative to the chrome executable.
#if defined(OS_WIN)
const wchar_t library_name[] = L"ppapi_tests.dll";
#elif defined(OS_MACOSX)
const char library_name[] = "ppapi_tests.plugin";
#elif defined(OS_POSIX)
const char library_name[] = "libppapi_tests.so";
#endif

}  // namespace

class PPAPITest : public UITest {
 public:
  PPAPITest() {
    // Append the switch to register the pepper plugin.
    // library name = <out dir>/<test_name>.<library_extension>
    // MIME type = application/x-ppapi-<test_name>
    FilePath plugin_dir;
    PathService::Get(base::DIR_EXE, &plugin_dir);

    FilePath plugin_lib = plugin_dir.Append(library_name);
    EXPECT_TRUE(file_util::PathExists(plugin_lib));
    FilePath::StringType pepper_plugin = plugin_lib.value();
    pepper_plugin.append(FILE_PATH_LITERAL(";application/x-ppapi-tests"));
    launch_arguments_.AppendSwitchNative(switches::kRegisterPepperPlugins,
                                         pepper_plugin);

    // The test sends us the result via a cookie.
    launch_arguments_.AppendSwitch(switches::kEnableFileCookies);

    // Some stuff is hung off of the testing interface which is not enabled
    // by default.
    launch_arguments_.AppendSwitch(switches::kEnablePepperTesting);
  }

  void RunTest(const std::string& test_case) {
    FilePath test_path;
    PathService::Get(base::DIR_SOURCE_ROOT, &test_path);
    test_path = test_path.Append(FILE_PATH_LITERAL("third_party"));
    test_path = test_path.Append(FILE_PATH_LITERAL("ppapi"));
    test_path = test_path.Append(FILE_PATH_LITERAL("tests"));
    test_path = test_path.Append(FILE_PATH_LITERAL("test_case.html"));

    // Sanity check the file name.
    EXPECT_TRUE(file_util::PathExists(test_path));

    GURL::Replacements replacements;
    replacements.SetQuery(test_case.c_str(),
                          url_parse::Component(0, test_case.size()));
    GURL test_url = net::FilePathToFileURL(test_path);
    RunTestURL(test_url.ReplaceComponents(replacements));
  }

  void RunTestViaHTTP(const std::string& test_case) {
    const wchar_t kDocRoot[] = L"third_party/ppapi/tests";
    scoped_refptr<net::HTTPTestServer> server(
        net::HTTPTestServer::CreateServer(kDocRoot));
    ASSERT_TRUE(server);
    RunTestURL(server->TestServerPage("files/test_case.html?" + test_case));
  }

 private:
  void RunTestURL(const GURL& test_url) {
    scoped_refptr<TabProxy> tab(GetActiveTab());
    ASSERT_TRUE(tab.get());
    ASSERT_TRUE(tab->NavigateToURL(test_url));
    std::string escaped_value =
        WaitUntilCookieNonEmpty(tab.get(), test_url,
            "COMPLETION_COOKIE", action_max_timeout_ms());
    EXPECT_STREQ("PASS", escaped_value.c_str());
  }
};

TEST_F(PPAPITest, DeviceContext2D) {
  RunTest("DeviceContext2D");
}

// TODO(brettw) bug 51344: this is flaky on bots. Seems to timeout navigating.
// Possibly all the image allocations slow things down on a loaded bot too much.
TEST_F(PPAPITest, FLAKY_ImageData) {
  RunTest("ImageData");
}

TEST_F(PPAPITest, Buffer) {
  RunTest("Buffer");
}

// TODO(brettw) bug 51345: this failed consistently on one of the bots.
TEST_F(PPAPITest, FAILS_URLLoader) {
  RunTestViaHTTP("URLLoader");
}

// Flaky, http://crbug.com/51012
TEST_F(PPAPITest, FLAKY_PaintAggregator) {
  RunTestViaHTTP("PaintAggregator");
}

#if defined(OS_LINUX)
// Flaky, http://crbug.com/48544.
TEST_F(PPAPITest, FLAKY_Scrollbar) {
#else
TEST_F(PPAPITest, Scrollbar) {
#endif
  RunTest("Scrollbar");
}

TEST_F(PPAPITest, UrlUtil) {
  RunTest("UrlUtil");
}
<commit_msg>Mark scrollbar test flaky on Mac.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/file_util.h"
#include "base/path_service.h"
#include "build/build_config.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/ui/ui_test.h"
#include "net/base/net_util.h"
#include "net/test/test_server.h"
#include "webkit/glue/plugins/plugin_switches.h"

namespace {

// Platform-specific filename relative to the chrome executable.
#if defined(OS_WIN)
const wchar_t library_name[] = L"ppapi_tests.dll";
#elif defined(OS_MACOSX)
const char library_name[] = "ppapi_tests.plugin";
#elif defined(OS_POSIX)
const char library_name[] = "libppapi_tests.so";
#endif

}  // namespace

class PPAPITest : public UITest {
 public:
  PPAPITest() {
    // Append the switch to register the pepper plugin.
    // library name = <out dir>/<test_name>.<library_extension>
    // MIME type = application/x-ppapi-<test_name>
    FilePath plugin_dir;
    PathService::Get(base::DIR_EXE, &plugin_dir);

    FilePath plugin_lib = plugin_dir.Append(library_name);
    EXPECT_TRUE(file_util::PathExists(plugin_lib));
    FilePath::StringType pepper_plugin = plugin_lib.value();
    pepper_plugin.append(FILE_PATH_LITERAL(";application/x-ppapi-tests"));
    launch_arguments_.AppendSwitchNative(switches::kRegisterPepperPlugins,
                                         pepper_plugin);

    // The test sends us the result via a cookie.
    launch_arguments_.AppendSwitch(switches::kEnableFileCookies);

    // Some stuff is hung off of the testing interface which is not enabled
    // by default.
    launch_arguments_.AppendSwitch(switches::kEnablePepperTesting);
  }

  void RunTest(const std::string& test_case) {
    FilePath test_path;
    PathService::Get(base::DIR_SOURCE_ROOT, &test_path);
    test_path = test_path.Append(FILE_PATH_LITERAL("third_party"));
    test_path = test_path.Append(FILE_PATH_LITERAL("ppapi"));
    test_path = test_path.Append(FILE_PATH_LITERAL("tests"));
    test_path = test_path.Append(FILE_PATH_LITERAL("test_case.html"));

    // Sanity check the file name.
    EXPECT_TRUE(file_util::PathExists(test_path));

    GURL::Replacements replacements;
    replacements.SetQuery(test_case.c_str(),
                          url_parse::Component(0, test_case.size()));
    GURL test_url = net::FilePathToFileURL(test_path);
    RunTestURL(test_url.ReplaceComponents(replacements));
  }

  void RunTestViaHTTP(const std::string& test_case) {
    const wchar_t kDocRoot[] = L"third_party/ppapi/tests";
    scoped_refptr<net::HTTPTestServer> server(
        net::HTTPTestServer::CreateServer(kDocRoot));
    ASSERT_TRUE(server);
    RunTestURL(server->TestServerPage("files/test_case.html?" + test_case));
  }

 private:
  void RunTestURL(const GURL& test_url) {
    scoped_refptr<TabProxy> tab(GetActiveTab());
    ASSERT_TRUE(tab.get());
    ASSERT_TRUE(tab->NavigateToURL(test_url));
    std::string escaped_value =
        WaitUntilCookieNonEmpty(tab.get(), test_url,
            "COMPLETION_COOKIE", action_max_timeout_ms());
    EXPECT_STREQ("PASS", escaped_value.c_str());
  }
};

TEST_F(PPAPITest, DeviceContext2D) {
  RunTest("DeviceContext2D");
}

// TODO(brettw) bug 51344: this is flaky on bots. Seems to timeout navigating.
// Possibly all the image allocations slow things down on a loaded bot too much.
TEST_F(PPAPITest, FLAKY_ImageData) {
  RunTest("ImageData");
}

TEST_F(PPAPITest, Buffer) {
  RunTest("Buffer");
}

// TODO(brettw) bug 51345: this failed consistently on one of the bots.
TEST_F(PPAPITest, FAILS_URLLoader) {
  RunTestViaHTTP("URLLoader");
}

// Flaky, http://crbug.com/51012
TEST_F(PPAPITest, FLAKY_PaintAggregator) {
  RunTestViaHTTP("PaintAggregator");
}

#if defined(OS_WIN)
TEST_F(PPAPITest, Scrollbar) {
#else
// Flaky, http://crbug.com/48544.
TEST_F(PPAPITest, FLAKY_Scrollbar) {
#endif
  RunTest("Scrollbar");
}

TEST_F(PPAPITest, UrlUtil) {
  RunTest("UrlUtil");
}
<|endoftext|>


<commit_before><commit_msg>Fix for ui_tests - accidental change went in. TBR=jianli Review URL: http://codereview.chromium.org/150043<commit_after><|endoftext|>


<commit_before>/****************************************************************************
 *
 *   Copyright (C) 2014 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. Neither the name PX4 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.
 *
 ****************************************************************************/

/**
 * @file hardpoint.hpp
 *
 * @author Andreas Jochum <Andreas@NicaDrone.com>
 */

#pragma once

#include <uavcan/uavcan.hpp>
#include <uavcan/equipment/hardpoint/Command.hpp>
#include <uavcan/equipment/hardpoint/Status.hpp>
#include <systemlib/perf_counter.h>

/**
 * @brief The UavcanHardpointController class
 */

class UavcanHardpointController
{
public:
	UavcanHardpointController(uavcan::INode &node);
	~UavcanHardpointController();

	/*
	* setup periodic updater
	*/
	int init();

	/*
	 * set command
	 */
	void set_command(uint8_t hardpoint_id, uint16_t command);

private:
	/*
	 * Max update rate to avoid exessive bus traffic
	 */
	static constexpr unsigned			MAX_RATE_HZ = 1;	///< XXX make this configurable

	uavcan::equipment::hardpoint::Command		_cmd;

	void periodic_update(const uavcan::TimerEvent &);

	typedef uavcan::MethodBinder<UavcanHardpointController *, void (UavcanHardpointController::*)(const uavcan::TimerEvent &)>
	TimerCbBinder;

	pthread_mutex_t					_node_mutex;
	/*
	 * libuavcan related things
	 */
	uavcan::MonotonicTime						_prev_cmd_pub;   ///< rate limiting
	uavcan::INode							&_node;
	uavcan::Publisher<uavcan::equipment::hardpoint::Command>	_uavcan_pub_raw_cmd;
	uavcan::TimerEventForwarder<TimerCbBinder>			_timer;

};
<commit_msg>more cleanup<commit_after>/****************************************************************************
 *
 *   Copyright (C) 2014 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. Neither the name PX4 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.
 *
 ****************************************************************************/

/**
 * @file hardpoint.hpp
 *
 * @author Andreas Jochum <Andreas@NicaDrone.com>
 */

#pragma once

#include <uavcan/uavcan.hpp>
#include <uavcan/equipment/hardpoint/Command.hpp>
#include <uavcan/equipment/hardpoint/Status.hpp>
#include <systemlib/perf_counter.h>

/**
 * @brief The UavcanHardpointController class
 */

class UavcanHardpointController
{
public:
	UavcanHardpointController(uavcan::INode &node);
	~UavcanHardpointController();

	/*
	* setup periodic updater
	*/
	int init();

	/*
	 * set command
	 */
	void set_command(uint8_t hardpoint_id, uint16_t command);

private:
	/*
	 * Max update rate to avoid exessive bus traffic
	 */
	static constexpr unsigned			MAX_RATE_HZ = 1;	///< XXX make this configurable

	uavcan::equipment::hardpoint::Command		_cmd;

	void periodic_update(const uavcan::TimerEvent &);

	typedef uavcan::MethodBinder<UavcanHardpointController *, void (UavcanHardpointController::*)(const uavcan::TimerEvent &)>
	TimerCbBinder;

	pthread_mutex_t					_node_mutex;
	/*
	 * libuavcan related things
	 */
	uavcan::INode							&_node;
	uavcan::Publisher<uavcan::equipment::hardpoint::Command>	_uavcan_pub_raw_cmd;
	uavcan::TimerEventForwarder<TimerCbBinder>			_timer;

};
<|endoftext|>


<commit_before>//*****************************************************************************
// Copyright 2017-2020 Intel Corporation
//
// 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 "ngraph/op/embeddingbag_offsets_sum.hpp"
#include "ngraph/op/constant.hpp"

using namespace std;
using namespace ngraph;

constexpr NodeTypeInfo op::v3::EmbeddingBagOffsetsSum::type_info;

op::v3::EmbeddingBagOffsetsSum::EmbeddingBagOffsetsSum(const Output<Node>& emb_table,
                                                       const Output<Node>& indices,
                                                       const Output<Node>& offsets,
                                                       const Output<Node>& per_sample_weights,
                                                       const Output<Node>& default_index)
    : Op({emb_table, indices, offsets, per_sample_weights, default_index})
{
    constructor_validate_and_infer_types();
}

op::v3::EmbeddingBagOffsetsSum::EmbeddingBagOffsetsSum(const Output<Node>& emb_table,
                                                       const Output<Node>& indices,
                                                       const Output<Node>& offsets,
                                                       const Output<Node>& per_sample_weights)
    : Op({emb_table, indices, offsets, per_sample_weights})
{
    constructor_validate_and_infer_types();
}

op::v3::EmbeddingBagOffsetsSum::EmbeddingBagOffsetsSum(const Output<Node>& emb_table,
                                                       const Output<Node>& indices,
                                                       const Output<Node>& offsets)
    : Op({emb_table, indices, offsets})
{
    constructor_validate_and_infer_types();
}

void op::v3::EmbeddingBagOffsetsSum::validate_and_infer_types()
{
    enum
    {
        EMB_TABLE,
        INDICES,
        OFFSETS,
        PER_SAMPLE_WEIGHTS,
        DEFAULT_INDEX
    };

    NODE_VALIDATION_CHECK(this,
                          get_input_element_type(OFFSETS) == element::i64 ||
                              get_input_element_type(OFFSETS) == element::i32,
                          "OFFSETS type must be i32 or i64");

    NODE_VALIDATION_CHECK(this,
                          get_input_element_type(INDICES) == element::i64 ||
                              get_input_element_type(INDICES) == element::i32,
                          "INDICES type must be i32 or i64");

    NODE_VALIDATION_CHECK(
        this,
        get_input_element_type(INDICES).compatible(get_input_element_type(OFFSETS)),
        "Offsets element type (",
        get_input_element_type(OFFSETS),
        ") must match indices element type (",
        get_input_element_type(INDICES),
        ")");

    NODE_VALIDATION_CHECK(this,
                          get_input_partial_shape(INDICES).is_dynamic() ||
                              get_input_partial_shape(INDICES).to_shape().size() == 1,
                          "INDICES must be 1D");

    NODE_VALIDATION_CHECK(this,
                          get_input_partial_shape(OFFSETS).is_dynamic() ||
                              get_input_partial_shape(OFFSETS).to_shape().size() == 1,
                          "OFFSETS must be 1D");

    if (get_input_size() >= 4)
    {
        NODE_VALIDATION_CHECK(this,
                              get_input_element_type(EMB_TABLE).compatible(
                                  get_input_element_type(PER_SAMPLE_WEIGHTS)),
                              "Per sample weight element type (",
                              get_input_element_type(PER_SAMPLE_WEIGHTS),
                              ") must match embedding table element type (",
                              get_input_element_type(EMB_TABLE),
                              ")");

        NODE_VALIDATION_CHECK(this,
                              get_input_partial_shape(PER_SAMPLE_WEIGHTS).is_dynamic() ||
                                  get_input_partial_shape(PER_SAMPLE_WEIGHTS).to_shape().size() ==
                                      1,
                              "PER_SAMPLE_WEIGHTS must be 1D");

        NODE_VALIDATION_CHECK(this,
                              get_input_partial_shape(INDICES).compatible(
                                  get_input_partial_shape(PER_SAMPLE_WEIGHTS)),
                              "INDICES and PER_SAMPLE_WEIGHTS shape must be same");
    }

    if (get_input_size() == 5)
    {
        NODE_VALIDATION_CHECK(this,
                              get_input_element_type(DEFAULT_INDEX) == element::i64 ||
                                  get_input_element_type(DEFAULT_INDEX) == element::i32,
                              "DEFAULT_INDEX type must be i32 or i64");

        NODE_VALIDATION_CHECK(
            this,
            get_input_element_type(INDICES).compatible(get_input_element_type(DEFAULT_INDEX)),
            "Default_index element type (",
            get_input_element_type(DEFAULT_INDEX),
            ") must match indices element type (",
            get_input_element_type(INDICES),
            ")");

        NODE_VALIDATION_CHECK(this,
                              get_input_partial_shape(DEFAULT_INDEX).compatible(PartialShape{}),
                              "DEFAULT_INDEX must be a scalar");
    }

    element::Type result_et = get_input_element_type(EMB_TABLE);

    const PartialShape& emb_table_shape = get_input_partial_shape(EMB_TABLE);
    const PartialShape& offsets_shape = get_input_partial_shape(OFFSETS);

    PartialShape result_shape;
    if (emb_table_shape.rank().is_static())
    {
        std::vector<Dimension> result_dims(emb_table_shape.rank().get_length());
        result_dims[0] = offsets_shape.rank().is_static() ? offsets_shape[0] : Dimension::dynamic();
        for (size_t i = 1; i < emb_table_shape.rank().get_length(); i++)
        {
            result_dims[i] = emb_table_shape[i];
        }

        result_shape = PartialShape(result_dims);
    }
    else
    {
        result_shape = PartialShape::dynamic();
    }

    set_output_type(0, result_et, result_shape);
}

shared_ptr<Node>
    op::v3::EmbeddingBagOffsetsSum::clone_with_new_inputs(const OutputVector& new_args) const
{
    if (new_args.size() == 3)
    {
        return make_shared<EmbeddingBagOffsetsSum>(new_args.at(0), new_args.at(1), new_args.at(2));
    }
    else if (new_args.size() == 4)
    {
        return make_shared<EmbeddingBagOffsetsSum>(
            new_args.at(0), new_args.at(1), new_args.at(2), new_args.at(3));
    }
    else
    {
        return make_shared<EmbeddingBagOffsetsSum>(
            new_args.at(0), new_args.at(1), new_args.at(2), new_args.at(3), new_args.at(4));
    }
}
<commit_msg>Add checks<commit_after>//*****************************************************************************
// Copyright 2017-2020 Intel Corporation
//
// 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 "ngraph/op/embeddingbag_offsets_sum.hpp"
#include "ngraph/op/constant.hpp"

using namespace std;
using namespace ngraph;

constexpr NodeTypeInfo op::v3::EmbeddingBagOffsetsSum::type_info;

op::v3::EmbeddingBagOffsetsSum::EmbeddingBagOffsetsSum(const Output<Node>& emb_table,
                                                       const Output<Node>& indices,
                                                       const Output<Node>& offsets,
                                                       const Output<Node>& per_sample_weights,
                                                       const Output<Node>& default_index)
    : Op({emb_table, indices, offsets, per_sample_weights, default_index})
{
    constructor_validate_and_infer_types();
}

op::v3::EmbeddingBagOffsetsSum::EmbeddingBagOffsetsSum(const Output<Node>& emb_table,
                                                       const Output<Node>& indices,
                                                       const Output<Node>& offsets,
                                                       const Output<Node>& per_sample_weights)
    : Op({emb_table, indices, offsets, per_sample_weights})
{
    constructor_validate_and_infer_types();
}

op::v3::EmbeddingBagOffsetsSum::EmbeddingBagOffsetsSum(const Output<Node>& emb_table,
                                                       const Output<Node>& indices,
                                                       const Output<Node>& offsets)
    : Op({emb_table, indices, offsets})
{
    constructor_validate_and_infer_types();
}

void op::v3::EmbeddingBagOffsetsSum::validate_and_infer_types()
{
    enum
    {
        EMB_TABLE,
        INDICES,
        OFFSETS,
        PER_SAMPLE_WEIGHTS,
        DEFAULT_INDEX
    };

    NODE_VALIDATION_CHECK(this,
                          get_input_element_type(OFFSETS) == element::i64 ||
                              get_input_element_type(OFFSETS) == element::i32,
                          "OFFSETS type must be i32 or i64");

    NODE_VALIDATION_CHECK(this,
                          get_input_element_type(INDICES) == element::i64 ||
                              get_input_element_type(INDICES) == element::i32,
                          "INDICES type must be i32 or i64");

    NODE_VALIDATION_CHECK(
        this,
        get_input_element_type(INDICES).compatible(get_input_element_type(OFFSETS)),
        "Offsets element type (",
        get_input_element_type(OFFSETS),
        ") must match indices element type (",
        get_input_element_type(INDICES),
        ")");

    NODE_VALIDATION_CHECK(this,
                          get_input_partial_shape(INDICES).is_dynamic() ||
                              get_input_partial_shape(INDICES).to_shape().size() == 1,
                          "INDICES must be 1D");

    NODE_VALIDATION_CHECK(this,
                          get_input_partial_shape(OFFSETS).is_dynamic() ||
                              get_input_partial_shape(OFFSETS).to_shape().size() == 1,
                          "OFFSETS must be 1D");

    if (get_input_size() >= 4)
    {
        NODE_VALIDATION_CHECK(this,
                              get_input_element_type(EMB_TABLE).compatible(
                                  get_input_element_type(PER_SAMPLE_WEIGHTS)),
                              "Per sample weight element type (",
                              get_input_element_type(PER_SAMPLE_WEIGHTS),
                              ") must match embedding table element type (",
                              get_input_element_type(EMB_TABLE),
                              ")");

        NODE_VALIDATION_CHECK(this,
                              get_input_partial_shape(PER_SAMPLE_WEIGHTS).is_dynamic() ||
                                  get_input_partial_shape(PER_SAMPLE_WEIGHTS).to_shape().size() ==
                                      1,
                              "PER_SAMPLE_WEIGHTS must be 1D");

        NODE_VALIDATION_CHECK(this,
                              get_input_partial_shape(INDICES).compatible(
                                  get_input_partial_shape(PER_SAMPLE_WEIGHTS)),
                              "INDICES and PER_SAMPLE_WEIGHTS shape must be same");
    }

    if (get_input_size() == 5)
    {
        NODE_VALIDATION_CHECK(this,
                              get_input_element_type(DEFAULT_INDEX) == element::i64 ||
                                  get_input_element_type(DEFAULT_INDEX) == element::i32,
                              "DEFAULT_INDEX type must be i32 or i64");

        NODE_VALIDATION_CHECK(
            this,
            get_input_element_type(INDICES).compatible(get_input_element_type(DEFAULT_INDEX)),
            "Default_index element type (",
            get_input_element_type(DEFAULT_INDEX),
            ") must match indices element type (",
            get_input_element_type(INDICES),
            ")");

        NODE_VALIDATION_CHECK(this,
                              get_input_partial_shape(DEFAULT_INDEX).compatible(PartialShape{}),
                              "DEFAULT_INDEX must be a scalar");
    }

    element::Type result_et = get_input_element_type(EMB_TABLE);

    const PartialShape& emb_table_shape = get_input_partial_shape(EMB_TABLE);
    const PartialShape& offsets_shape = get_input_partial_shape(OFFSETS);

    PartialShape result_shape;
    if (emb_table_shape.rank().is_static())
    {
        std::vector<Dimension> result_dims(emb_table_shape.rank().get_length());
        result_dims[0] = offsets_shape.rank().is_static() ? offsets_shape[0] : Dimension::dynamic();
        for (size_t i = 1; i < emb_table_shape.rank().get_length(); i++)
        {
            result_dims[i] = emb_table_shape[i];
        }

        result_shape = PartialShape(result_dims);
    }
    else
    {
        result_shape = PartialShape::dynamic();
    }

    set_output_type(0, result_et, result_shape);
}

shared_ptr<Node>
    op::v3::EmbeddingBagOffsetsSum::clone_with_new_inputs(const OutputVector& new_args) const
{
    check_new_args_count(this, new_args);
    if (new_args.size() == 3)
    {
        return make_shared<EmbeddingBagOffsetsSum>(new_args.at(0), new_args.at(1), new_args.at(2));
    }
    else if (new_args.size() == 4)
    {
        return make_shared<EmbeddingBagOffsetsSum>(
            new_args.at(0), new_args.at(1), new_args.at(2), new_args.at(3));
    }
    else if (new_args.size() == 5)
    {
        return make_shared<EmbeddingBagOffsetsSum>(
            new_args.at(0), new_args.at(1), new_args.at(2), new_args.at(3), new_args.at(4));
    }
    else
    {
        throw ngraph_error("Incorrect number of arguments");
    }
}
<|endoftext|>


<commit_before>// .transaction(Array sqls) -> Transaction

NAN_METHOD(Database::CreateTransaction) {
	REQUIRE_ARGUMENT_ARRAY(0, sources);

	Database* db = Nan::ObjectWrap::Unwrap<Database>(info.This());
	if (!db->open) {
		return Nan::ThrowTypeError("The database connection is not open");
	}
	if (db->busy) {
		return Nan::ThrowTypeError("This database connection is busy executing a query");
	}
	if (db->readonly) {
		return Nan::ThrowTypeError("This operation is not available while in readonly mode");
	}

	unsigned int len = sources->Length();
	if (!(len > 0)) {
		return Nan::ThrowRangeError("No SQL statements were provided");
	}
	if (len > max_transaction_length) {
		return Nan::ThrowRangeError("Too many SQL statements were provided");
	}
	v8::Local<v8::Array> digestedSources = Nan::New<v8::Array>(len);

	// Validate and digest source strings.
	v8::Local<v8::String> semicolon = Nan::New(";").ToLocalChecked();
	for (unsigned int i=0; i<len; ++i) {
		Nan::MaybeLocal<v8::Value> maybeValue = Nan::Get(sources, i);
		if (maybeValue.IsEmpty()) {
			return;
		}
		v8::Local<v8::Value> value = maybeValue.ToLocalChecked();
		if (!value->IsString()) {
			return Nan::ThrowTypeError("Expected each item in the given array to be a string");
		}
		v8::Local<v8::String> source = v8::Local<v8::String>::Cast(value);
		v8::String::Value utf16(source);
		uint16_t last_char = (*utf16)[utf16.length() - 1];
		if (last_char != 0x3b) {
			source = v8::String::Concat(source, semicolon);
		}
		Nan::Set(digestedSources, i, source);
	}

	// Create joined source string.
	v8::Local<v8::Value> joinArgs[1] = {Nan::New("\n").ToLocalChecked()};
	INVOKE_METHOD(joinedSource, digestedSources, "join", 1, joinArgs)
	if (!joinedSource->IsString()) {
		return Nan::ThrowTypeError("Expected Array.prototype.join to return a string");
	}

	CONSTRUCTING_PRIVILEGES = true;
	v8::Local<v8::Function> cons = Nan::New<v8::Function>(Transaction::constructor);
	v8::Local<v8::Object> transaction = Nan::NewInstance(cons).ToLocalChecked();
	CONSTRUCTING_PRIVILEGES = false;
	Transaction* trans = Nan::ObjectWrap::Unwrap<Transaction>(transaction);

	// Initializes C++ object properties.
	trans->db = db;
	trans->handle_count = len;
	trans->handles = new sqlite3_stmt* [len]();

	// Create statement handles from each source string.
	for (unsigned int i=0; i<len; ++i) {
		v8::Local<v8::String> source = v8::Local<v8::String>::Cast(Nan::Get(digestedSources, i).ToLocalChecked());
		v8::String::Value utf16(source);
		const void* tail;

		int status = sqlite3_prepare16_v2(db->db_handle, *utf16, utf16.length() * sizeof (uint16_t) + 1, &(trans->handles[i]), &tail);

		// Validates the newly created statement.
		if (status != SQLITE_OK) {
			CONCAT3(message, "Failed to construct SQL statement (", sqlite3_errmsg(db->db_handle), ")");
			return Nan::ThrowError(message.c_str());
		}
		if (trans->handles[i] == NULL) {
			return Nan::ThrowTypeError("One of the supplied SQL strings contains no statements");
		}
		if (tail != (const void*)(*utf16 + utf16.length())) {
			return Nan::ThrowRangeError("Each provided string may only contain a single SQL statement");
		}
		if (sqlite3_stmt_readonly(trans->handles[i])) {
			return Nan::ThrowTypeError("Transactions cannot contain read-only statements");
		}
	}
	Nan::ForceSet(transaction, NEW_INTERNAL_STRING_FAST("source"), joinedSource, FROZEN);
	Nan::ForceSet(transaction, NEW_INTERNAL_STRING_FAST("database"), info.This(), FROZEN);
	if (db->safe_ints) {trans->state |= SAFE_INTS;}

	// Pushes onto transs set.
	trans->extras->id = NEXT_TRANSACTION_ID++;
	db->transs.insert(db->transs.end(), trans);

	info.GetReturnValue().Set(transaction);
}
<commit_msg>semicolon<commit_after>// .transaction(Array sqls) -> Transaction

NAN_METHOD(Database::CreateTransaction) {
	REQUIRE_ARGUMENT_ARRAY(0, sources);

	Database* db = Nan::ObjectWrap::Unwrap<Database>(info.This());
	if (!db->open) {
		return Nan::ThrowTypeError("The database connection is not open");
	}
	if (db->busy) {
		return Nan::ThrowTypeError("This database connection is busy executing a query");
	}
	if (db->readonly) {
		return Nan::ThrowTypeError("This operation is not available while in readonly mode");
	}

	unsigned int len = sources->Length();
	if (!(len > 0)) {
		return Nan::ThrowRangeError("No SQL statements were provided");
	}
	if (len > max_transaction_length) {
		return Nan::ThrowRangeError("Too many SQL statements were provided");
	}
	v8::Local<v8::Array> digestedSources = Nan::New<v8::Array>(len);

	// Validate and digest source strings.
	v8::Local<v8::String> semicolon = Nan::New(";").ToLocalChecked();
	for (unsigned int i=0; i<len; ++i) {
		Nan::MaybeLocal<v8::Value> maybeValue = Nan::Get(sources, i);
		if (maybeValue.IsEmpty()) {
			return;
		}
		v8::Local<v8::Value> value = maybeValue.ToLocalChecked();
		if (!value->IsString()) {
			return Nan::ThrowTypeError("Expected each item in the given array to be a string");
		}
		v8::Local<v8::String> source = v8::Local<v8::String>::Cast(value);
		v8::String::Value utf16(source);
		uint16_t last_char = (*utf16)[utf16.length() - 1];
		if (last_char != 0x3b) {
			source = v8::String::Concat(source, semicolon);
		}
		Nan::Set(digestedSources, i, source);
	}

	// Create joined source string.
	v8::Local<v8::Value> joinArgs[1] = {Nan::New("\n").ToLocalChecked()};
	INVOKE_METHOD(joinedSource, digestedSources, "join", 1, joinArgs);
	if (!joinedSource->IsString()) {
		return Nan::ThrowTypeError("Expected Array.prototype.join to return a string");
	}

	CONSTRUCTING_PRIVILEGES = true;
	v8::Local<v8::Function> cons = Nan::New<v8::Function>(Transaction::constructor);
	v8::Local<v8::Object> transaction = Nan::NewInstance(cons).ToLocalChecked();
	CONSTRUCTING_PRIVILEGES = false;
	Transaction* trans = Nan::ObjectWrap::Unwrap<Transaction>(transaction);

	// Initializes C++ object properties.
	trans->db = db;
	trans->handle_count = len;
	trans->handles = new sqlite3_stmt* [len]();

	// Create statement handles from each source string.
	for (unsigned int i=0; i<len; ++i) {
		v8::Local<v8::String> source = v8::Local<v8::String>::Cast(Nan::Get(digestedSources, i).ToLocalChecked());
		v8::String::Value utf16(source);
		const void* tail;

		int status = sqlite3_prepare16_v2(db->db_handle, *utf16, utf16.length() * sizeof (uint16_t) + 1, &(trans->handles[i]), &tail);

		// Validates the newly created statement.
		if (status != SQLITE_OK) {
			CONCAT3(message, "Failed to construct SQL statement (", sqlite3_errmsg(db->db_handle), ")");
			return Nan::ThrowError(message.c_str());
		}
		if (trans->handles[i] == NULL) {
			return Nan::ThrowTypeError("One of the supplied SQL strings contains no statements");
		}
		if (tail != (const void*)(*utf16 + utf16.length())) {
			return Nan::ThrowRangeError("Each provided string may only contain a single SQL statement");
		}
		if (sqlite3_stmt_readonly(trans->handles[i])) {
			return Nan::ThrowTypeError("Transactions cannot contain read-only statements");
		}
	}
	Nan::ForceSet(transaction, NEW_INTERNAL_STRING_FAST("source"), joinedSource, FROZEN);
	Nan::ForceSet(transaction, NEW_INTERNAL_STRING_FAST("database"), info.This(), FROZEN);
	if (db->safe_ints) {trans->state |= SAFE_INTS;}

	// Pushes onto transs set.
	trans->extras->id = NEXT_TRANSACTION_ID++;
	db->transs.insert(db->transs.end(), trans);

	info.GetReturnValue().Set(transaction);
}
<|endoftext|>


<commit_before>#include <stdarg.h>
#include <stdio.h>

#ifndef va_copy
#  ifdef __va_copy
#    define va_copy __va_copy
#  else
#    define va_copy(dst, src) memcpy(&dst, &src, sizeof(va_list))
#  endif
#endif

#include "string_buf.hpp"

  // reserve space for at least s+1 characters
  void StringBuf::reserve_i(size_t s)
  {
    size_t old_size = end_ - begin_;
    size_t new_size = (storage_end_ - begin_) * 3 / 2;
    if (new_size < 60) new_size = 60;
    if (new_size < s + 1) new_size = s + 1;
    if (old_size == 0) {
      if (d) GC_FREE(d);
      d = (StringObj *)GC_MALLOC_ATOMIC(sizeof(StringObj) + new_size);
    } else {
      StringObj * d2 = (StringObj *)GC_MALLOC_ATOMIC(sizeof(StringObj) + new_size);
      memcpy(d2->str, d->str, old_size);
      GC_FREE(d);
      d = d2;
    }
    begin_ = d->str;
    d->size = 0;
    end_ = begin_ + old_size;
    storage_end_ = begin_ + new_size;
  }

  int StringBuf::vprintf(const char * format, va_list ap0)
  {
    reserve(size() + 64);
    int res = 0;
    va_list ap;
  loop: {
      int avail = storage_end_ - end_;
      if (res < 0 && avail > 1024*1024)
        return -1; // to avoid an infinite loop in case a neg result
                   // really means an error and not just "not enough
                   // space"
      va_copy(ap,ap0);
      res = vsnprintf(end_, avail, format, ap);
      va_end(ap);
      if (res < 0) {
        reserve_i(); goto loop;
      } else if (res > avail) {
        reserve_i(size() + res); goto loop;
      }
    }
    end_ += res;
    return res;
  }

  bool StringIStream::append_line(StringBuf & str, char d)
  {
    if (in_str[0] == '\0') return false;
    const char * end = in_str;
    while (*end != d && *end != '\0') ++end;
    str.append(in_str, end - in_str);
    in_str = end;
    if (*in_str == d) ++in_str;
    return true;
  }

  bool StringIStream::read(void * data, unsigned int size)
  {
    char * str = static_cast<char *>(data);
    while (*in_str != '\0' && size != 0) {
      *str = *in_str;
      ++in_str;
      ++str;
      ++size;
    }
    return size == 0;
  }

<commit_msg>Bug fix.  Leave room for space in vprintf.<commit_after>#include <stdarg.h>
#include <stdio.h>

#ifndef va_copy
#  ifdef __va_copy
#    define va_copy __va_copy
#  else
#    define va_copy(dst, src) memcpy(&dst, &src, sizeof(va_list))
#  endif
#endif

#include "string_buf.hpp"

  // reserve space for at least s+1 characters
  void StringBuf::reserve_i(size_t s)
  {
    size_t old_size = end_ - begin_;
    size_t new_size = (storage_end_ - begin_) * 3 / 2;
    if (new_size < 60) new_size = 60;
    if (new_size < s + 1) new_size = s + 1;
    if (old_size == 0) {
      if (d) GC_FREE(d);
      d = (StringObj *)GC_MALLOC_ATOMIC(sizeof(StringObj) + new_size);
    } else {
      StringObj * d2 = (StringObj *)GC_MALLOC_ATOMIC(sizeof(StringObj) + new_size);
      memcpy(d2->str, d->str, old_size);
      GC_FREE(d);
      d = d2;
    }
    begin_ = d->str;
    d->size = 0;
    end_ = begin_ + old_size;
    storage_end_ = begin_ + new_size;
  }

  int StringBuf::vprintf(const char * format, va_list ap0)
  {
    reserve(size() + 64);
    int res = 0;
    va_list ap;
  loop: {
      int avail = storage_end_ - end_ - 1;
      if (res < 0 && avail > 1024*1024)
        return -1; // to avoid an infinite loop in case a neg result
                   // really means an error and not just "not enough
                   // space"
      va_copy(ap,ap0);
      res = vsnprintf(end_, avail, format, ap);
      va_end(ap);
      if (res < 0) {
        reserve_i(); goto loop;
      } else if (res > avail) {
        reserve_i(size() + res); goto loop;
      }
    }
    end_ += res;
    return res;
  }

  bool StringIStream::append_line(StringBuf & str, char d)
  {
    if (in_str[0] == '\0') return false;
    const char * end = in_str;
    while (*end != d && *end != '\0') ++end;
    str.append(in_str, end - in_str);
    in_str = end;
    if (*in_str == d) ++in_str;
    return true;
  }

  bool StringIStream::read(void * data, unsigned int size)
  {
    char * str = static_cast<char *>(data);
    while (*in_str != '\0' && size != 0) {
      *str = *in_str;
      ++in_str;
      ++str;
      ++size;
    }
    return size == 0;
  }

<|endoftext|>


<commit_before>#include <new>
#include <typeinfo>
#include <string>
#include <list>
#include <map>

#include <cstdarg>
#include <cstdlib>
#include <cstdio>
#include <cerrno>
#include <ctime>

#include "Server.hpp"
<commit_msg>Update Engine.hpp<commit_after>#include <new>
#include <typeinfo>
#include <string>
#include <list>
#include <map>

#include <cstdarg>
#include <cstdlib>
#include <cstdio>
#include <cerrno>
#include <ctime>

#include "Server.hpp"
#include "Prototypes.hpp"
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkOBJReader.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-2000 Ken Martin, Will Schroeder, Bill Lorensen
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 name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
   of any contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

 * Modified source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

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 REGENTS 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 "vtkOBJReader.h"
#include "vtkObjectFactory.h"

//------------------------------------------------------------------------------
vtkOBJReader* vtkOBJReader::New()
{
  // First try to create the object from the vtkObjectFactory
  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkOBJReader");
  if(ret)
    {
    return (vtkOBJReader*)ret;
    }
  // If the factory was unable to create the object, then create it here.
  return new vtkOBJReader;
}

// Description:
// Instantiate object with NULL filename.
vtkOBJReader::vtkOBJReader()
{
  this->FileName = NULL;
}

vtkOBJReader::~vtkOBJReader()
{
  if (this->FileName)
    {
    delete [] this->FileName;
    this->FileName = NULL;
    }
}

void vtkOBJReader::Execute()
{
  FILE *fptr;
  char line[1024];
  vtkPoints *objPts;
  vtkNormals *objNormals;
  vtkTCoords *objTCoords;
  vtkPoints *pts;
  vtkNormals *normals;
  vtkTCoords *tcoords;
  vtkCellArray *polys;
  float xyz[3], n[3], tc[3];
  vtkPolyData *output = this->GetOutput();
  vtkPointData *outputPD = output->GetPointData();
  int count;
  int ptId;
  int numberOfPts, numberOfNormals, numberOfTCoords;
  int objPtId, objNormalId, objTCoordId;
  char *slash, *blank, *next, *ptr;

  vtkDebugMacro(<<"Reading file");

  if (!this->FileName)
    {
    vtkErrorMacro(<< "A FileName must be specified.");
    return;
    }

  // Initialize
  if ((fptr = fopen(this->FileName, "r")) == NULL)
    {
    vtkErrorMacro(<< "File " << this->FileName << " not found");
    return;
    }

  // allocate points and point data to hold obj input
  objPts = vtkPoints::New();
  objPts->Allocate(1000,5000);

  objNormals = vtkNormals::New();
  objNormals->Allocate(1000,5000);

  objTCoords = vtkTCoords::New();
  objTCoords->SetNumberOfComponents(2);
  objTCoords->Allocate(1000,5000);

  polys = vtkCellArray::New();
  polys->Allocate(1000,5000);

  // parse file twice... first time to get point data and then cells
  while (fgets (line, 1024, fptr))
    {
    if (strncmp (line, "v ", 2) == 0)
      {
      sscanf (line, "%*[^ ]%f %f %f", xyz, xyz + 1, xyz + 2);
      objPts->InsertNextPoint(xyz);
      }
    else if (strncmp (line, "vt", 2) == 0)
      {
      sscanf (line, "%*[^ ]%f %f %f", tc, tc + 1, tc + 2);
      objTCoords->InsertNextTCoord(tc);
      }
    else if (strncmp (line, "vn", 2) == 0)
      {
      sscanf (line, "%*[^ ]%f %f %f", n, n + 1, n + 2);
      objNormals->InsertNextNormal(n);
      }
    }

  // allocate points and point data for vtk polydata
  pts = vtkPoints::New();
  numberOfPts = objPts->GetNumberOfPoints();
  pts->Allocate(numberOfPts, numberOfPts);

  numberOfNormals = objNormals->GetNumberOfNormals ();
  if (numberOfNormals > 0)
    {
    normals = vtkNormals::New();
    normals->Allocate(numberOfPts, numberOfPts);
    }
  else
    {
    normals = NULL;
    }

  numberOfTCoords = objTCoords->GetNumberOfTCoords ();
  if (numberOfTCoords > 0)
    {
    tcoords = vtkTCoords::New();
    tcoords->SetNumberOfComponents(2);
    tcoords->Allocate(numberOfPts, numberOfPts);
    }
  else
    {
    tcoords = NULL;
    }

  ptId = 0;
  rewind (fptr);
  while (fgets (line, 1024, fptr))
    {
    if ( strncmp(line, "f ", 2) == 0 || strncmp(line, "fo", 2) == 0)
      {
      count = 0;
      polys->InsertNextCell(0);
      ptr = line;
      while ((ptr = (char *) strchr (ptr, (int) ' ')))
        {
        while (*ptr == ' ')
	  {
	  ptr++;
	  }
        if ( sscanf(ptr, "%d", &objPtId) == 1 )
          {
          polys->InsertCellPoint(ptId++);
	  pts->InsertNextPoint (objPts->GetPoint (objPtId-1));
          count++;
	  objNormalId = -1;
	  objTCoordId = -1;
          if ((next = (char *) strchr (ptr, (int) '/')))
            {
            ptr = next + 1;
            if (*ptr == '/')
              {
              sscanf (ptr + 1, "%d", &objNormalId);
              }
            else
              {
              sscanf (ptr, "%d", &objTCoordId);
              blank = (char *) strchr (line, (int) ' ');
              slash = (char *) strchr (line, (int) '/');
              if (blank && slash && (slash < blank))
                {
                ptr = slash + 1;
                sscanf (ptr, "%d", &objNormalId);
                }
              }
            }
	  if (normals && objNormalId != -1)
	    {
	    normals->InsertNextNormal (objNormals->GetNormal (objNormalId - 1));
	    }
	  if (tcoords && objTCoordId != -1)
	    {
	    tcoords->InsertNextTCoord (objTCoords->GetTCoord (objTCoordId - 1));
	    }
          }
        }
      polys->UpdateCellCount(count);
      }
    }

  // close the file
  fclose (fptr);

  // delete the obj points, normals and tcoords
  objPts->Delete();
  objNormals->Delete();
  objTCoords->Delete();

  output->SetPoints (pts);
  pts->Delete ();

  // update output
  if (normals)
    {
    if ( normals->GetNumberOfNormals() > 0 )
      {
      outputPD->SetNormals(normals);
      }
    normals->Delete();
    }

  if (tcoords)
    {
    if ( tcoords->GetNumberOfTCoords() > 0 )
      {
      outputPD->SetTCoords(tcoords);
      }
    tcoords->Delete();
    }

  output->SetPolys(polys);
  polys->Delete();

  output->Squeeze();
}

void vtkOBJReader::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkPolyDataSource::PrintSelf(os,indent);

  os << indent << "File Name: "
     << (this->FileName ? this->FileName : "(none)") << "\n";

}
<commit_msg>ERR: Reported by John Tourtellott <johnt@raytechcomputing.com> At 09:36 AM 10/31/00 -0500, John Tourtellott wrote: I believe that the vtkOBJReader class never reads vertex normals from an input file, due to a bug in vtkOBJReader.cxx at lines 208-209:<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkOBJReader.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-2000 Ken Martin, Will Schroeder, Bill Lorensen
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 name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
   of any contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

 * Modified source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

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 REGENTS 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 "vtkOBJReader.h"
#include "vtkObjectFactory.h"

//------------------------------------------------------------------------------
vtkOBJReader* vtkOBJReader::New()
{
  // First try to create the object from the vtkObjectFactory
  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkOBJReader");
  if(ret)
    {
    return (vtkOBJReader*)ret;
    }
  // If the factory was unable to create the object, then create it here.
  return new vtkOBJReader;
}

// Description:
// Instantiate object with NULL filename.
vtkOBJReader::vtkOBJReader()
{
  this->FileName = NULL;
}

vtkOBJReader::~vtkOBJReader()
{
  if (this->FileName)
    {
    delete [] this->FileName;
    this->FileName = NULL;
    }
}

void vtkOBJReader::Execute()
{
  FILE *fptr;
  char line[1024];
  vtkPoints *objPts;
  vtkNormals *objNormals;
  vtkTCoords *objTCoords;
  vtkPoints *pts;
  vtkNormals *normals;
  vtkTCoords *tcoords;
  vtkCellArray *polys;
  float xyz[3], n[3], tc[3];
  vtkPolyData *output = this->GetOutput();
  vtkPointData *outputPD = output->GetPointData();
  int count;
  int ptId;
  int numberOfPts, numberOfNormals, numberOfTCoords;
  int objPtId, objNormalId, objTCoordId;
  char *slash, *blank, *next, *ptr;

  vtkDebugMacro(<<"Reading file");

  if (!this->FileName)
    {
    vtkErrorMacro(<< "A FileName must be specified.");
    return;
    }

  // Initialize
  if ((fptr = fopen(this->FileName, "r")) == NULL)
    {
    vtkErrorMacro(<< "File " << this->FileName << " not found");
    return;
    }

  // allocate points and point data to hold obj input
  objPts = vtkPoints::New();
  objPts->Allocate(1000,5000);

  objNormals = vtkNormals::New();
  objNormals->Allocate(1000,5000);

  objTCoords = vtkTCoords::New();
  objTCoords->SetNumberOfComponents(2);
  objTCoords->Allocate(1000,5000);

  polys = vtkCellArray::New();
  polys->Allocate(1000,5000);

  // parse file twice... first time to get point data and then cells
  while (fgets (line, 1024, fptr))
    {
    if (strncmp (line, "v ", 2) == 0)
      {
      sscanf (line, "%*[^ ]%f %f %f", xyz, xyz + 1, xyz + 2);
      objPts->InsertNextPoint(xyz);
      }
    else if (strncmp (line, "vt", 2) == 0)
      {
      sscanf (line, "%*[^ ]%f %f %f", tc, tc + 1, tc + 2);
      objTCoords->InsertNextTCoord(tc);
      }
    else if (strncmp (line, "vn", 2) == 0)
      {
      sscanf (line, "%*[^ ]%f %f %f", n, n + 1, n + 2);
      objNormals->InsertNextNormal(n);
      }
    }

  // allocate points and point data for vtk polydata
  pts = vtkPoints::New();
  numberOfPts = objPts->GetNumberOfPoints();
  pts->Allocate(numberOfPts, numberOfPts);

  numberOfNormals = objNormals->GetNumberOfNormals ();
  if (numberOfNormals > 0)
    {
    normals = vtkNormals::New();
    normals->Allocate(numberOfPts, numberOfPts);
    }
  else
    {
    normals = NULL;
    }

  numberOfTCoords = objTCoords->GetNumberOfTCoords ();
  if (numberOfTCoords > 0)
    {
    tcoords = vtkTCoords::New();
    tcoords->SetNumberOfComponents(2);
    tcoords->Allocate(numberOfPts, numberOfPts);
    }
  else
    {
    tcoords = NULL;
    }

  ptId = 0;
  rewind (fptr);
  while (fgets (line, 1024, fptr))
    {
    if ( strncmp(line, "f ", 2) == 0 || strncmp(line, "fo", 2) == 0)
      {
      count = 0;
      polys->InsertNextCell(0);
      ptr = line;
      while ((ptr = (char *) strchr (ptr, (int) ' ')))
        {
        while (*ptr == ' ')
	  {
	  ptr++;
	  }
        if ( sscanf(ptr, "%d", &objPtId) == 1 )
          {
          polys->InsertCellPoint(ptId++);
	  pts->InsertNextPoint (objPts->GetPoint (objPtId-1));
          count++;
	  objNormalId = -1;
	  objTCoordId = -1;
          if ((next = (char *) strchr (ptr, (int) '/')))
            {
            ptr = next + 1;
            if (*ptr == '/')
              {
              sscanf (ptr + 1, "%d", &objNormalId);
              }
            else
              {
              sscanf (ptr, "%d", &objTCoordId);
              blank = (char *) strchr (ptr, (int) ' ');
              slash = (char *) strchr (ptr, (int) '/');
              if (blank && slash && (slash < blank))
                {
                ptr = slash + 1;
                sscanf (ptr, "%d", &objNormalId);
                }
              }
            }
	  if (normals && objNormalId != -1)
	    {
	    normals->InsertNextNormal (objNormals->GetNormal (objNormalId - 1));
	    }
	  if (tcoords && objTCoordId != -1)
	    {
	    tcoords->InsertNextTCoord (objTCoords->GetTCoord (objTCoordId - 1));
	    }
          }
        }
      polys->UpdateCellCount(count);
      }
    }

  // close the file
  fclose (fptr);

  // delete the obj points, normals and tcoords
  objPts->Delete();
  objNormals->Delete();
  objTCoords->Delete();

  output->SetPoints (pts);
  pts->Delete ();

  // update output
  if (normals)
    {
    if ( normals->GetNumberOfNormals() > 0 )
      {
      outputPD->SetNormals(normals);
      }
    normals->Delete();
    }

  if (tcoords)
    {
    if ( tcoords->GetNumberOfTCoords() > 0 )
      {
      outputPD->SetTCoords(tcoords);
      }
    tcoords->Delete();
    }

  output->SetPolys(polys);
  polys->Delete();

  output->Squeeze();
}

void vtkOBJReader::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkPolyDataSource::PrintSelf(os,indent);

  os << indent << "File Name: "
     << (this->FileName ? this->FileName : "(none)") << "\n";

}
<|endoftext|>


<commit_before>/* $Id$ */
/* --------------------------------------------------------------------------
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell

CppAD is distributed under multiple licenses. This distribution is under
the terms of the
                    Common Public License Version 1.0.

A copy of this license is included in the COPYING file of this distribution.
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
-------------------------------------------------------------------------- */

# include <cppad/cppad.hpp>
# include <omp.h>

# define NUMBER_THREADS     4
# define NUMBER_CALLS       40

// y[0] = x[0] + x[1]
// y[1] = x[1] + x[2]
namespace {
	// ------------------------------------------------------------------
	// used to inform CppAD when we are in parallel execution mode
	bool in_parallel(void)
	{	return static_cast<bool>( omp_in_parallel() ); }
	// ------------------------------------------------------------------
	// used to inform CppAD of the current thread number
	size_t thread_number(void)
	{	return static_cast<size_t>( omp_get_thread_num() ); }

	// y[0] = x[0] + x[1]
	bool user_atomic_forward(
		size_t                         id ,
		size_t                          k ,
		size_t                          n ,
		size_t                          m ,
		const CppAD::vector<bool>&     vx ,
		CppAD::vector<bool>&           vy ,
		const CppAD::vector<double>&   tx ,
		CppAD::vector<double>&         ty )
	{	assert(n >= 3 && m == 2);
		if( k > 0 )
			return false;

		ty[0] = tx[0] + tx[1];
		ty[1] = tx[1] + tx[2];

		if( vy.size() > 0 )
		{	vy[0] = (vx[0] | vx[1]);
			vy[1] = (vx[1] | vx[2]);
		}
		return true;
	}

	bool user_atomic_reverse(
		size_t                         id ,
		size_t                          k ,
		size_t                          n ,
		size_t                          m ,
		const CppAD::vector<double>&   tx ,
		const CppAD::vector<double>&   ty ,
		CppAD::vector<double>&         px ,
		const CppAD::vector<double>&   py )
	{	return false; }

	bool user_atomic_for_jac_sparse(
		size_t                                  id ,
		size_t                                   n ,
		size_t                                   m ,
		size_t                                   q ,
		const CppAD::vector< std::set<size_t> >& r ,
		CppAD::vector< std::set<size_t>  >&      s )
	{	return false; }

	bool user_atomic_rev_jac_sparse(
		size_t                                  id ,
		size_t                                   n ,
		size_t                                   m ,
		size_t                                   q ,
		CppAD::vector< std::set<size_t> >&       r ,
		const CppAD::vector< std::set<size_t> >& s )
	{	return false; }

	bool user_atomic_rev_hes_sparse(
		size_t                                  id ,
		size_t                                   n ,
		size_t                                   m ,
		size_t                                   q ,
		const CppAD::vector< std::set<size_t> >& r ,
		const CppAD::vector<bool>&               s ,
		CppAD::vector<bool>&                     t ,
		const CppAD::vector< std::set<size_t> >& u ,
		CppAD::vector< std::set<size_t> >&       v )
	{	return false; }

	CPPAD_USER_ATOMIC(
		my_user_atomic             ,
		CppAD::vector              ,
		double                     ,
		user_atomic_forward        ,
		user_atomic_reverse        ,
		user_atomic_for_jac_sparse ,
		user_atomic_rev_jac_sparse ,
		user_atomic_rev_hes_sparse
	)

	bool user_atomic(int call_index)
	{	bool ok = true;
		using CppAD::AD;
		using CppAD::vector;

		size_t j;
		size_t m = 2;
		size_t n = size_t(call_index + 3);
		vector< AD<double> > ax(n), ay(m);
		for(j = 0; j < n; j++)
			ax[j] = AD<double>(j + 1);
		CppAD::Independent(ax);

		// use user atomic function
		size_t id = 0;
		my_user_atomic(id, ax, ay);

		// create function
		CppAD::ADFun<double> g(ax, ay);

		// now use the tape with the user atomic function
		vector<double> x(n), y(m);
		for(j = 0; j < n; j++)
			x[j] = (j + 1) * (j + 1);
		y = g.Forward(0, x);
		// y[0] = x[0] + x[1]
		ok &= (y[0] == x[0] + x[1]);
		// y[1] = x[1] + x[2]
		ok &= (y[0] == x[0] + x[1]);

		return ok;
	}
}

# if CPPAD_TEST_OPENMP
bool user_atomic_openmp(void)
{	using CppAD::thread_alloc;

	bool ok = true;
	bool ok_all[NUMBER_CALLS];
	size_t num_threads = NUMBER_THREADS;
	int int_num_threads = int(num_threads);

	// make first call in sequential mode
	int call_index = 0;
	ok &= user_atomic(call_index);

	// turn off dynamic thread adjustment
	omp_set_num_threads( int_num_threads );

	// setup for using CppAD::AD<double> in parallel
	thread_alloc::parallel_setup(
		num_threads, in_parallel, thread_number
	);
	thread_alloc::hold_memory(true);
	CppAD::parallel_ad<double>();

# pragma omp parallel for
	for(call_index = 0; call_index < NUMBER_CALLS; call_index++)
		ok_all[call_index] = user_atomic(call_index);
// end omp parallel for

	// tear down parallel mode
	omp_set_num_threads(1);
	thread_alloc::parallel_setup(1, CPPAD_NULL, CPPAD_NULL);
	thread_alloc::hold_memory(false);
	CppAD::parallel_ad<double>();

	// combine all the ok flags into one
	for(call_index = 0; call_index < int_num_threads; call_index++)
		ok &= ok_all[call_index];

	// --------------------------------------------------------------------
	// Free all temporary work space associated with user_atomic objects.
	// (If there are future calls to user atomic functions, they will
	// create new temporary work space.)
	CppAD::user_atomic<double>::clear();

	return ok;
}
# endif
<commit_msg>Previous commit fixed a bug when using user_atomic with multi-threading. In addition, it added a test to demonstrate the bug as well as verify the fix. It also started a set of multi-threading tests that are not examples.<commit_after>/* $Id$ */
/* --------------------------------------------------------------------------
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell

CppAD is distributed under multiple licenses. This distribution is under
the terms of the
                    Common Public License Version 1.0.

A copy of this license is included in the COPYING file of this distribution.
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
-------------------------------------------------------------------------- */

# include <cppad/cppad.hpp>

# define NUMBER_THREADS     4
# define NUMBER_CALLS       40

// y[0] = x[0] + x[1]
// y[1] = x[1] + x[2]
namespace {
# ifdef CPPAD_TEST_OPENMP
	// ------------------------------------------------------------------
	// used to inform CppAD when we are in parallel execution mode
	bool in_parallel(void)
	{	return static_cast<bool>( omp_in_parallel() ); }
	// ------------------------------------------------------------------
	// used to inform CppAD of the current thread number
	size_t thread_number(void)
	{	return static_cast<size_t>( omp_get_thread_num() ); }
# endif

	// y[0] = x[0] + x[1]
	bool user_atomic_forward(
		size_t                         id ,
		size_t                          k ,
		size_t                          n ,
		size_t                          m ,
		const CppAD::vector<bool>&     vx ,
		CppAD::vector<bool>&           vy ,
		const CppAD::vector<double>&   tx ,
		CppAD::vector<double>&         ty )
	{	assert(n >= 3 && m == 2);
		if( k > 0 )
			return false;

		ty[0] = tx[0] + tx[1];
		ty[1] = tx[1] + tx[2];

		if( vy.size() > 0 )
		{	vy[0] = (vx[0] | vx[1]);
			vy[1] = (vx[1] | vx[2]);
		}
		return true;
	}

	bool user_atomic_reverse(
		size_t                         id ,
		size_t                          k ,
		size_t                          n ,
		size_t                          m ,
		const CppAD::vector<double>&   tx ,
		const CppAD::vector<double>&   ty ,
		CppAD::vector<double>&         px ,
		const CppAD::vector<double>&   py )
	{	return false; }

	bool user_atomic_for_jac_sparse(
		size_t                                  id ,
		size_t                                   n ,
		size_t                                   m ,
		size_t                                   q ,
		const CppAD::vector< std::set<size_t> >& r ,
		CppAD::vector< std::set<size_t>  >&      s )
	{	return false; }

	bool user_atomic_rev_jac_sparse(
		size_t                                  id ,
		size_t                                   n ,
		size_t                                   m ,
		size_t                                   q ,
		CppAD::vector< std::set<size_t> >&       r ,
		const CppAD::vector< std::set<size_t> >& s )
	{	return false; }

	bool user_atomic_rev_hes_sparse(
		size_t                                  id ,
		size_t                                   n ,
		size_t                                   m ,
		size_t                                   q ,
		const CppAD::vector< std::set<size_t> >& r ,
		const CppAD::vector<bool>&               s ,
		CppAD::vector<bool>&                     t ,
		const CppAD::vector< std::set<size_t> >& u ,
		CppAD::vector< std::set<size_t> >&       v )
	{	return false; }

	CPPAD_USER_ATOMIC(
		my_user_atomic             ,
		CppAD::vector              ,
		double                     ,
		user_atomic_forward        ,
		user_atomic_reverse        ,
		user_atomic_for_jac_sparse ,
		user_atomic_rev_jac_sparse ,
		user_atomic_rev_hes_sparse
	)

	bool user_atomic(int call_index)
	{	bool ok = true;
		using CppAD::AD;
		using CppAD::vector;

		size_t j;
		size_t m = 2;
		size_t n = size_t(call_index + 3);
		vector< AD<double> > ax(n), ay(m);
		for(j = 0; j < n; j++)
			ax[j] = AD<double>(j + 1);
		CppAD::Independent(ax);

		// use user atomic function
		size_t id = 0;
		my_user_atomic(id, ax, ay);

		// create function
		CppAD::ADFun<double> g(ax, ay);

		// now use the tape with the user atomic function
		vector<double> x(n), y(m);
		for(j = 0; j < n; j++)
			x[j] = (j + 1) * (j + 1);
		y = g.Forward(0, x);
		// y[0] = x[0] + x[1]
		ok &= (y[0] == x[0] + x[1]);
		// y[1] = x[1] + x[2]
		ok &= (y[0] == x[0] + x[1]);

		return ok;
	}
}

# ifdef CPPAD_TEST_OPENMP

# include <omp.h>

bool user_atomic_openmp(void)
{	using CppAD::thread_alloc;

	bool ok = true;
	bool ok_all[NUMBER_CALLS];
	size_t num_threads = NUMBER_THREADS;
	int int_num_threads = int(num_threads);

	// make first call in sequential mode
	int call_index = 0;
	ok &= user_atomic(call_index);

	// turn off dynamic thread adjustment
	omp_set_num_threads( int_num_threads );

	// setup for using CppAD::AD<double> in parallel
	thread_alloc::parallel_setup(
		num_threads, in_parallel, thread_number
	);
	thread_alloc::hold_memory(true);
	CppAD::parallel_ad<double>();

# pragma omp parallel for
	for(call_index = 0; call_index < NUMBER_CALLS; call_index++)
		ok_all[call_index] = user_atomic(call_index);
// end omp parallel for

	// tear down parallel mode
	omp_set_num_threads(1);
	thread_alloc::parallel_setup(1, CPPAD_NULL, CPPAD_NULL);
	thread_alloc::hold_memory(false);
	CppAD::parallel_ad<double>();

	// combine all the ok flags into one
	for(call_index = 0; call_index < int_num_threads; call_index++)
		ok &= ok_all[call_index];

	// --------------------------------------------------------------------
	// Free all temporary work space associated with user_atomic objects.
	// (If there are future calls to user atomic functions, they will
	// create new temporary work space.)
	CppAD::user_atomic<double>::clear();

	return ok;
}
# endif
<|endoftext|>


<commit_before>/*******************************
Copyright (C) 2013-2015 gregoire ANGERAND

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

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
GNU General Public License for more details.

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

#include "DeferredShadingRenderer.h"
#include "DeferredCommon.h"

namespace n {
namespace graphics {

struct LightData
{
	LightData(Light<> *l) : light(l), shadowData(light->castShadows() ? light->getShadowRenderer()->prepare() : 0) {
	}

	Light<> *light;
	void *shadowData;
};

struct FrameData
{
	math::Vec3 pos;
	math::Matrix4<> inv;
	core::Array<LightData> lights[LightType::Max];
	void *child;
};

template<LightType Type>
ShaderCombinaison *getShader() {
	static ShaderCombinaison *shader[LightType::Max] = {0};
	core::String computeDir[LightType::Max] = {"return n_LightPos - pos;",
											   "return n_LightMatrix[0];",
											   "return n_LightMatrix[0];"};
	core::String attenuate[LightType::Max] = {"float x = min(lightDist, n_LightRadius); "
												  "return sqr(1.0 - sqr(sqr(x / n_LightRadius))) / (sqr(x) + 1.0);",
											  "return 1.0;",
											  "return any(greaterThan(abs(n_LightMatrix * (pos - n_LightPos)), n_LightSize)) ? 0.0 : 1.0;"};
	if(!shader[Type]) {
		shader[Type] = new ShaderCombinaison(new Shader<FragmentShader>(
			"uniform sampler2D n_0;"
			"uniform sampler2D n_1;"
			"uniform sampler2D n_2;"
			"uniform sampler2D n_D;"
			"uniform mat4 n_Inv;"
			"uniform vec3 n_Cam;"

			"uniform vec3 n_LightPos;"
			"uniform mat3 n_LightMatrix;"
			"uniform vec3 n_LightSize;"
			"uniform vec3 n_LightColor;"
			"uniform float n_LightRadius;"

			"uniform sampler2D n_LightShadow;"
			"uniform float n_LightShadowMul;"
			"uniform mat4 n_LightShadowMatrix;"

			"in vec4 n_ScreenPosition;"

			"out vec4 n_Out;"

			"const float epsilon = 0.0001;"

			+ getBRDFs() +

			"vec3 projectShadow(vec3 p) {"
				"vec4 proj = n_LightShadowMatrix * vec4(p, 1);"
				"return (proj.xyz / proj.w) * 0.5 + 0.5;"
			"}"

			"float computeShadow(vec3 pos) {"
				"vec3 proj = projectShadow(pos);"
				"float d = texture(n_LightShadow, proj.xy).x;"
				"return d < proj.z ? 0.0 : 1.0;"
			"}"

			"vec3 unproj(vec2 C) {"
				"vec4 VP = vec4(vec3(C, texture(n_D, C).x) * 2.0 - 1.0, 1.0);"
				"vec4 P = n_Inv * VP;"
				"return P.xyz / P.w;"
			"}"

			"vec2 computeTexCoord() {"
				"return (n_ScreenPosition.xy / n_ScreenPosition.w) * 0.5 + 0.5;"
			"}"

			"float attenuate(vec3 lightDir, vec3 pos, float lightDist) {"
				+ attenuate[Type] +
			"}"

			"vec3 computeDir(vec3 pos) {"
				+ computeDir[Type] +
			"}"

			"void main() {"
				"vec2 texCoord = computeTexCoord();"
				"vec4 albedo = texture(n_0, texCoord);"
				"vec3 pos = unproj(texCoord);"
				"vec3 normal = normalize(texture(n_1, texCoord).xyz * 2.0 - 1.0);"
				"vec4 material = texture(n_2, texCoord);"
				"vec3 view = normalize(n_Cam - pos);"
				"vec3 lightDir = computeDir(pos);"
				"float lightDist = length(lightDir);"
				"vec3 lightVec = lightDir / lightDist;"
				"float metallic = material.y;"

				"float shadow = 1.0;"
				"if(n_LightShadowMul != 0.0) {"
					"shadow = computeShadow(pos);"
				"}"

				"float att = attenuate(lightDir, pos, lightDist);"
				"float NoL = saturate(dot(normal, lightDir));"
				"vec3 light = n_LightColor * NoL * att * shadow;"

				"float diffuse = brdf_lambert(lightDir, view, normal, material);"
				"float specular = brdf_cook_torrance(lightDir, view, normal, material);"
				"n_Out = vec4(light * (diffuse * albedo.rgb * (1.0 - metallic) + specular * mix(vec3(1), albedo.rgb, metallic)), albedo.a);"

				//"n_Out = vec4(vec3(brdf(dir, view, normal, material) + 0.25), 1.0);"
				//"n_Out = vec4(vec3(NoL), 1);"
				//"n_Out = vec4(shadow);"
			"}"), Type == Directional ? ShaderProgram::NoProjectionShader : ShaderProgram::ProjectionShader);
	}
	return shader[Type];
}

template<LightType Type>
void lightGeometryPass(const Light<> *l, ShaderCombinaison *sh, const math::Matrix3<> &lightMatrix) {
	switch(Type) {
		case Directional:
			GLContext::getContext()->getScreen().draw(VertexAttribs());
		break;

		case Box: {
			const BoxLight<> *box = dynamic_cast<const BoxLight<> *>(l);
			GLContext::getContext()->setModelMatrix(math::Matrix4<>(lightMatrix[0] * box->getSize().x() * -box->getScale(), 0,
																	lightMatrix[1] * box->getSize().y() * -box->getScale(), 0,
																	lightMatrix[2] * box->getSize().z() * -box->getScale(), 0,
																	0, 0, 0, 1).transposed());
			sh->setValue("n_LightSize", box->getSize() * box->getScale() * 2);
			getBox().draw(VertexAttribs());
		} break;

		case Point: {
			GLContext::getContext()->setModelMatrix(math::Transform<>(l->getPosition(), l->getRadius() + 1).getMatrix());
			getSphere().draw(VertexAttribs());
		} break;
	}
}

template<LightType Type>
ShaderCombinaison *lightPass(const FrameData *data, GBufferRenderer *child) {
	ShaderCombinaison *sh = getShader<Type>();
	sh->bind();

	sh->setValue("n_0", child->getFrameBuffer().getAttachement(0));
	sh->setValue("n_1", child->getFrameBuffer().getAttachement(1));
	sh->setValue("n_2", child->getFrameBuffer().getAttachement(2));
	sh->setValue("n_D", child->getFrameBuffer().getDepthAttachement());
	sh->setValue("n_Inv", data->inv);
	sh->setValue("n_Cam", data->pos);

	for(const LightData &ld : data->lights[Type]) {
		const Light<> *l = ld.light;
		math::Transform<> transform = l->getTransform();
		math::Matrix3<> lightMatrix(-transform.getX().normalized(), -transform.getY().normalized(), -transform.getZ().normalized());

		sh->setValue("n_LightPos", l->getPosition());
		sh->setValue("n_LightRadius", l->getRadius());
		sh->setValue("n_LightColor", l->getColor().sub(3) * l->getIntensity());
		sh->setValue("n_LightMatrix", lightMatrix.transposed());
		sh->setValue("n_LightShadowMul", l->castShadows() ? 1.0 : 0.0);
		if(l->castShadows()) {
			sh->setValue("n_LightShadow", l->getShadowRenderer()->getDepth());
			sh->setValue("n_LightShadowMatrix", l->getShadowRenderer()->getShadowMatrix());
		}
		lightGeometryPass<Type>(l, sh, lightMatrix);
	}

	return sh;
}

DeferredShadingRenderer::DeferredShadingRenderer(GBufferRenderer *c, const math::Vec2ui &s) : BufferedRenderer(s.isNull() ? c->getFrameBuffer().getSize() : s), child(c) {
	buffer.setAttachmentEnabled(0, true);
	buffer.setAttachmentFormat(0, ImageFormat::RGBA16F);
	buffer.setDepthEnabled(true);
}

void *DeferredShadingRenderer::prepare() {
	void *ptr = child->prepare();
	SceneRenderer::FrameData *sceneData = child->getSceneRendererData(ptr);

	return new FrameData({sceneData->camera->getPosition(),
						  (sceneData->proj * sceneData->view).inverse(),
						  {child->getRenderer()->getScene()->query<PointLight<>>(*sceneData->camera),
						   child->getRenderer()->getScene()->get<DirectionalLight<>>(),
						   child->getRenderer()->getScene()->get<BoxLight<>>()},
						  ptr});
}

void DeferredShadingRenderer::render(void *ptr) {
	FrameData *data = reinterpret_cast<FrameData *>(ptr);
	SceneRenderer::FrameData *sceneData = child->getSceneRendererData(data->child);

	child->render(data->child);

	for(uint i = 0; i != LightType::Max; i++) {
		data->lights[i].foreach([](const LightData &l) {
			if(l.light->castShadows()) {
				l.light->getShadowRenderer()->render(l.shadowData);
			}
		});
	}

	GLContext::getContext()->setProjectionMatrix(sceneData->proj);
	GLContext::getContext()->setViewMatrix(sceneData->view);

	{
		buffer.bind();
		buffer.clear(true, false);
		child->getFrameBuffer().blit(FrameBuffer::Depth);

		getLightMaterial<Point>().bind();
		lightPass<Point>(data, child);

		getLightMaterial<Box>().bind();
		lightPass<Box>(data, child);

		getLightMaterial<Directional>().bind();
		lightPass<Directional>(data, child)->unbind();
	}

	delete data;
}

}
}
<commit_msg>Tighter shadowmaps.<commit_after>/*******************************
Copyright (C) 2013-2015 gregoire ANGERAND

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

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
GNU General Public License for more details.

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

#include "DeferredShadingRenderer.h"
#include "DeferredCommon.h"

namespace n {
namespace graphics {

struct LightData
{
	LightData(Light<> *l) : light(l), shadowData(light->castShadows() ? light->getShadowRenderer()->prepare() : 0) {
	}

	Light<> *light;
	void *shadowData;
};

struct FrameData
{
	math::Vec3 pos;
	math::Matrix4<> inv;
	core::Array<LightData> lights[LightType::Max];
	void *child;
};

template<LightType Type>
ShaderCombinaison *getShader() {
	static ShaderCombinaison *shader[LightType::Max] = {0};
	core::String computeDir[LightType::Max] = {"return n_LightPos - pos;",
											   "return n_LightForward;",
											   "return n_LightForward;"};
	core::String attenuate[LightType::Max] = {"float x = min(lightDist, n_LightRadius); "
												  "return sqr(1.0 - sqr(sqr(x / n_LightRadius))) / (sqr(x) + 1.0);",
											  "return 1.0;",
											  "return any(greaterThan(abs(n_LightMatrix * (pos - n_LightPos)), n_LightSize)) ? 0.0 : 1.0;"};
	if(!shader[Type]) {
		shader[Type] = new ShaderCombinaison(new Shader<FragmentShader>(
			"uniform sampler2D n_0;"
			"uniform sampler2D n_1;"
			"uniform sampler2D n_2;"
			"uniform sampler2D n_D;"
			"uniform mat4 n_Inv;"
			"uniform vec3 n_Cam;"

			"uniform vec3 n_LightPos;"
			"uniform vec3 n_LightForward;"
			"uniform vec3 n_LightColor;"

			"uniform float n_LightRadius;"
			"uniform mat3 n_LightMatrix;"
			"uniform vec3 n_LightSize;"

			"uniform sampler2D n_LightShadow;"
			"uniform float n_LightShadowMul;"
			"uniform mat4 n_LightShadowMatrix;"

			"in vec4 n_ScreenPosition;"

			"out vec4 n_Out;"

			"const float epsilon = 0.0001;"

			+ getBRDFs() +

			"vec3 projectShadow(vec3 p) {"
				"vec4 proj = n_LightShadowMatrix * vec4(p, 1);"
				"return (proj.xyz / proj.w) * 0.5 + 0.5;"
			"}"

			"float computeShadow(vec3 pos) {"
				"vec3 proj = projectShadow(pos);"
				"float d = texture(n_LightShadow, proj.xy).x;"
				"return step(proj.z, d);"
			"}"

			"vec3 unproj(vec2 C) {"
				"vec4 VP = vec4(vec3(C, texture(n_D, C).x) * 2.0 - 1.0, 1.0);"
				"vec4 P = n_Inv * VP;"
				"return P.xyz / P.w;"
			"}"

			"vec2 computeTexCoord() {"
				"return (n_ScreenPosition.xy / n_ScreenPosition.w) * 0.5 + 0.5;"
			"}"

			"float attenuate(vec3 lightDir, vec3 pos, float lightDist) {"
				+ attenuate[Type] +
			"}"

			"vec3 computeDir(vec3 pos) {"
				+ computeDir[Type] +
			"}"

			"void main() {"
				"vec2 texCoord = computeTexCoord();"
				"vec4 albedo = texture(n_0, texCoord);"
				"vec3 pos = unproj(texCoord);"
				"vec3 normal = normalize(texture(n_1, texCoord).xyz * 2.0 - 1.0);"
				"vec4 material = texture(n_2, texCoord);"
				"vec3 view = normalize(n_Cam - pos);"
				"vec3 lightDir = computeDir(pos);"
				"float lightDist = length(lightDir);"
				"vec3 lightVec = lightDir / lightDist;"
				"float metallic = material.y;"

				"float shadow = 1.0;"
				"if(n_LightShadowMul != 0.0) {"
					"shadow = computeShadow(pos);"
				"}"

				"float att = attenuate(lightDir, pos, lightDist);"
				"float NoL = saturate(dot(normal, lightDir));"
				"vec3 light = n_LightColor * NoL * att * shadow;"

				"float diffuse = brdf_lambert(lightDir, view, normal, material);"
				"float specular = brdf_cook_torrance(lightDir, view, normal, material);"
				"n_Out = vec4(light * (diffuse * albedo.rgb * (1.0 - metallic) + specular * mix(vec3(1), albedo.rgb, metallic)), albedo.a);"

				//"n_Out = vec4(vec3(brdf(dir, view, normal, material) + 0.25), 1.0);"
				//"n_Out = vec4(vec3(NoL), 1);"
				//"n_Out = vec4(shadow);"
			"}"), Type == Directional ? ShaderProgram::NoProjectionShader : ShaderProgram::ProjectionShader);
	}
	return shader[Type];
}

template<LightType Type>
void lightGeometryPass(const Light<> *l, ShaderCombinaison *sh, const math::Vec3 &forward) {
	switch(Type) {
		case Directional:
			GLContext::getContext()->getScreen().draw(VertexAttribs());
		break;

		case Box: {
			const BoxLight<> *box = dynamic_cast<const BoxLight<> *>(l);
			math::Matrix3<> lightMatrix(forward, -l->getTransform().getY().normalized(), -l->getTransform().getZ().normalized());
			GLContext::getContext()->setModelMatrix(math::Matrix4<>(lightMatrix[0] * box->getSize().x() * box->getScale() * -2, 0,
																	lightMatrix[1] * box->getSize().y() * box->getScale() * -2, 0,
																	lightMatrix[2] * box->getSize().z() * box->getScale() * -2, 0,
																	0, 0, 0, 1).transposed());
			sh->setValue("n_LightSize", box->getSize() * box->getScale());
			sh->setValue("n_LightMatrix", lightMatrix);
			getBox().draw(VertexAttribs());
		} break;

		case Point:
			GLContext::getContext()->setModelMatrix(math::Transform<>(l->getPosition(), l->getRadius() + 1).getMatrix());
			getSphere().draw(VertexAttribs());
		break;
	}
}

template<LightType Type>
ShaderCombinaison *lightPass(const FrameData *data, GBufferRenderer *child) {
	ShaderCombinaison *sh = getShader<Type>();
	sh->bind();

	sh->setValue("n_0", child->getFrameBuffer().getAttachement(0));
	sh->setValue("n_1", child->getFrameBuffer().getAttachement(1));
	sh->setValue("n_2", child->getFrameBuffer().getAttachement(2));
	sh->setValue("n_D", child->getFrameBuffer().getDepthAttachement());
	sh->setValue("n_Inv", data->inv);
	sh->setValue("n_Cam", data->pos);

	for(const LightData &ld : data->lights[Type]) {
		const Light<> *l = ld.light;
		math::Vec3 forward = -l->getTransform().getX().normalized();

		sh->setValue("n_LightPos", l->getPosition());
		sh->setValue("n_LightRadius", l->getRadius());
		sh->setValue("n_LightColor", l->getColor().sub(3) * l->getIntensity());
		sh->setValue("n_LightForward", forward);
		sh->setValue("n_LightShadowMul", l->castShadows() ? 1.0 : 0.0);
		if(l->castShadows()) {
			sh->setValue("n_LightShadow", l->getShadowRenderer()->getDepth());
			sh->setValue("n_LightShadowMatrix", l->getShadowRenderer()->getShadowMatrix());
		}
		lightGeometryPass<Type>(l, sh, forward);
	}

	return sh;
}

DeferredShadingRenderer::DeferredShadingRenderer(GBufferRenderer *c, const math::Vec2ui &s) : BufferedRenderer(s.isNull() ? c->getFrameBuffer().getSize() : s), child(c) {
	buffer.setAttachmentEnabled(0, true);
	buffer.setAttachmentFormat(0, ImageFormat::RGBA16F);
	buffer.setDepthEnabled(true);
}

void *DeferredShadingRenderer::prepare() {
	void *ptr = child->prepare();
	SceneRenderer::FrameData *sceneData = child->getSceneRendererData(ptr);

	return new FrameData({sceneData->camera->getPosition(),
						  (sceneData->proj * sceneData->view).inverse(),
						  {child->getRenderer()->getScene()->query<PointLight<>>(*sceneData->camera),
						   child->getRenderer()->getScene()->get<DirectionalLight<>>(),
						   child->getRenderer()->getScene()->get<BoxLight<>>()},
						  ptr});
}

void DeferredShadingRenderer::render(void *ptr) {
	FrameData *data = reinterpret_cast<FrameData *>(ptr);
	SceneRenderer::FrameData *sceneData = child->getSceneRendererData(data->child);

	child->render(data->child);

	for(uint i = 0; i != LightType::Max; i++) {
		data->lights[i].foreach([](const LightData &l) {
			if(l.light->castShadows()) {
				l.light->getShadowRenderer()->render(l.shadowData);
			}
		});
	}

	GLContext::getContext()->setProjectionMatrix(sceneData->proj);
	GLContext::getContext()->setViewMatrix(sceneData->view);

	{
		buffer.bind();
		buffer.clear(true, false);
		child->getFrameBuffer().blit(FrameBuffer::Depth);

		getLightMaterial<Point>().bind();
		lightPass<Point>(data, child);

		getLightMaterial<Box>().bind();
		lightPass<Box>(data, child);

		getLightMaterial<Directional>().bind();
		lightPass<Directional>(data, child)->unbind();
	}

	delete data;
}

}
}
<|endoftext|>