<commit_before>#include "stdafx.h"
#include "cpu_helper.h"

#define TF_BIT				0x100
#define BREAK_OPCODE		0xCC
#define DR7_TRACE_BRANCH	0x200
#define DR7_LAST_BRANCH		0x100

bool
set_break_point(
	_In_ ch_param* param,
	_In_ DWORD_PTR address,
	_Out_ unsigned char* opcode
	)
{
	_ASSERTE(NULL != param);
	_ASSERTE(0 != address);
	_ASSERTE(NULL != opcode);
	if (NULL == param || 0 == address || NULL == opcode) return false;

	SIZE_T cb_rw = 0;
	unsigned char temp = 0;
	BOOL ret = ReadProcessMemory(
		param->hproc,
		(LPCVOID)address,
		&temp,
		sizeof(unsigned char),
		&cb_rw
		);

	if (TRUE != ret || cb_rw != sizeof(unsigned char))
	{
		log(
			"ReadProcessMemory( hprocess = 0x%08x, address = 0x%p ), gle = %u",
			param->hproc,
			address,
			GetLastError()
			);
		return false;
	}

	*opcode = temp;

	if (temp == BREAK_OPCODE)
	{
		#pragma TODO(" ּҿ  ٸ Ÿ 극ũ Ʈ ġϷ ϴ  ذϱ")
		log(
			"hprocess = 0x%08x, address =0x%p, breakpoint is already installed",
			param->hproc,
			address
			);
		return true;
	}

	MEMORY_BASIC_INFORMATION mbi = { 0 };
	if (0 == VirtualQueryEx(
		param->hproc,
		(LPCVOID)address,
		&mbi,
		sizeof(mbi)))
	{
		log(
			"VirtualQueryEx( hprocess = 0x%08x, address = 0x%p ), gle = %u",
			param->hproc,
			address,
			GetLastError());
		return false;
	}

	if (TRUE != VirtualProtectEx(
		param->hproc,
		mbi.BaseAddress,
		mbi.RegionSize,
		PAGE_EXECUTE_READWRITE,
		&mbi.Protect))
	{
		log(
			"VirtualProtectEx( hprocess = 0x%08x, address = 0x%p, size = %u, PAGE_EXECUTE_READWRITE ), gle = %u",
			param->hproc,
			mbi.BaseAddress,
			mbi.RegionSize,
			GetLastError()
			);
		return false;
	}

	do
	{
		temp = BREAK_OPCODE;
		ret = WriteProcessMemory(
			param->hproc,
			(LPVOID)address,
			&temp,
			sizeof(unsigned char),
			&cb_rw);

		if (TRUE != ret || cb_rw != sizeof(unsigned char))
		{
			log(
				"WriteProcessMemory( hprocess = 0x%08x, address = 0x%p ), gle = %u",
				param->hproc,
				address,
				GetLastError()
				);

			ret = FALSE;
			break;
		}

		if (TRUE != FlushInstructionCache(param->hproc, (LPCVOID)address, sizeof(unsigned char)))
		{
			log(
				"WriteProcessMemory( hprocess = 0x%08x, address = 0x%p ), gle = %u",
				param->hproc,
				address,
				GetLastError()
				);
		}
	} while (false);

	VirtualProtectEx(param->hproc, mbi.BaseAddress, mbi.RegionSize, mbi.Protect, &mbi.Protect);
	return (TRUE == ret) ? true : false;
}<commit_msg>make clear_break_point()<commit_after>#include "stdafx.h"
#include "cpu_helper.h"

#define TF_BIT				0x100
#define BREAK_OPCODE		0xCC
#define DR7_TRACE_BRANCH	0x200
#define DR7_LAST_BRANCH		0x100

bool
set_break_point(
	_In_ ch_param* param,
	_In_ DWORD_PTR address,
	_Out_ unsigned char* opcode
	)
{
	_ASSERTE(NULL != param);
	_ASSERTE(0 != address);
	_ASSERTE(NULL != opcode);
	if (NULL == param || 0 == address || NULL == opcode) return false;

	SIZE_T cb_rw = 0;
	unsigned char temp = 0;
	BOOL ret = ReadProcessMemory(
		param->hproc,
		(LPCVOID)address,
		&temp,
		sizeof(unsigned char),
		&cb_rw
		);

	if (TRUE != ret || cb_rw != sizeof(unsigned char))
	{
		log(
			"ReadProcessMemory( hprocess = 0x%08x, address = 0x%p ), gle = %u",
			param->hproc,
			address,
			GetLastError()
			);
		return false;
	}

	*opcode = temp;

	if (temp == BREAK_OPCODE)
	{
		log(
			"hprocess = 0x%08x, address =0x%p, breakpoint is already installed",
			param->hproc,
			address
			);
		return true;
	}

	MEMORY_BASIC_INFORMATION mbi = { 0 };
	if (0 == VirtualQueryEx(
		param->hproc,
		(LPCVOID)address,
		&mbi,
		sizeof(mbi)))
	{
		log(
			"VirtualQueryEx( hprocess = 0x%08x, address = 0x%p ), gle = %u",
			param->hproc,
			address,
			GetLastError());
		return false;
	}

	if (TRUE != VirtualProtectEx(
		param->hproc,
		mbi.BaseAddress,
		mbi.RegionSize,
		PAGE_EXECUTE_READWRITE,
		&mbi.Protect))
	{
		log(
			"VirtualProtectEx( hprocess = 0x%08x, address = 0x%p, size = %u, PAGE_EXECUTE_READWRITE ), gle = %u",
			param->hproc,
			mbi.BaseAddress,
			mbi.RegionSize,
			GetLastError()
			);
		return false;
	}

	do
	{
		temp = BREAK_OPCODE;
		ret = WriteProcessMemory(
			param->hproc,
			(LPVOID)address,
			&temp,
			sizeof(unsigned char),
			&cb_rw);

		if (TRUE != ret || cb_rw != sizeof(unsigned char))
		{
			log(
				"WriteProcessMemory( hprocess = 0x%08x, address = 0x%p ), gle = %u",
				param->hproc,
				address,
				GetLastError()
				);

			ret = FALSE;
			break;
		}

		if (TRUE != FlushInstructionCache(param->hproc, (LPCVOID)address, sizeof(unsigned char)))
		{
			log(
				"WriteProcessMemory( hprocess = 0x%08x, address = 0x%p ), gle = %u",
				param->hproc,
				address,
				GetLastError()
				);
		}
	} while (false);

	VirtualProtectEx(param->hproc, mbi.BaseAddress, mbi.RegionSize, mbi.Protect, &mbi.Protect);
	return (TRUE == ret) ? true : false;
}

bool
clear_break_point(
	_In_ ch_param* param,
	_In_ DWORD_PTR address,
	_In_ unsigned char opcode,
	_In_ bool reset_eip
	)
{
	_ASSERTE(NULL != param);
	_ASSERTE(0 != address);
	_ASSERTE(NULL != opcode);
	if (NULL == param || 0 == address || NULL == opcode) return false;

	SIZE_T cb_rw = 0;
	unsigned char temp = 0;
	BOOL ret = ReadProcessMemory(
		param->hproc,
		(LPCVOID)address,
		&temp,
		sizeof(unsigned char),
		&cb_rw
		);

	if (TRUE != ret || cb_rw != sizeof(unsigned char))
	{
		log(
			"ReadProcessMemory( hprocess = 0x%08x, address = 0x%p ), gle = %u",
			param->hproc,
			address,
			GetLastError()
			);
		return false;
	}

	if (temp != BREAK_OPCODE)
	{
		log(
			"hprocess = 0x%08x, address = 0x%p, opcode = 0x%02x (not BREAK_OPCODE!)",
			param->hproc,
			address,
			temp
			);
		return false;
	}

	MEMORY_BASIC_INFORMATION mbi = { 0 };
	if (0 == VirtualQueryEx(
		param->hproc,
		(LPCVOID)address,
		&mbi,
		sizeof(mbi)))
	{
		log(
			"VirtualQueryEx( hprocess = 0x%08x, address = 0x%p ), gle = %u",
			param->hproc,
			address,
			GetLastError()
			);
		return false;
	}

	if (TRUE != VirtualProtectEx(
		param->hproc,
		mbi.BaseAddress,
		mbi.RegionSize,
		PAGE_EXECUTE_READWRITE,
		&mbi.Protect))
	{
		log(
			"VirtualProtectEx( hprocess = 0x%08x, address = 0x%p, size = %u, PAGE_EXECUTE_READWRITE ) gle = %u",
			param->hproc,
			mbi.BaseAddress,
			mbi.RegionSize,
			GetLastError()
			);
		return false;
	}

	do
	{
		ret = WriteProcessMemory(
			param->hproc,
			(LPVOID)address,
			&opcode,
			sizeof(unsigned char),
			&cb_rw);
		if (TRUE != ret || cb_rw != sizeof(unsigned char))
		{
			log(
				"WriteProcessMemory( hprocess = 0x%08x, address = 0x%p ), gle = %u",
				param->hproc,
				address,
				GetLastError()
				);

				ret = FALSE;
			break;
		}

		if (TRUE != FlushInstructionCache(param->hproc, (LPCVOID)address, sizeof(unsigned char)))
		{
			log(
				"WriteProcessMemory( hprocess = 0x%08x, address = 0x%p ), gle = %u",
				param->hproc,
				address,
				GetLastError()
				);
		}
	} while (false);

	VirtualProtectEx(param->hproc, mbi.BaseAddress, mbi.RegionSize, mbi.Protect, &mbi.Protect);

	if (true == reset_eip)
	{
		_ASSERTE(NULL != param->hthread);
		if (NULL != param->hthread)
		{
#if defined(_AMD64_)
			param->context.Rip--;
#elif defined(_X86_)
			param->context.Eip--;
#else
#error !!unsupported architecture!!
#endif
			if (TRUE != SetThreadContext(param->hthread, &param->context))
			{
				log(
					"SetThreadContext(hthread=0x%08x), gle = %u",
					param->hthread,
					GetLastError()
					);
			}
		}
	}

	return (TRUE == ret) ? true : false;
}<|endoftext|>


<commit_before><commit_msg>Fix a typo in a comment.<commit_after><|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 "chrome/browser/net/preconnect.h"

#include "base/logging.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/common/net/url_request_context_getter.h"
#include "net/http/http_network_session.h"
#include "net/http/http_transaction_factory.h"
#include "net/url_request/url_request_context.h"

namespace chrome_browser_net {

// We will deliberately leak this singular instance, which is used only for
// callbacks.
// static
Preconnect* Preconnect::callback_instance_;

// static
bool Preconnect::PreconnectOnUIThread(const GURL& url) {
  // Try to do connection warming for this search provider.
  URLRequestContextGetter* getter = Profile::GetDefaultRequestContext();
  if (!getter)
    return false;
  // Prewarm connection to Search URL.
  ChromeThread::PostTask(
      ChromeThread::IO,
      FROM_HERE,
      NewRunnableFunction(Preconnect::PreconnectOnIOThread, url));
  return true;
}

// static
void Preconnect::PreconnectOnIOThread(const GURL& url) {
  URLRequestContextGetter* getter = Profile::GetDefaultRequestContext();
  if (!getter)
    return;
  if (!ChromeThread::CurrentlyOn(ChromeThread::IO)) {
    LOG(DFATAL) << "This must be run only on the IO thread.";
    return;
  }
  URLRequestContext* context = getter->GetURLRequestContext();
  net::HttpTransactionFactory* factory = context->http_transaction_factory();
  net::HttpNetworkSession* session = factory->GetSession();
  scoped_refptr<net::TCPClientSocketPool> pool = session->tcp_socket_pool();

  net::TCPSocketParams params(url.host(), url.EffectiveIntPort(), net::LOW,
                              GURL(), false);

  net::ClientSocketHandle handle;
  if (!callback_instance_)
    callback_instance_ = new Preconnect;

  // TODO(jar): This does not handle proxies currently.
  handle.Init(url.spec(), params, net::LOWEST,
              callback_instance_, pool, net::BoundNetLog());
  handle.Reset();
}

void Preconnect::RunWithParams(const Tuple1<int>& params) {
  // This will rarely be called, as we reset the connection just after creating.
  NOTREACHED();
}
}  // chrome_browser_net
<commit_msg>Fix the construction of the pool names for preconnect.<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 "chrome/browser/net/preconnect.h"

#include "base/logging.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/common/net/url_request_context_getter.h"
#include "net/base/host_port_pair.h"
#include "net/http/http_network_session.h"
#include "net/http/http_transaction_factory.h"
#include "net/url_request/url_request_context.h"

namespace chrome_browser_net {

// We will deliberately leak this singular instance, which is used only for
// callbacks.
// static
Preconnect* Preconnect::callback_instance_;

// static
bool Preconnect::PreconnectOnUIThread(const GURL& url) {
  // Try to do connection warming for this search provider.
  URLRequestContextGetter* getter = Profile::GetDefaultRequestContext();
  if (!getter)
    return false;
  // Prewarm connection to Search URL.
  ChromeThread::PostTask(
      ChromeThread::IO,
      FROM_HERE,
      NewRunnableFunction(Preconnect::PreconnectOnIOThread, url));
  return true;
}

// static
void Preconnect::PreconnectOnIOThread(const GURL& url) {
  URLRequestContextGetter* getter = Profile::GetDefaultRequestContext();
  if (!getter)
    return;
  if (!ChromeThread::CurrentlyOn(ChromeThread::IO)) {
    LOG(DFATAL) << "This must be run only on the IO thread.";
    return;
  }
  URLRequestContext* context = getter->GetURLRequestContext();
  net::HttpTransactionFactory* factory = context->http_transaction_factory();
  net::HttpNetworkSession* session = factory->GetSession();
  scoped_refptr<net::TCPClientSocketPool> pool = session->tcp_socket_pool();

  net::TCPSocketParams params(url.host(), url.EffectiveIntPort(), net::LOW,
                              GURL(), false);

  net::ClientSocketHandle handle;
  if (!callback_instance_)
    callback_instance_ = new Preconnect;

  net::HostPortPair endpoint(url.host(), url.EffectiveIntPort());
  std::string group_name = endpoint.ToString();
  if (url.SchemeIs("https"))
    group_name = StringPrintf("ssl/%s", group_name.c_str());

  // TODO(jar): This does not handle proxies currently.
  handle.Init(group_name, params, net::LOWEST,
              callback_instance_, pool, net::BoundNetLog());
  handle.Reset();
}

void Preconnect::RunWithParams(const Tuple1<int>& params) {
  // This will rarely be called, as we reset the connection just after creating.
  NOTREACHED();
}
}  // chrome_browser_net
<|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 "chrome/browser/plugin_updater.h"

#include <string>
#include <vector>

#include "base/command_line.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/scoped_ptr.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "base/version.h"
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profile.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/pepper_plugin_registry.h"
#include "chrome/common/pref_names.h"
#include "webkit/glue/plugins/webplugininfo.h"

PluginUpdater::PluginUpdater()
    : enable_internal_pdf_(true),
      notify_pending_(false) {
}

DictionaryValue* PluginUpdater::CreatePluginFileSummary(
    const WebPluginInfo& plugin) {
  DictionaryValue* data = new DictionaryValue();
  data->SetString("path", plugin.path.value());
  data->SetString("name", plugin.name);
  data->SetString("version", plugin.version);
  data->SetBoolean("enabled", plugin.enabled);
  return data;
}

// static
ListValue* PluginUpdater::GetPluginGroupsData() {
  NPAPI::PluginList::PluginMap plugin_groups;
  NPAPI::PluginList::Singleton()->GetPluginGroups(true, &plugin_groups);

  // Construct DictionaryValues to return to the UI
  ListValue* plugin_groups_data = new ListValue();
  for (NPAPI::PluginList::PluginMap::const_iterator it =
       plugin_groups.begin();
       it != plugin_groups.end();
       ++it) {
    plugin_groups_data->Append(it->second->GetDataForUI());
  }
  return plugin_groups_data;
}

void PluginUpdater::EnablePluginGroup(bool enable, const string16& group_name) {
  if (PluginGroup::IsPluginNameDisabledByPolicy(group_name))
    enable = false;
  NPAPI::PluginList::Singleton()->EnableGroup(enable, group_name);
  NotifyPluginStatusChanged();
}

void PluginUpdater::EnablePluginFile(bool enable,
                                     const FilePath::StringType& path) {
  FilePath file_path(path);
  if (enable && !PluginGroup::IsPluginPathDisabledByPolicy(file_path))
    NPAPI::PluginList::Singleton()->EnablePlugin(file_path);
  else
    NPAPI::PluginList::Singleton()->DisablePlugin(file_path);

  NotifyPluginStatusChanged();
}

void PluginUpdater::Observe(NotificationType type,
                            const NotificationSource& source,
                            const NotificationDetails& details) {
  DCHECK_EQ(NotificationType::PREF_CHANGED, type.value);
  const std::string* pref_name = Details<std::string>(details).ptr();
  if (!pref_name) {
    NOTREACHED();
    return;
  }
  if (*pref_name == prefs::kPluginsPluginsBlacklist) {
    PrefService* pref_service = Source<PrefService>(source).ptr();
    const ListValue* list =
        pref_service->GetList(prefs::kPluginsPluginsBlacklist);
    DisablePluginsFromPolicy(list);
  }
}

void PluginUpdater::DisablePluginsFromPolicy(const ListValue* plugin_names) {
  // Generate the set of unique disabled plugin patterns from the disabled
  // plugins list.
  std::set<string16> policy_disabled_plugin_patterns;
  if (plugin_names) {
    ListValue::const_iterator end(plugin_names->end());
    for (ListValue::const_iterator current(plugin_names->begin());
         current != end; ++current) {
      string16 plugin_name;
      if ((*current)->GetAsString(&plugin_name)) {
        policy_disabled_plugin_patterns.insert(plugin_name);
      }
    }
  }
  PluginGroup::SetPolicyDisabledPluginPatterns(policy_disabled_plugin_patterns);

  NotifyPluginStatusChanged();
}

void PluginUpdater::DisablePluginGroupsFromPrefs(Profile* profile) {
  bool update_internal_dir = false;
  FilePath last_internal_dir =
  profile->GetPrefs()->GetFilePath(prefs::kPluginsLastInternalDirectory);
  FilePath cur_internal_dir;
  if (PathService::Get(chrome::DIR_INTERNAL_PLUGINS, &cur_internal_dir) &&
      cur_internal_dir != last_internal_dir) {
    update_internal_dir = true;
    profile->GetPrefs()->SetFilePath(
        prefs::kPluginsLastInternalDirectory, cur_internal_dir);
  }

  if (!enable_internal_pdf_) {
    // This DCHECK guards against us disabling/enabling the pdf plugin more than
    // once without renaming the flag that tells us whether we can enable it
    // automatically.  Each time we disable the plugin by default after it was
    // enabled by default, we need to rename that flag.
    DCHECK(!profile->GetPrefs()->GetBoolean(prefs::kPluginsEnabledInternalPDF));
  }

  bool found_internal_pdf = false;
  bool force_enable_internal_pdf = false;
  string16 pdf_group_name = ASCIIToUTF16(PepperPluginRegistry::kPDFPluginName);
  FilePath pdf_path;
  PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf_path);
  FilePath::StringType pdf_path_str = pdf_path.value();
  if (enable_internal_pdf_ &&
      !profile->GetPrefs()->GetBoolean(prefs::kPluginsEnabledInternalPDF)) {
    // We switched to the internal pdf plugin being on by default, and so we
    // need to force it to be enabled.  We only want to do it this once though,
    // i.e. we don't want to enable it again if the user disables it afterwards.
    profile->GetPrefs()->SetBoolean(prefs::kPluginsEnabledInternalPDF, true);
    force_enable_internal_pdf = true;
  }

  if (ListValue* saved_plugins_list =
          profile->GetPrefs()->GetMutableList(prefs::kPluginsPluginsList)) {
    for (ListValue::const_iterator it = saved_plugins_list->begin();
         it != saved_plugins_list->end();
         ++it) {
      if (!(*it)->IsType(Value::TYPE_DICTIONARY)) {
        LOG(WARNING) << "Invalid entry in " << prefs::kPluginsPluginsList;
        continue;  // Oops, don't know what to do with this item.
      }

      DictionaryValue* plugin = static_cast<DictionaryValue*>(*it);
      string16 group_name;
      bool enabled = true;
      plugin->GetBoolean("enabled", &enabled);

      FilePath::StringType path;
      // The plugin list constains all the plugin files in addition to the
      // plugin groups.
      if (plugin->GetString("path", &path)) {
        // Files have a path attribute, groups don't.
        FilePath plugin_path(path);
        if (update_internal_dir &&
            FilePath::CompareIgnoreCase(plugin_path.DirName().value(),
                last_internal_dir.value()) == 0) {
          // If the internal plugin directory has changed and if the plugin
          // looks internal, update its path in the prefs.
          plugin_path = cur_internal_dir.Append(plugin_path.BaseName());
          path = plugin_path.value();
          plugin->SetString("path", path);
        }

        if (FilePath::CompareIgnoreCase(path, pdf_path_str) == 0) {
          found_internal_pdf = true;
          if (!enabled && force_enable_internal_pdf) {
            enabled = true;
            plugin->SetBoolean("enabled", true);
          }
        }
        if (!enabled)
          NPAPI::PluginList::Singleton()->DisablePlugin(plugin_path);
      } else if (!enabled && plugin->GetString("name", &group_name)) {
        // Don't disable this group if it's for the pdf plugin and we just
        // forced it on.
        if (force_enable_internal_pdf && pdf_group_name == group_name)
          continue;

        // Otherwise this is a list of groups.
        EnablePluginGroup(false, group_name);
      }
    }
  }

  // Build the set of policy-disabled plugin patterns once and cache it.
  // Don't do this in the constructor, there's no profile available there.
  const ListValue* plugin_blacklist =
      profile->GetPrefs()->GetList(prefs::kPluginsPluginsBlacklist);
  DisablePluginsFromPolicy(plugin_blacklist);

  if (!enable_internal_pdf_ && !found_internal_pdf) {
    // The internal PDF plugin is disabled by default, and the user hasn't
    // overridden the default.
    NPAPI::PluginList::Singleton()->DisablePlugin(pdf_path);
    EnablePluginGroup(false, pdf_group_name);
  }

  if (force_enable_internal_pdf) {
    // See http://crbug.com/50105 for background.
    EnablePluginGroup(false, ASCIIToUTF16(PluginGroup::kAdobeReader8GroupName));
    EnablePluginGroup(false, ASCIIToUTF16(PluginGroup::kAdobeReader9GroupName));
    UpdatePreferences(profile);
  }
}

void PluginUpdater::UpdatePreferences(Profile* profile) {
  BrowserThread::PostTask(
    BrowserThread::FILE,
    FROM_HERE,
    NewRunnableFunction(
        &PluginUpdater::GetPreferencesDataOnFileThread, profile));
}

void PluginUpdater::GetPreferencesDataOnFileThread(void* profile) {
  std::vector<WebPluginInfo> plugins;
  NPAPI::PluginList::Singleton()->GetPlugins(false, &plugins);

  NPAPI::PluginList::PluginMap groups;
  NPAPI::PluginList::Singleton()->GetPluginGroups(false, &groups);

  BrowserThread::PostTask(
    BrowserThread::UI,
    FROM_HERE,
    NewRunnableFunction(
        &PluginUpdater::OnUpdatePreferences,
        static_cast<Profile*>(profile), plugins, groups));
}

void PluginUpdater::OnUpdatePreferences(
    Profile* profile,
    const std::vector<WebPluginInfo>& plugins,
    const NPAPI::PluginList::PluginMap& groups) {
  ListValue* plugins_list = profile->GetPrefs()->GetMutableList(
      prefs::kPluginsPluginsList);
  plugins_list->Clear();

  FilePath internal_dir;
  if (PathService::Get(chrome::DIR_INTERNAL_PLUGINS, &internal_dir))
    profile->GetPrefs()->SetFilePath(prefs::kPluginsLastInternalDirectory,
                                     internal_dir);

  // Add the plugin files.
  for (std::vector<WebPluginInfo>::const_iterator it = plugins.begin();
       it != plugins.end();
       ++it) {
    plugins_list->Append(CreatePluginFileSummary(*it));
  }

  // Add the groups as well.
  for (NPAPI::PluginList::PluginMap::const_iterator it = groups.begin();
       it != groups.end(); ++it) {
    // Don't save preferences for vulnerable pugins.
    if (!CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kDisableOutdatedPlugins) ||
        !it->second->IsVulnerable()) {
      plugins_list->Append(it->second->GetSummary());
    }
  }
}

void PluginUpdater::NotifyPluginStatusChanged() {
  if (notify_pending_)
    return;
  notify_pending_ = true;
  MessageLoop::current()->PostTask(
      FROM_HERE,
      NewRunnableFunction(&PluginUpdater::OnNotifyPluginStatusChanged));
}

void PluginUpdater::OnNotifyPluginStatusChanged() {
  GetPluginUpdater()->notify_pending_ = false;
  NotificationService::current()->Notify(
      NotificationType::PLUGIN_ENABLE_STATUS_CHANGED,
      Source<PluginUpdater>(GetPluginUpdater()),
      NotificationService::NoDetails());
}

/*static*/
PluginUpdater* PluginUpdater::GetPluginUpdater() {
  return Singleton<PluginUpdater>::get();
}
<commit_msg>Try to green the memory bots.  This is just a band-aid, since my previous change exposed the problem with tcmalloc being initialized twice by the test plugin.  The effect of this band-aid is that the settings won't be saved right away, which is what's loading the plugin.<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 "chrome/browser/plugin_updater.h"

#include <string>
#include <vector>

#include "base/command_line.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/scoped_ptr.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "base/version.h"
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profile.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/pepper_plugin_registry.h"
#include "chrome/common/pref_names.h"
#include "webkit/glue/plugins/webplugininfo.h"

PluginUpdater::PluginUpdater()
    : enable_internal_pdf_(true),
      notify_pending_(false) {
}

DictionaryValue* PluginUpdater::CreatePluginFileSummary(
    const WebPluginInfo& plugin) {
  DictionaryValue* data = new DictionaryValue();
  data->SetString("path", plugin.path.value());
  data->SetString("name", plugin.name);
  data->SetString("version", plugin.version);
  data->SetBoolean("enabled", plugin.enabled);
  return data;
}

// static
ListValue* PluginUpdater::GetPluginGroupsData() {
  NPAPI::PluginList::PluginMap plugin_groups;
  NPAPI::PluginList::Singleton()->GetPluginGroups(true, &plugin_groups);

  // Construct DictionaryValues to return to the UI
  ListValue* plugin_groups_data = new ListValue();
  for (NPAPI::PluginList::PluginMap::const_iterator it =
       plugin_groups.begin();
       it != plugin_groups.end();
       ++it) {
    plugin_groups_data->Append(it->second->GetDataForUI());
  }
  return plugin_groups_data;
}

void PluginUpdater::EnablePluginGroup(bool enable, const string16& group_name) {
  if (PluginGroup::IsPluginNameDisabledByPolicy(group_name))
    enable = false;
  NPAPI::PluginList::Singleton()->EnableGroup(enable, group_name);
  NotifyPluginStatusChanged();
}

void PluginUpdater::EnablePluginFile(bool enable,
                                     const FilePath::StringType& path) {
  FilePath file_path(path);
  if (enable && !PluginGroup::IsPluginPathDisabledByPolicy(file_path))
    NPAPI::PluginList::Singleton()->EnablePlugin(file_path);
  else
    NPAPI::PluginList::Singleton()->DisablePlugin(file_path);

  NotifyPluginStatusChanged();
}

void PluginUpdater::Observe(NotificationType type,
                            const NotificationSource& source,
                            const NotificationDetails& details) {
  DCHECK_EQ(NotificationType::PREF_CHANGED, type.value);
  const std::string* pref_name = Details<std::string>(details).ptr();
  if (!pref_name) {
    NOTREACHED();
    return;
  }
  if (*pref_name == prefs::kPluginsPluginsBlacklist) {
    PrefService* pref_service = Source<PrefService>(source).ptr();
    const ListValue* list =
        pref_service->GetList(prefs::kPluginsPluginsBlacklist);
    DisablePluginsFromPolicy(list);
  }
}

void PluginUpdater::DisablePluginsFromPolicy(const ListValue* plugin_names) {
  // Generate the set of unique disabled plugin patterns from the disabled
  // plugins list.
  std::set<string16> policy_disabled_plugin_patterns;
  if (plugin_names) {
    ListValue::const_iterator end(plugin_names->end());
    for (ListValue::const_iterator current(plugin_names->begin());
         current != end; ++current) {
      string16 plugin_name;
      if ((*current)->GetAsString(&plugin_name)) {
        policy_disabled_plugin_patterns.insert(plugin_name);
      }
    }
  }
  PluginGroup::SetPolicyDisabledPluginPatterns(policy_disabled_plugin_patterns);

  NotifyPluginStatusChanged();
}

void PluginUpdater::DisablePluginGroupsFromPrefs(Profile* profile) {
  bool update_internal_dir = false;
  FilePath last_internal_dir =
  profile->GetPrefs()->GetFilePath(prefs::kPluginsLastInternalDirectory);
  FilePath cur_internal_dir;
  if (PathService::Get(chrome::DIR_INTERNAL_PLUGINS, &cur_internal_dir) &&
      cur_internal_dir != last_internal_dir) {
    update_internal_dir = true;
    profile->GetPrefs()->SetFilePath(
        prefs::kPluginsLastInternalDirectory, cur_internal_dir);
  }

  if (!enable_internal_pdf_) {
    // This DCHECK guards against us disabling/enabling the pdf plugin more than
    // once without renaming the flag that tells us whether we can enable it
    // automatically.  Each time we disable the plugin by default after it was
    // enabled by default, we need to rename that flag.
    DCHECK(!profile->GetPrefs()->GetBoolean(prefs::kPluginsEnabledInternalPDF));
  }

  bool found_internal_pdf = false;
  bool force_enable_internal_pdf = false;
  string16 pdf_group_name = ASCIIToUTF16(PepperPluginRegistry::kPDFPluginName);
  FilePath pdf_path;
  PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf_path);
  FilePath::StringType pdf_path_str = pdf_path.value();
  if (enable_internal_pdf_ &&
      !profile->GetPrefs()->GetBoolean(prefs::kPluginsEnabledInternalPDF)) {
    // We switched to the internal pdf plugin being on by default, and so we
    // need to force it to be enabled.  We only want to do it this once though,
    // i.e. we don't want to enable it again if the user disables it afterwards.
    profile->GetPrefs()->SetBoolean(prefs::kPluginsEnabledInternalPDF, true);
    force_enable_internal_pdf = true;
  }

  if (ListValue* saved_plugins_list =
          profile->GetPrefs()->GetMutableList(prefs::kPluginsPluginsList)) {
    for (ListValue::const_iterator it = saved_plugins_list->begin();
         it != saved_plugins_list->end();
         ++it) {
      if (!(*it)->IsType(Value::TYPE_DICTIONARY)) {
        LOG(WARNING) << "Invalid entry in " << prefs::kPluginsPluginsList;
        continue;  // Oops, don't know what to do with this item.
      }

      DictionaryValue* plugin = static_cast<DictionaryValue*>(*it);
      string16 group_name;
      bool enabled = true;
      plugin->GetBoolean("enabled", &enabled);

      FilePath::StringType path;
      // The plugin list constains all the plugin files in addition to the
      // plugin groups.
      if (plugin->GetString("path", &path)) {
        // Files have a path attribute, groups don't.
        FilePath plugin_path(path);
        if (update_internal_dir &&
            FilePath::CompareIgnoreCase(plugin_path.DirName().value(),
                last_internal_dir.value()) == 0) {
          // If the internal plugin directory has changed and if the plugin
          // looks internal, update its path in the prefs.
          plugin_path = cur_internal_dir.Append(plugin_path.BaseName());
          path = plugin_path.value();
          plugin->SetString("path", path);
        }

        if (FilePath::CompareIgnoreCase(path, pdf_path_str) == 0) {
          found_internal_pdf = true;
          if (!enabled && force_enable_internal_pdf) {
            enabled = true;
            plugin->SetBoolean("enabled", true);
          }
        }
        if (!enabled)
          NPAPI::PluginList::Singleton()->DisablePlugin(plugin_path);
      } else if (!enabled && plugin->GetString("name", &group_name)) {
        // Don't disable this group if it's for the pdf plugin and we just
        // forced it on.
        if (force_enable_internal_pdf && pdf_group_name == group_name)
          continue;

        // Otherwise this is a list of groups.
        EnablePluginGroup(false, group_name);
      }
    }
  }

  // Build the set of policy-disabled plugin patterns once and cache it.
  // Don't do this in the constructor, there's no profile available there.
  const ListValue* plugin_blacklist =
      profile->GetPrefs()->GetList(prefs::kPluginsPluginsBlacklist);
  DisablePluginsFromPolicy(plugin_blacklist);

  if (!enable_internal_pdf_ && !found_internal_pdf) {
    // The internal PDF plugin is disabled by default, and the user hasn't
    // overridden the default.
    NPAPI::PluginList::Singleton()->DisablePlugin(pdf_path);
    EnablePluginGroup(false, pdf_group_name);
  }

  if (force_enable_internal_pdf) {
    // See http://crbug.com/50105 for background.
    EnablePluginGroup(false, ASCIIToUTF16(PluginGroup::kAdobeReader8GroupName));
    EnablePluginGroup(false, ASCIIToUTF16(PluginGroup::kAdobeReader9GroupName));
  }
}

void PluginUpdater::UpdatePreferences(Profile* profile) {
  BrowserThread::PostTask(
    BrowserThread::FILE,
    FROM_HERE,
    NewRunnableFunction(
        &PluginUpdater::GetPreferencesDataOnFileThread, profile));
}

void PluginUpdater::GetPreferencesDataOnFileThread(void* profile) {
  std::vector<WebPluginInfo> plugins;
  NPAPI::PluginList::Singleton()->GetPlugins(false, &plugins);

  NPAPI::PluginList::PluginMap groups;
  NPAPI::PluginList::Singleton()->GetPluginGroups(false, &groups);

  BrowserThread::PostTask(
    BrowserThread::UI,
    FROM_HERE,
    NewRunnableFunction(
        &PluginUpdater::OnUpdatePreferences,
        static_cast<Profile*>(profile), plugins, groups));
}

void PluginUpdater::OnUpdatePreferences(
    Profile* profile,
    const std::vector<WebPluginInfo>& plugins,
    const NPAPI::PluginList::PluginMap& groups) {
  ListValue* plugins_list = profile->GetPrefs()->GetMutableList(
      prefs::kPluginsPluginsList);
  plugins_list->Clear();

  FilePath internal_dir;
  if (PathService::Get(chrome::DIR_INTERNAL_PLUGINS, &internal_dir))
    profile->GetPrefs()->SetFilePath(prefs::kPluginsLastInternalDirectory,
                                     internal_dir);

  // Add the plugin files.
  for (std::vector<WebPluginInfo>::const_iterator it = plugins.begin();
       it != plugins.end();
       ++it) {
    plugins_list->Append(CreatePluginFileSummary(*it));
  }

  // Add the groups as well.
  for (NPAPI::PluginList::PluginMap::const_iterator it = groups.begin();
       it != groups.end(); ++it) {
    // Don't save preferences for vulnerable pugins.
    if (!CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kDisableOutdatedPlugins) ||
        !it->second->IsVulnerable()) {
      plugins_list->Append(it->second->GetSummary());
    }
  }
}

void PluginUpdater::NotifyPluginStatusChanged() {
  if (notify_pending_)
    return;
  notify_pending_ = true;
  MessageLoop::current()->PostTask(
      FROM_HERE,
      NewRunnableFunction(&PluginUpdater::OnNotifyPluginStatusChanged));
}

void PluginUpdater::OnNotifyPluginStatusChanged() {
  GetPluginUpdater()->notify_pending_ = false;
  NotificationService::current()->Notify(
      NotificationType::PLUGIN_ENABLE_STATUS_CHANGED,
      Source<PluginUpdater>(GetPluginUpdater()),
      NotificationService::NoDetails());
}

/*static*/
PluginUpdater* PluginUpdater::GetPluginUpdater() {
  return Singleton<PluginUpdater>::get();
}
<|endoftext|>


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

/**
 * \file brw_lower_texture_gradients.cpp
 */

#include "glsl/ir.h"
#include "glsl/ir_builder.h"
#include "program/prog_instruction.h"
#include "brw_context.h"

using namespace ir_builder;

class lower_texture_grad_visitor : public ir_hierarchical_visitor {
public:
   lower_texture_grad_visitor(bool has_sample_d_c)
      : has_sample_d_c(has_sample_d_c)
   {
      progress = false;
   }

   ir_visitor_status visit_leave(ir_texture *ir);

   bool progress;
   bool has_sample_d_c;

private:
   void emit(ir_variable *, ir_rvalue *);
};

/**
 * Emit a variable declaration and an assignment to initialize it.
 */
void
lower_texture_grad_visitor::emit(ir_variable *var, ir_rvalue *value)
{
   base_ir->insert_before(var);
   base_ir->insert_before(assign(var, value));
}

static const glsl_type *
txs_type(const glsl_type *type)
{
   unsigned dims;
   switch (type->sampler_dimensionality) {
   case GLSL_SAMPLER_DIM_1D:
      dims = 1;
      break;
   case GLSL_SAMPLER_DIM_2D:
   case GLSL_SAMPLER_DIM_RECT:
   case GLSL_SAMPLER_DIM_CUBE:
      dims = 2;
      break;
   case GLSL_SAMPLER_DIM_3D:
      dims = 3;
      break;
   default:
      unreachable("Should not get here: invalid sampler dimensionality");
   }

   if (type->sampler_array)
      dims++;

   return glsl_type::get_instance(GLSL_TYPE_INT, dims, 1);
}

ir_visitor_status
lower_texture_grad_visitor::visit_leave(ir_texture *ir)
{
   /* Only lower textureGrad with shadow samplers */
   if (ir->op != ir_txd || !ir->shadow_comparitor)
      return visit_continue;

   /* Lower textureGrad() with samplerCubeShadow even if we have the sample_d_c
    * message.  GLSL provides gradients for the 'r' coordinate.  Unfortunately:
    *
    * From the Ivybridge PRM, Volume 4, Part 1, sample_d message description:
    * "The r coordinate contains the faceid, and the r gradients are ignored
    *  by hardware."
    *
    * We likely need to do a similar treatment for samplerCube and
    * samplerCubeArray, but we have insufficient testing for that at the moment.
    */
   bool need_lowering = !has_sample_d_c ||
      ir->sampler->type->sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE;

   if (!need_lowering)
      return visit_continue;

   void *mem_ctx = ralloc_parent(ir);

   const glsl_type *grad_type = ir->lod_info.grad.dPdx->type;

   /* Use textureSize() to get the width and height of LOD 0; swizzle away
    * the depth/number of array slices.
    */
   ir_texture *txs = new(mem_ctx) ir_texture(ir_txs);
   txs->set_sampler(ir->sampler->clone(mem_ctx, NULL),
		    txs_type(ir->sampler->type));
   txs->lod_info.lod = new(mem_ctx) ir_constant(0);
   ir_variable *size =
      new(mem_ctx) ir_variable(grad_type, "size", ir_var_temporary);
   if (ir->sampler->type->sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE) {
      base_ir->insert_before(size);
      base_ir->insert_before(assign(size, expr(ir_unop_i2f, txs), WRITEMASK_XY));
      base_ir->insert_before(assign(size, new(mem_ctx) ir_constant(1.0f), WRITEMASK_Z));
   } else {
      emit(size, expr(ir_unop_i2f,
                      swizzle_for_size(txs, grad_type->vector_elements)));
   }

   /* Scale the gradients by width and height.  Effectively, the incoming
    * gradients are s'(x,y), t'(x,y), and r'(x,y) from equation 3.19 in the
    * GL 3.0 spec; we want u'(x,y), which is w_t * s'(x,y).
    */
   ir_variable *dPdx =
      new(mem_ctx) ir_variable(grad_type, "dPdx", ir_var_temporary);
   emit(dPdx, mul(size, ir->lod_info.grad.dPdx));

   ir_variable *dPdy =
      new(mem_ctx) ir_variable(grad_type, "dPdy", ir_var_temporary);
   emit(dPdy, mul(size, ir->lod_info.grad.dPdy));

   /* Calculate rho from equation 3.20 of the GL 3.0 specification. */
   ir_rvalue *rho;
   if (dPdx->type->is_scalar()) {
      rho = expr(ir_binop_max, expr(ir_unop_abs, dPdx),
			       expr(ir_unop_abs, dPdy));
   } else {
      rho = expr(ir_binop_max, expr(ir_unop_sqrt, dot(dPdx, dPdx)),
			       expr(ir_unop_sqrt, dot(dPdy, dPdy)));
   }

   /* lambda_base = log2(rho).  We're ignoring GL state biases for now. */
   ir->op = ir_txl;
   ir->lod_info.lod = expr(ir_unop_log2, rho);

   progress = true;
   return visit_continue;
}

extern "C" {

bool
brw_lower_texture_gradients(struct brw_context *brw,
                            struct exec_list *instructions)
{
   bool has_sample_d_c = brw->gen >= 8 || brw->is_haswell;
   lower_texture_grad_visitor v(has_sample_d_c);

   visit_list_elements(&v, instructions);

   return v.progress;
}

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

/**
 * \file brw_lower_texture_gradients.cpp
 */

#include "glsl/ir.h"
#include "glsl/ir_builder.h"
#include "program/prog_instruction.h"
#include "brw_context.h"

using namespace ir_builder;

class lower_texture_grad_visitor : public ir_hierarchical_visitor {
public:
   lower_texture_grad_visitor(bool has_sample_d_c)
      : has_sample_d_c(has_sample_d_c)
   {
      progress = false;
   }

   ir_visitor_status visit_leave(ir_texture *ir);

   bool progress;
   bool has_sample_d_c;

private:
   void emit(ir_variable *, ir_rvalue *);
};

/**
 * Emit a variable declaration and an assignment to initialize it.
 */
void
lower_texture_grad_visitor::emit(ir_variable *var, ir_rvalue *value)
{
   base_ir->insert_before(var);
   base_ir->insert_before(assign(var, value));
}

static const glsl_type *
txs_type(const glsl_type *type)
{
   unsigned dims;
   switch (type->sampler_dimensionality) {
   case GLSL_SAMPLER_DIM_1D:
      dims = 1;
      break;
   case GLSL_SAMPLER_DIM_2D:
   case GLSL_SAMPLER_DIM_RECT:
   case GLSL_SAMPLER_DIM_CUBE:
      dims = 2;
      break;
   case GLSL_SAMPLER_DIM_3D:
      dims = 3;
      break;
   default:
      unreachable("Should not get here: invalid sampler dimensionality");
   }

   if (type->sampler_array)
      dims++;

   return glsl_type::get_instance(GLSL_TYPE_INT, dims, 1);
}

ir_visitor_status
lower_texture_grad_visitor::visit_leave(ir_texture *ir)
{
   /* Only lower textureGrad with shadow samplers */
   if (ir->op != ir_txd || !ir->shadow_comparitor)
      return visit_continue;

   /* Lower textureGrad() with samplerCubeShadow even if we have the sample_d_c
    * message.  GLSL provides gradients for the 'r' coordinate.  Unfortunately:
    *
    * From the Ivybridge PRM, Volume 4, Part 1, sample_d message description:
    * "The r coordinate contains the faceid, and the r gradients are ignored
    *  by hardware."
    *
    * We likely need to do a similar treatment for samplerCube and
    * samplerCubeArray, but we have insufficient testing for that at the moment.
    */
   bool need_lowering = !has_sample_d_c ||
      ir->sampler->type->sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE;

   if (!need_lowering)
      return visit_continue;

   void *mem_ctx = ralloc_parent(ir);

   const glsl_type *grad_type = ir->lod_info.grad.dPdx->type;

   /* Use textureSize() to get the width and height of LOD 0; swizzle away
    * the depth/number of array slices.
    */
   ir_texture *txs = new(mem_ctx) ir_texture(ir_txs);
   txs->set_sampler(ir->sampler->clone(mem_ctx, NULL),
		    txs_type(ir->sampler->type));
   txs->lod_info.lod = new(mem_ctx) ir_constant(0);
   ir_variable *size =
      new(mem_ctx) ir_variable(grad_type, "size", ir_var_temporary);
   if (ir->sampler->type->sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE) {
      base_ir->insert_before(size);
      base_ir->insert_before(assign(size,
                                    swizzle_for_size(expr(ir_unop_i2f, txs), 2),
                                    WRITEMASK_XY));
      base_ir->insert_before(assign(size, new(mem_ctx) ir_constant(1.0f), WRITEMASK_Z));
   } else {
      emit(size, expr(ir_unop_i2f,
                      swizzle_for_size(txs, grad_type->vector_elements)));
   }

   /* Scale the gradients by width and height.  Effectively, the incoming
    * gradients are s'(x,y), t'(x,y), and r'(x,y) from equation 3.19 in the
    * GL 3.0 spec; we want u'(x,y), which is w_t * s'(x,y).
    */
   ir_variable *dPdx =
      new(mem_ctx) ir_variable(grad_type, "dPdx", ir_var_temporary);
   emit(dPdx, mul(size, ir->lod_info.grad.dPdx));

   ir_variable *dPdy =
      new(mem_ctx) ir_variable(grad_type, "dPdy", ir_var_temporary);
   emit(dPdy, mul(size, ir->lod_info.grad.dPdy));

   /* Calculate rho from equation 3.20 of the GL 3.0 specification. */
   ir_rvalue *rho;
   if (dPdx->type->is_scalar()) {
      rho = expr(ir_binop_max, expr(ir_unop_abs, dPdx),
			       expr(ir_unop_abs, dPdy));
   } else {
      rho = expr(ir_binop_max, expr(ir_unop_sqrt, dot(dPdx, dPdx)),
			       expr(ir_unop_sqrt, dot(dPdy, dPdy)));
   }

   /* lambda_base = log2(rho).  We're ignoring GL state biases for now. */
   ir->op = ir_txl;
   ir->lod_info.lod = expr(ir_unop_log2, rho);

   progress = true;
   return visit_continue;
}

extern "C" {

bool
brw_lower_texture_gradients(struct brw_context *brw,
                            struct exec_list *instructions)
{
   bool has_sample_d_c = brw->gen >= 8 || brw->is_haswell;
   lower_texture_grad_visitor v(has_sample_d_c);

   visit_list_elements(&v, instructions);

   return v.progress;
}

}
<|endoftext|>


<commit_before>
#include <Beard/utility.hpp>
#include <Beard/keys.hpp>
#include <Beard/geometry.hpp>
#include <Beard/txt/Defs.hpp>
#include <Beard/tty/Defs.hpp>
#include <Beard/tty/Terminal.hpp>
#include <Beard/ui/Root.hpp>
#include <Beard/ui/Field.hpp>

#include <duct/CharacterSet.hpp>

#include <iostream>

namespace Beard {
namespace ui {

// class Field implementation

namespace {
static ui::Widget::type_info const
s_type_info{
	ui::Widget::Type::Field,
	enum_combine(
		ui::Widget::TypeFlags::focusable
	)
};
} // anonymous namespace

Field::~Field() noexcept = default;

void
Field::update_view() noexcept {
	if (!has_input_control()) {
		m_view.col_extent(txt::Extent::head);
	} else {
		auto const& frame = get_geometry().get_frame();
		auto const inner_width = max_ce(0, frame.size.width - 2 - 1);
		if (
			m_view.col() > m_cursor.col() ||
			m_view.col() + inner_width < m_cursor.col()
		) {
			m_view.col_abs(
				m_cursor.col() - (inner_width * 0.5)
			);
		}
	}
}

// implementation

ui::Widget::type_info const&
Field::get_type_info_impl() const noexcept {
	return s_type_info;
}

void
Field::reflow_impl(
	Rect const& area,
	bool const cache
) noexcept {
	base_type::reflow_impl(area, cache);
	update_view();
}

namespace {
static KeyInputMatch const
s_kim_icontrol[]{
	{KeyMod::none, KeyCode::enter, codepoint_none, false}/*,
	{KeyMod::none, KeyCode::none, ' ', false}*/
};

static duct::CharacterSet const
s_input_blacklist{
	"\t"
};
}; // anonymous namespace

bool
Field::handle_event_impl(
	ui::Event const& event
) noexcept {
	switch (event.type) {
	case ui::EventType::key_input:
		if (
			key_input_match(event.key_input, s_kim_icontrol) ||
			(has_input_control() && KeyCode::esc == event.key_input.code)
		) {
			set_input_control(!has_input_control());
			signal_control_changed(
				std::move(std::static_pointer_cast<ui::Field>(
					shared_from_this()
				)),
				has_input_control()
			);
			get_root()->get_context().get_terminal().set_caret_visible(
				has_input_control()
			);
			/*m_cursor.col_extent(
				has_input_control()
				? txt::Extent::tail
				: txt::Extent::head
			);*/
			update_view();
			queue_actions(enum_combine(
				ui::UpdateActions::render,
				ui::UpdateActions::flag_noclear
			));
			return true;
		} else if (has_input_control()) {
			switch (event.key_input.code) {
			case KeyCode::up   : m_cursor.row_prev(); break;
			case KeyCode::down : m_cursor.row_next(); break;
			case KeyCode::left : m_cursor.col_prev(); break;
			case KeyCode::right: m_cursor.col_next(); break;
			case KeyCode::home: m_cursor.col_extent(txt::Extent::head); break;
			case KeyCode::end : m_cursor.col_extent(txt::Extent::tail); break;
			case KeyCode::del      : m_cursor.erase(); break;
			case KeyCode::backspace: m_cursor.erase_before(); break;
			default:
				if (
					codepoint_none != event.key_input.cp &&
					(!m_filter || m_filter(event.key_input.cp)) &&
					!s_input_blacklist.contains(event.key_input.cp)
				) {
					m_cursor.insert_step(event.key_input.cp);
				}
				break;
			}
			update_view();
			queue_actions(enum_combine(
				ui::UpdateActions::render,
				ui::UpdateActions::flag_noclear
			));
			return true;
		}
		break;

	default:
		break;
	}
	return false;
}

void
Field::render_impl(
	ui::Widget::RenderData& rd
) noexcept {
	auto const& frame = get_geometry().get_frame();
	auto const& node = m_cursor.get_node();

	bool const use_underline = rd.get_boolean(
		ui::property_field_content_underline
	);
	tty::attr_type const
		content_fg
		= (use_underline) ? tty::Attr::underline : 0
		| rd.get_attr(is_focused()
			? ui::property_content_fg_active
			: ui::property_content_fg_inactive
		),
		content_bg
		= rd.get_attr(is_focused()
			? ui::property_content_bg_active
			: ui::property_content_bg_inactive
		)
	;
	tty::Cell cell_end = tty::make_cell(
		'[',
		rd.get_attr(is_focused()
			? ui::property_primary_fg_active
			: ui::property_primary_fg_inactive
		),
		rd.get_attr(is_focused()
			? ui::property_primary_bg_active
			: ui::property_primary_bg_inactive
		)
	);
	rd.terminal.put_cell(frame.pos.x, frame.pos.y, cell_end);
	auto const inner_width = max_ce(geom_value_type{0}, frame.size.width - 2);
	auto const put_count = min_ce(
		static_cast<txt::Cursor::difference_type>(inner_width),
		max_ce(
			txt::Cursor::difference_type{0},
			signed_cast(node.points()) - m_view.col()
		)
	);
	rd.terminal.put_sequence(
		frame.pos.x + 1,
		frame.pos.y,
		txt::Sequence{
			&*node.cbegin() + m_view.index(),
			unsigned_cast(max_ce(
				txt::Cursor::difference_type{0},
				signed_cast(node.units()) - m_view.index()
			))
		},
		put_count,
		content_fg,
		content_bg
	);
	tty::Cell const cell_ul = tty::make_cell(
		' ',
		content_fg,
		content_bg
	);
	rd.terminal.put_line(
		{static_cast<geom_value_type>(frame.pos.x + 1 + put_count), frame.pos.y},
		inner_width - put_count,
		Axis::horizontal,
		cell_ul
	);
	cell_end.u8block.assign(']');
	rd.terminal.put_cell(
		frame.pos.x + frame.size.width - 1,
		frame.pos.y,
		cell_end
	);
	if (has_input_control()) {
		rd.terminal.set_caret_pos(
			frame.pos.x
			+ min_ce(
				inner_width,
				1 + static_cast<geom_value_type>(
					m_cursor.col() - m_view.col()
				)
			),
			frame.pos.y
		);
	}
}

// properties

void
Field::set_text(
	String const& text
) {
	m_cursor.col_extent(txt::Extent::head);
	m_cursor.assign(text);
	m_cursor.col_extent(txt::Extent::tail);
	update_view();
	queue_actions(enum_combine(
		ui::UpdateActions::flag_parent,
		ui::UpdateActions::reflow,
		ui::UpdateActions::render
	));
}

} // namespace ui
} // namespace Beard
<commit_msg>ui::Field: changed floating-point op to an integer op (x*0.5 to x/2).<commit_after>
#include <Beard/utility.hpp>
#include <Beard/keys.hpp>
#include <Beard/geometry.hpp>
#include <Beard/txt/Defs.hpp>
#include <Beard/tty/Defs.hpp>
#include <Beard/tty/Terminal.hpp>
#include <Beard/ui/Root.hpp>
#include <Beard/ui/Field.hpp>

#include <duct/CharacterSet.hpp>

#include <iostream>

namespace Beard {
namespace ui {

// class Field implementation

namespace {
static ui::Widget::type_info const
s_type_info{
	ui::Widget::Type::Field,
	enum_combine(
		ui::Widget::TypeFlags::focusable
	)
};
} // anonymous namespace

Field::~Field() noexcept = default;

void
Field::update_view() noexcept {
	if (!has_input_control()) {
		m_view.col_extent(txt::Extent::head);
	} else {
		auto const& frame = get_geometry().get_frame();
		auto const inner_width = max_ce(0, frame.size.width - 2 - 1);
		if (
			m_view.col() > m_cursor.col() ||
			m_view.col() + inner_width < m_cursor.col()
		) {
			m_view.col_abs(
				m_cursor.col() - (inner_width / 2)
			);
		}
	}
}

// implementation

ui::Widget::type_info const&
Field::get_type_info_impl() const noexcept {
	return s_type_info;
}

void
Field::reflow_impl(
	Rect const& area,
	bool const cache
) noexcept {
	base_type::reflow_impl(area, cache);
	update_view();
}

namespace {
static KeyInputMatch const
s_kim_icontrol[]{
	{KeyMod::none, KeyCode::enter, codepoint_none, false}/*,
	{KeyMod::none, KeyCode::none, ' ', false}*/
};

static duct::CharacterSet const
s_input_blacklist{
	"\t"
};
}; // anonymous namespace

bool
Field::handle_event_impl(
	ui::Event const& event
) noexcept {
	switch (event.type) {
	case ui::EventType::key_input:
		if (
			key_input_match(event.key_input, s_kim_icontrol) ||
			(has_input_control() && KeyCode::esc == event.key_input.code)
		) {
			set_input_control(!has_input_control());
			signal_control_changed(
				std::move(std::static_pointer_cast<ui::Field>(
					shared_from_this()
				)),
				has_input_control()
			);
			get_root()->get_context().get_terminal().set_caret_visible(
				has_input_control()
			);
			/*m_cursor.col_extent(
				has_input_control()
				? txt::Extent::tail
				: txt::Extent::head
			);*/
			update_view();
			queue_actions(enum_combine(
				ui::UpdateActions::render,
				ui::UpdateActions::flag_noclear
			));
			return true;
		} else if (has_input_control()) {
			switch (event.key_input.code) {
			case KeyCode::up   : m_cursor.row_prev(); break;
			case KeyCode::down : m_cursor.row_next(); break;
			case KeyCode::left : m_cursor.col_prev(); break;
			case KeyCode::right: m_cursor.col_next(); break;
			case KeyCode::home: m_cursor.col_extent(txt::Extent::head); break;
			case KeyCode::end : m_cursor.col_extent(txt::Extent::tail); break;
			case KeyCode::del      : m_cursor.erase(); break;
			case KeyCode::backspace: m_cursor.erase_before(); break;
			default:
				if (
					codepoint_none != event.key_input.cp &&
					(!m_filter || m_filter(event.key_input.cp)) &&
					!s_input_blacklist.contains(event.key_input.cp)
				) {
					m_cursor.insert_step(event.key_input.cp);
				}
				break;
			}
			update_view();
			queue_actions(enum_combine(
				ui::UpdateActions::render,
				ui::UpdateActions::flag_noclear
			));
			return true;
		}
		break;

	default:
		break;
	}
	return false;
}

void
Field::render_impl(
	ui::Widget::RenderData& rd
) noexcept {
	auto const& frame = get_geometry().get_frame();
	auto const& node = m_cursor.get_node();

	bool const use_underline = rd.get_boolean(
		ui::property_field_content_underline
	);
	tty::attr_type const
		content_fg
		= (use_underline) ? tty::Attr::underline : 0
		| rd.get_attr(is_focused()
			? ui::property_content_fg_active
			: ui::property_content_fg_inactive
		),
		content_bg
		= rd.get_attr(is_focused()
			? ui::property_content_bg_active
			: ui::property_content_bg_inactive
		)
	;
	tty::Cell cell_end = tty::make_cell(
		'[',
		rd.get_attr(is_focused()
			? ui::property_primary_fg_active
			: ui::property_primary_fg_inactive
		),
		rd.get_attr(is_focused()
			? ui::property_primary_bg_active
			: ui::property_primary_bg_inactive
		)
	);
	rd.terminal.put_cell(frame.pos.x, frame.pos.y, cell_end);
	auto const inner_width = max_ce(geom_value_type{0}, frame.size.width - 2);
	auto const put_count = min_ce(
		static_cast<txt::Cursor::difference_type>(inner_width),
		max_ce(
			txt::Cursor::difference_type{0},
			signed_cast(node.points()) - m_view.col()
		)
	);
	rd.terminal.put_sequence(
		frame.pos.x + 1,
		frame.pos.y,
		txt::Sequence{
			&*node.cbegin() + m_view.index(),
			unsigned_cast(max_ce(
				txt::Cursor::difference_type{0},
				signed_cast(node.units()) - m_view.index()
			))
		},
		put_count,
		content_fg,
		content_bg
	);
	tty::Cell const cell_ul = tty::make_cell(
		' ',
		content_fg,
		content_bg
	);
	rd.terminal.put_line(
		{static_cast<geom_value_type>(frame.pos.x + 1 + put_count), frame.pos.y},
		inner_width - put_count,
		Axis::horizontal,
		cell_ul
	);
	cell_end.u8block.assign(']');
	rd.terminal.put_cell(
		frame.pos.x + frame.size.width - 1,
		frame.pos.y,
		cell_end
	);
	if (has_input_control()) {
		rd.terminal.set_caret_pos(
			frame.pos.x
			+ min_ce(
				inner_width,
				1 + static_cast<geom_value_type>(
					m_cursor.col() - m_view.col()
				)
			),
			frame.pos.y
		);
	}
}

// properties

void
Field::set_text(
	String const& text
) {
	m_cursor.col_extent(txt::Extent::head);
	m_cursor.assign(text);
	m_cursor.col_extent(txt::Extent::tail);
	update_view();
	queue_actions(enum_combine(
		ui::UpdateActions::flag_parent,
		ui::UpdateActions::reflow,
		ui::UpdateActions::render
	));
}

} // namespace ui
} // namespace Beard
<|endoftext|>


<commit_before>/*
 * This file is part of the CN24 semantic segmentation software,
 * copyright (C) 2015 Clemens-Alexander Brust (ikosa dot de at gmail dot com).
 *
 * For licensing information, see the LICENSE file included with this project.
 */

#include <cn24.h>

#include <vector>
#include <string>
#include <cmath>
#include <random>

// TEST SETUP
std::vector<std::string> test_layers_noseed = {
  "maxpooling(size=3x3)",
  "amaxpooling(size=3x3)",
  "amaxpooling(size=3x3 stride=2x2)",
  "convolution(size=3x3 kernels=3)",
  "convolution(size=3x3 stride=2x2 kernels=3)",
  "convolution(size=3x3 group=3 kernels=9)",
  "tanh","sigm","relu"
};

unsigned int SAMPLES = 2, WIDTH = 9, HEIGHT = 6, MAPS = 3;
unsigned int SEEDS = 3;
Conv::datum epsilon = 0.005;

// UTILITIES
Conv::datum SimpleSumLoss(const Conv::Tensor& tensor) {
  Conv::datum sum = 0;

  for (unsigned int e = 0; e < tensor.elements(); e++) {
    const Conv::datum element = tensor.data_ptr_const()[e];
    sum += fabs(element);
  }

  return sum;
}

Conv::datum SimpleSumLoss(const std::vector<Conv::CombinedTensor*>& outputs) {
  Conv::datum sum = 0;

  for (unsigned int o = 0; o < outputs.size(); o++) {
    sum += SimpleSumLoss(outputs[o]->data);
  }

  return sum;
}

void SimpleSumLossGradient(const std::vector<Conv::CombinedTensor*>& outputs) {
  for (unsigned int o = 0; o < outputs.size(); o++) {
    Conv::Tensor& tensor = outputs[o]->data;
    Conv::Tensor& delta_tensor = outputs[o]->delta;
    for (unsigned int e = 0; e < tensor.elements(); e++) {
      const Conv::datum element = tensor.data_ptr_const()[e];
      const Conv::datum gradient = element > 0.0 ? 1.0 : -1.0;
      delta_tensor.data_ptr()[e] = gradient;
    }
  }
}

namespace Conv {
  bool DoGradientTest(Conv::Layer* layer, Conv::Tensor& data, Conv::Tensor& delta, std::vector<Conv::CombinedTensor*>& outputs, Conv::datum epsilon) {
    layer->FeedForward();
    SimpleSumLossGradient(outputs);
    layer->BackPropagate();

    unsigned int elements = data.elements();
    unsigned int okay = 0;

    // Weight gradient test
    for (unsigned int w = 0; w < data.elements(); w++) {
      const Conv::datum weight = data.data_ptr_const()[w];
      const Conv::datum gradient = delta.data_ptr_const()[w];

      // Using central diff
      data.data_ptr()[w] = weight + epsilon;
      layer->FeedForward();
      const Conv::datum forward_loss = SimpleSumLoss(outputs);

      data.data_ptr()[w] = weight - epsilon;
      layer->FeedForward();
      const Conv::datum backward_loss = SimpleSumLoss(outputs);

      const Conv::datum fd_gradient = (forward_loss - backward_loss) / (2.0 * epsilon);
      data.data_ptr()[w] = weight;

      const Conv::datum ratio = fd_gradient / gradient;
      if(ratio > 1.2 || ratio < 0.8) {
        LOGDEBUG << "BP Grad : " << gradient;
        LOGDEBUG << "FD Grad : " << fd_gradient;
        LOGDEBUG << "Ratio   : " << ratio;
        LOGDEBUG << "Diff    : " << gradient - fd_gradient;
      } else {
        okay++;
      }
    }
    if(okay != elements) {
      double success_rate = (double)okay/(double)elements;
      if(success_rate > 0.95)
        return true;
      else {
        LOGERROR << okay << " of " << elements << " gradients okay - " << std::setprecision(3) << 100.0 * (double)okay/(double)elements << "%";
        return false;
      }
    } else {
      return true;
    }
  }
}

int main(int argc, char* argv[]) {
  if(argc > 1)
    Conv::System::Init(3);
  else
    Conv::System::Init();

  std::mt19937 seed_generator(93023);
  std::uniform_real_distribution<Conv::datum> dist(1.0, 2.0);

  Conv::NetStatus net_status;
  net_status.SetIsTesting(true);

  bool test_failed = false;

  Conv::CombinedTensor input_data(SAMPLES, WIDTH, HEIGHT, MAPS);

  std::vector<std::string> test_layers;

  // Inject random seeds
  for (std::string& layer_descriptor : test_layers_noseed) {
    for(unsigned int i = 0; i < SEEDS; i++) {
      std::string injected_descriptor = Conv::LayerFactory::InjectSeed(layer_descriptor, seed_generator());
      test_layers.push_back(injected_descriptor);
    }
  }

  for (std::string& layer_descriptor : test_layers) {
    bool data_sign = seed_generator() % 2 == 0;
    for(unsigned int e = 0; e < input_data.data.elements(); e++) {
      if(data_sign)
        input_data.data.data_ptr()[e] = dist(seed_generator);
      else
        input_data.data.data_ptr()[e] = -dist(seed_generator);
    }
    input_data.delta.Clear(0.0);

    LOGINFO << "Testing layer: " << layer_descriptor;
    Conv::Layer* layer = Conv::LayerFactory::ConstructLayer(layer_descriptor);
    if(layer == nullptr) {
      test_failed = true;
      LOGERROR << "        FAILED";
      continue;
    }

    LOGDEBUG << "    Description: " << layer->GetLayerDescription();

    std::vector<Conv::CombinedTensor*> outputs;
    bool createoutputs_success = layer->CreateOutputs({&input_data}, outputs);
    if(!createoutputs_success) {
      test_failed = true;
      LOGINFO << "    Creating outputs...";
      LOGERROR << "       FAILED";
      continue;
    }

    for(Conv::CombinedTensor* output : outputs) {
      LOGDEBUG << "        Output: " << output->data;
    }

    bool connect_success = layer->Connect({&input_data}, outputs, &net_status);
    if(!connect_success) {
      test_failed = true;
      LOGINFO << "    Connecting...";
      LOGERROR << "        FAILED";
      continue;
    }

    layer->OnLayerConnect({});

    for(Conv::CombinedTensor* weights : layer->parameters()) {
      bool gradient_success = Conv::DoGradientTest(layer, weights->data, weights->delta, outputs, epsilon);
      if(!gradient_success) {
        test_failed = true;
        LOGINFO << "    Gradient test (weights)...";
        LOGERROR << "        FAILED";
        continue;
      }
    }

    bool gradient_success = Conv::DoGradientTest(layer, input_data.data, input_data.delta, outputs, epsilon);
    if(!gradient_success) {
      test_failed = true;
      LOGINFO << "    Gradient test (inputs)...";
      LOGERROR << "        FAILED";
      continue;
    }

    delete layer;
    for(Conv::CombinedTensor* output : outputs)
      delete output;
  }

  LOGEND;
  return test_failed ? -1 : 0;
}<commit_msg>SingleLayerGradientTest: Added separate run counts per layer, reduced required okayness for gradients to 85% per set<commit_after>/*
 * This file is part of the CN24 semantic segmentation software,
 * copyright (C) 2015 Clemens-Alexander Brust (ikosa dot de at gmail dot com).
 *
 * For licensing information, see the LICENSE file included with this project.
 */

#include <cn24.h>

#include <vector>
#include <utility>
#include <string>
#include <cmath>
#include <random>

// TEST SETUP
unsigned int RANDOM_RUNS = 15;
unsigned int SAMPLES = 2, WIDTH = 9, HEIGHT = 6, MAPS = 3;
Conv::datum epsilon = 0.005;

std::vector<std::pair<std::string, unsigned int>> test_layers_and_runs = {
  {"maxpooling(size=3x3)",1},
  {"maxpooling(size=3x2)",1},
  {"amaxpooling(size=3x3)",1},
  {"amaxpooling(size=3x2)",1},
  {"amaxpooling(size=3x3 stride=2x2)",1},
  {"convolution(size=3x3 kernels=3)",RANDOM_RUNS},
  {"convolution(size=3x3 stride=2x2 kernels=3)",RANDOM_RUNS},
  {"convolution(size=3x3 group=3 kernels=9)",RANDOM_RUNS},
  {"tanh",1},{"sigm",1},{"relu",1}
};

// UTILITIES
Conv::datum SimpleSumLoss(const Conv::Tensor& tensor) {
  Conv::datum sum = 0;

  for (unsigned int e = 0; e < tensor.elements(); e++) {
    const Conv::datum element = tensor.data_ptr_const()[e];
    sum += fabs(element);
  }

  return sum;
}

Conv::datum SimpleSumLoss(const std::vector<Conv::CombinedTensor*>& outputs) {
  Conv::datum sum = 0;

  for (unsigned int o = 0; o < outputs.size(); o++) {
    sum += SimpleSumLoss(outputs[o]->data);
  }

  return sum;
}

void SimpleSumLossGradient(const std::vector<Conv::CombinedTensor*>& outputs) {
  for (unsigned int o = 0; o < outputs.size(); o++) {
    Conv::Tensor& tensor = outputs[o]->data;
    Conv::Tensor& delta_tensor = outputs[o]->delta;
    for (unsigned int e = 0; e < tensor.elements(); e++) {
      const Conv::datum element = tensor.data_ptr_const()[e];
      const Conv::datum gradient = element > 0.0 ? 1.0 : -1.0;
      delta_tensor.data_ptr()[e] = gradient;
    }
  }
}

namespace Conv {
  bool DoGradientTest(Conv::Layer* layer, Conv::Tensor& data, Conv::Tensor& delta, std::vector<Conv::CombinedTensor*>& outputs, Conv::datum epsilon) {
    layer->FeedForward();
    SimpleSumLossGradient(outputs);
    layer->BackPropagate();

    unsigned int elements = data.elements();
    unsigned int okay = 0;

    // Weight gradient test
    for (unsigned int w = 0; w < data.elements(); w++) {
      const Conv::datum weight = data.data_ptr_const()[w];
      const Conv::datum gradient = delta.data_ptr_const()[w];

      // Using central diff
      data.data_ptr()[w] = weight + epsilon;
      layer->FeedForward();
      const Conv::datum forward_loss = SimpleSumLoss(outputs);

      data.data_ptr()[w] = weight - epsilon;
      layer->FeedForward();
      const Conv::datum backward_loss = SimpleSumLoss(outputs);

      const Conv::datum fd_gradient = (forward_loss - backward_loss) / (2.0 * epsilon);
      data.data_ptr()[w] = weight;

      const Conv::datum ratio = fd_gradient / gradient;
      if(ratio > 1.2 || ratio < 0.8) {
        LOGDEBUG << "BP Grad : " << gradient;
        LOGDEBUG << "FD Grad : " << fd_gradient;
        LOGDEBUG << "Ratio   : " << ratio;
        LOGDEBUG << "Diff    : " << gradient - fd_gradient;
      } else {
        okay++;
      }
    }
    if(okay != elements) {
      double success_rate = (double)okay/(double)elements;
      if(success_rate > 0.85)
        return true;
      else {
        LOGERROR << okay << " of " << elements << " gradients okay - " << std::setprecision(3) << 100.0 * (double)okay/(double)elements << "%";
        return false;
      }
    } else {
      return true;
    }
  }
}

int main(int argc, char* argv[]) {
  if(argc > 1)
    Conv::System::Init(3);
  else
    Conv::System::Init();

  std::mt19937 seed_generator(93023);
  std::uniform_real_distribution<Conv::datum> dist(1.0, 2.0);

  Conv::NetStatus net_status;
  net_status.SetIsTesting(true);

  bool test_failed = false;

  Conv::CombinedTensor input_data(SAMPLES, WIDTH, HEIGHT, MAPS);

  std::vector<std::string> test_layers;

  // Inject random seeds
  for (std::pair<std::string, unsigned int>& layer_pair : test_layers_and_runs) {
    std::string& layer_descriptor = layer_pair.first;
    unsigned int runs = layer_pair.second;
    for(unsigned int i = 0; i < runs; i++) {
      std::string injected_descriptor = Conv::LayerFactory::InjectSeed(layer_descriptor, seed_generator());
      test_layers.push_back(injected_descriptor);
    }
  }

  for (std::string& layer_descriptor : test_layers) {
    bool data_sign = seed_generator() % 2 == 0;
    for(unsigned int e = 0; e < input_data.data.elements(); e++) {
      if(data_sign)
        input_data.data.data_ptr()[e] = dist(seed_generator);
      else
        input_data.data.data_ptr()[e] = -dist(seed_generator);
    }
    input_data.delta.Clear(0.0);

    LOGINFO << "Testing layer: " << layer_descriptor;
    Conv::Layer* layer = Conv::LayerFactory::ConstructLayer(layer_descriptor);
    if(layer == nullptr) {
      test_failed = true;
      LOGERROR << "        FAILED";
      continue;
    }

    LOGDEBUG << "    Description: " << layer->GetLayerDescription();

    std::vector<Conv::CombinedTensor*> outputs;
    bool createoutputs_success = layer->CreateOutputs({&input_data}, outputs);
    if(!createoutputs_success) {
      test_failed = true;
      LOGINFO << "    Creating outputs...";
      LOGERROR << "       FAILED";
      continue;
    }

    for(Conv::CombinedTensor* output : outputs) {
      LOGDEBUG << "        Output: " << output->data;
    }

    bool connect_success = layer->Connect({&input_data}, outputs, &net_status);
    if(!connect_success) {
      test_failed = true;
      LOGINFO << "    Connecting...";
      LOGERROR << "        FAILED";
      continue;
    }

    layer->OnLayerConnect({});

    for(Conv::CombinedTensor* weights : layer->parameters()) {
      bool gradient_success = Conv::DoGradientTest(layer, weights->data, weights->delta, outputs, epsilon);
      if(!gradient_success) {
        test_failed = true;
        LOGINFO << "    Gradient test (weights)...";
        LOGERROR << "        FAILED";
        continue;
      }
    }

    bool gradient_success = Conv::DoGradientTest(layer, input_data.data, input_data.delta, outputs, epsilon);
    if(!gradient_success) {
      test_failed = true;
      LOGINFO << "    Gradient test (inputs)...";
      LOGERROR << "        FAILED";
      continue;
    }

    delete layer;
    for(Conv::CombinedTensor* output : outputs)
      delete output;
  }

  LOGEND;
  return test_failed ? -1 : 0;
}<|endoftext|>


<commit_before><commit_msg>bustage fix - file moved<commit_after><|endoftext|>


<commit_before><commit_msg>修复Linux下的版本报错问题<commit_after><|endoftext|>


<commit_before>#include <osgTerrain/Layer>
#include <osgDB/ObjectWrapper>
#include <osgDB/InputStream>
#include <osgDB/OutputStream>

static bool checkLayers( const osgTerrain::CompositeLayer& layer )
{
    return layer.getNumLayers()>0;
}

static bool readLayers( osgDB::InputStream& is, osgTerrain::CompositeLayer& layer )
{
    unsigned int size = 0; is >> size >> osgDB::BEGIN_BRACKET;
    for ( unsigned int i=0; i<size; ++i )
    {
        osgTerrain::Layer* child = dynamic_cast<osgTerrain::Layer*>( is.readObject() );
        if ( child ) layer.addLayer( child );
    }
    is >> osgDB::END_BRACKET;
    return true;
}

static bool writeLayers( osgDB::OutputStream& os, const osgTerrain::CompositeLayer& layer )
{
    unsigned int size = layer.getNumLayers();
    os << size << osgDB::BEGIN_BRACKET << std::endl;
    for ( unsigned int i=0; i<size; ++i )
    {
        os << layer.getLayer(i);
    }
    os << osgDB::END_BRACKET << std::endl;
    return true;
}

REGISTER_OBJECT_WRAPPER( osgTerrain_CompositeLayer,
                         new osgTerrain::CompositeLayer,
                         osgTerrain::CompositeLayer,
                         "osg::Object osgTerrain::Layer osgTerrain::CompositeLayer" )
{
    ADD_USER_SERIALIZER( Layers );  // _layers
}
<commit_msg>Implement support for compound name only entries in CompositeLayer<commit_after>#include <osgTerrain/Layer>
#include <osgDB/ObjectWrapper>
#include <osgDB/InputStream>
#include <osgDB/OutputStream>

static bool checkLayers( const osgTerrain::CompositeLayer& layer )
{
    return layer.getNumLayers()>0;
}

static bool readLayers( osgDB::InputStream& is, osgTerrain::CompositeLayer& layer )
{
    unsigned int size = 0; is >> size >> osgDB::BEGIN_BRACKET;
    for ( unsigned int i=0; i<size; ++i )
    {
        std::string type;
        is >> type;
        if ( type=="Object" )
        {
            osgTerrain::Layer* child = dynamic_cast<osgTerrain::Layer*>( is.readObject() );
            if ( child ) layer.addLayer( child );
        }
        else if ( type=="File" )
        {
            std::string compoundname;
            is.readWrappedString( compoundname );
            layer.addLayer( compoundname );
        }
    }
    is >> osgDB::END_BRACKET;
    return true;
}

static bool writeLayers( osgDB::OutputStream& os, const osgTerrain::CompositeLayer& layer )
{
    unsigned int size = layer.getNumLayers();
    os << size << osgDB::BEGIN_BRACKET << std::endl;
    for ( unsigned int i=0; i<size; ++i )
    {
        const osgTerrain::Layer* child = layer.getLayer(i);
        std::string type = child ? std::string("Object") : std::string("File");
        os << type;
        if ( child )
        {
            os << child;
        }
        else
        {
            os.writeWrappedString( layer.getCompoundName(i) );
            os << std::endl;
        }
    }
    os << osgDB::END_BRACKET << std::endl;
    return true;
}

REGISTER_OBJECT_WRAPPER( osgTerrain_CompositeLayer,
                         new osgTerrain::CompositeLayer,
                         osgTerrain::CompositeLayer,
                         "osg::Object osgTerrain::Layer osgTerrain::CompositeLayer" )
{
    ADD_USER_SERIALIZER( Layers );  // _layers
}
<|endoftext|>


<commit_before>#include <string>
#include <stdio.h>
#include <tag.h>
#include <tstringlist.h>
#include <tbytevectorlist.h>
#include <tpropertymap.h>
#include <oggfile.h>
#include <vorbisfile.h>
#include <oggpageheader.h>
#include <cppunit/extensions/HelperMacros.h>
#include "utils.h"

using namespace std;
using namespace TagLib;

class TestOGG : public CppUnit::TestFixture
{
  CPPUNIT_TEST_SUITE(TestOGG);
  CPPUNIT_TEST(testSimple);
  CPPUNIT_TEST(testSplitPackets);
  CPPUNIT_TEST(testDictInterface1);
  CPPUNIT_TEST(testDictInterface2);
  CPPUNIT_TEST(testAudioProperties);
  CPPUNIT_TEST_SUITE_END();

public:

  void testSimple()
  {
    ScopedFileCopy copy("empty", ".ogg");
    string newname = copy.fileName();

    Vorbis::File *f = new Vorbis::File(newname.c_str());
    f->tag()->setArtist("The Artist");
    f->save();
    delete f;

    f = new Vorbis::File(newname.c_str());
    CPPUNIT_ASSERT_EQUAL(String("The Artist"), f->tag()->artist());
    delete f;
  }

  void testSplitPackets()
  {
    ScopedFileCopy copy("empty", ".ogg");
    string newname = copy.fileName();

    String longText(std::string(128 * 1024, ' ').c_str());
    for (size_t i = 0; i < longText.length(); ++i)
      longText[i] = static_cast<wchar>(L'A' + (i % 26));

    Vorbis::File *f = new Vorbis::File(newname.c_str());
    f->tag()->setTitle(longText);
    f->save();
    delete f;

    f = new Vorbis::File(newname.c_str());
    CPPUNIT_ASSERT(f->isValid());
    CPPUNIT_ASSERT_EQUAL(19, f->lastPageHeader()->pageSequenceNumber());
    CPPUNIT_ASSERT_EQUAL(longText, f->tag()->title());
    f->tag()->setTitle("ABCDE");
    f->save();
    delete f;

    f = new Vorbis::File(newname.c_str());
    CPPUNIT_ASSERT(f->isValid());
    CPPUNIT_ASSERT_EQUAL(3, f->lastPageHeader()->pageSequenceNumber());
    CPPUNIT_ASSERT_EQUAL(String("ABCDE"), f->tag()->title());
    delete f;
  }

  void testDictInterface1()
  {
    ScopedFileCopy copy("empty", ".ogg");
    string newname = copy.fileName();

    Vorbis::File *f = new Vorbis::File(newname.c_str());

    CPPUNIT_ASSERT_EQUAL(TagLib::uint(0), f->tag()->properties().size());

    PropertyMap newTags;
    StringList values("value 1");
    values.append("value 2");
    newTags["ARTIST"] = values;
    f->tag()->setProperties(newTags);

    PropertyMap map = f->tag()->properties();
    CPPUNIT_ASSERT_EQUAL(TagLib::uint(1), map.size());
    CPPUNIT_ASSERT_EQUAL(TagLib::uint(2), map["ARTIST"].size());
    CPPUNIT_ASSERT_EQUAL(String("value 1"), map["ARTIST"][0]);
    delete f;

  }

  void testDictInterface2()
  {
    ScopedFileCopy copy("test", ".ogg");
    string newname = copy.fileName();

    Vorbis::File *f = new Vorbis::File(newname.c_str());
    PropertyMap tags = f->tag()->properties();

    CPPUNIT_ASSERT_EQUAL(TagLib::uint(2), tags["UNUSUALTAG"].size());
    CPPUNIT_ASSERT_EQUAL(String("usual value"), tags["UNUSUALTAG"][0]);
    CPPUNIT_ASSERT_EQUAL(String("another value"), tags["UNUSUALTAG"][1]);
    CPPUNIT_ASSERT_EQUAL(
      String("\xC3\xB6\xC3\xA4\xC3\xBC\x6F\xCE\xA3\xC3\xB8", String::UTF8),
      tags["UNICODETAG"][0]);

    tags["UNICODETAG"][0] = String(
      "\xCE\xBD\xCE\xB5\xCF\x89\x20\xCE\xBD\xCE\xB1\xCE\xBB\xCF\x85\xCE\xB5", String::UTF8);
    tags.erase("UNUSUALTAG");
    f->tag()->setProperties(tags);
    CPPUNIT_ASSERT_EQUAL(
      String("\xCE\xBD\xCE\xB5\xCF\x89\x20\xCE\xBD\xCE\xB1\xCE\xBB\xCF\x85\xCE\xB5", String::UTF8),
      f->tag()->properties()["UNICODETAG"][0]);
    CPPUNIT_ASSERT_EQUAL(false, f->tag()->properties().contains("UNUSUALTAG"));

    delete f;
  }

  void testAudioProperties()
  {
    Ogg::Vorbis::File f(TEST_FILE_PATH_C("empty.ogg"));
    CPPUNIT_ASSERT(f.audioProperties());
    CPPUNIT_ASSERT_EQUAL(3, f.audioProperties()->length());
    CPPUNIT_ASSERT_EQUAL(3, f.audioProperties()->lengthInSeconds());
    CPPUNIT_ASSERT_EQUAL(3685, f.audioProperties()->lengthInMilliseconds());
    CPPUNIT_ASSERT_EQUAL(9, f.audioProperties()->bitrate());
    CPPUNIT_ASSERT_EQUAL(2, f.audioProperties()->channels());
    CPPUNIT_ASSERT_EQUAL(44100, f.audioProperties()->sampleRate());
    CPPUNIT_ASSERT_EQUAL(0, f.audioProperties()->vorbisVersion());
    CPPUNIT_ASSERT_EQUAL(0, f.audioProperties()->bitrateMaximum());
    CPPUNIT_ASSERT_EQUAL(112000, f.audioProperties()->bitrateNominal());
    CPPUNIT_ASSERT_EQUAL(0, f.audioProperties()->bitrateMinimum());
  }
};

CPPUNIT_TEST_SUITE_REGISTRATION(TestOGG);
<commit_msg>Add a test for the CRC checksum of Ogg pages.<commit_after>#include <string>
#include <stdio.h>
#include <tag.h>
#include <tstringlist.h>
#include <tbytevectorlist.h>
#include <tpropertymap.h>
#include <oggfile.h>
#include <vorbisfile.h>
#include <oggpageheader.h>
#include <cppunit/extensions/HelperMacros.h>
#include "utils.h"

using namespace std;
using namespace TagLib;

class TestOGG : public CppUnit::TestFixture
{
  CPPUNIT_TEST_SUITE(TestOGG);
  CPPUNIT_TEST(testSimple);
  CPPUNIT_TEST(testSplitPackets);
  CPPUNIT_TEST(testDictInterface1);
  CPPUNIT_TEST(testDictInterface2);
  CPPUNIT_TEST(testAudioProperties);
  CPPUNIT_TEST(testPageChecksum);
  CPPUNIT_TEST_SUITE_END();

public:

  void testSimple()
  {
    ScopedFileCopy copy("empty", ".ogg");
    string newname = copy.fileName();

    Vorbis::File *f = new Vorbis::File(newname.c_str());
    f->tag()->setArtist("The Artist");
    f->save();
    delete f;

    f = new Vorbis::File(newname.c_str());
    CPPUNIT_ASSERT_EQUAL(String("The Artist"), f->tag()->artist());
    delete f;
  }

  void testSplitPackets()
  {
    ScopedFileCopy copy("empty", ".ogg");
    string newname = copy.fileName();

    String longText(std::string(128 * 1024, ' ').c_str());
    for (size_t i = 0; i < longText.length(); ++i)
      longText[i] = static_cast<wchar>(L'A' + (i % 26));

    Vorbis::File *f = new Vorbis::File(newname.c_str());
    f->tag()->setTitle(longText);
    f->save();
    delete f;

    f = new Vorbis::File(newname.c_str());
    CPPUNIT_ASSERT(f->isValid());
    CPPUNIT_ASSERT_EQUAL(19, f->lastPageHeader()->pageSequenceNumber());
    CPPUNIT_ASSERT_EQUAL(longText, f->tag()->title());
    f->tag()->setTitle("ABCDE");
    f->save();
    delete f;

    f = new Vorbis::File(newname.c_str());
    CPPUNIT_ASSERT(f->isValid());
    CPPUNIT_ASSERT_EQUAL(3, f->lastPageHeader()->pageSequenceNumber());
    CPPUNIT_ASSERT_EQUAL(String("ABCDE"), f->tag()->title());
    delete f;
  }

  void testDictInterface1()
  {
    ScopedFileCopy copy("empty", ".ogg");
    string newname = copy.fileName();

    Vorbis::File *f = new Vorbis::File(newname.c_str());

    CPPUNIT_ASSERT_EQUAL(TagLib::uint(0), f->tag()->properties().size());

    PropertyMap newTags;
    StringList values("value 1");
    values.append("value 2");
    newTags["ARTIST"] = values;
    f->tag()->setProperties(newTags);

    PropertyMap map = f->tag()->properties();
    CPPUNIT_ASSERT_EQUAL(TagLib::uint(1), map.size());
    CPPUNIT_ASSERT_EQUAL(TagLib::uint(2), map["ARTIST"].size());
    CPPUNIT_ASSERT_EQUAL(String("value 1"), map["ARTIST"][0]);
    delete f;

  }

  void testDictInterface2()
  {
    ScopedFileCopy copy("test", ".ogg");
    string newname = copy.fileName();

    Vorbis::File *f = new Vorbis::File(newname.c_str());
    PropertyMap tags = f->tag()->properties();

    CPPUNIT_ASSERT_EQUAL(TagLib::uint(2), tags["UNUSUALTAG"].size());
    CPPUNIT_ASSERT_EQUAL(String("usual value"), tags["UNUSUALTAG"][0]);
    CPPUNIT_ASSERT_EQUAL(String("another value"), tags["UNUSUALTAG"][1]);
    CPPUNIT_ASSERT_EQUAL(
      String("\xC3\xB6\xC3\xA4\xC3\xBC\x6F\xCE\xA3\xC3\xB8", String::UTF8),
      tags["UNICODETAG"][0]);

    tags["UNICODETAG"][0] = String(
      "\xCE\xBD\xCE\xB5\xCF\x89\x20\xCE\xBD\xCE\xB1\xCE\xBB\xCF\x85\xCE\xB5", String::UTF8);
    tags.erase("UNUSUALTAG");
    f->tag()->setProperties(tags);
    CPPUNIT_ASSERT_EQUAL(
      String("\xCE\xBD\xCE\xB5\xCF\x89\x20\xCE\xBD\xCE\xB1\xCE\xBB\xCF\x85\xCE\xB5", String::UTF8),
      f->tag()->properties()["UNICODETAG"][0]);
    CPPUNIT_ASSERT_EQUAL(false, f->tag()->properties().contains("UNUSUALTAG"));

    delete f;
  }

  void testAudioProperties()
  {
    Ogg::Vorbis::File f(TEST_FILE_PATH_C("empty.ogg"));
    CPPUNIT_ASSERT(f.audioProperties());
    CPPUNIT_ASSERT_EQUAL(3, f.audioProperties()->length());
    CPPUNIT_ASSERT_EQUAL(3, f.audioProperties()->lengthInSeconds());
    CPPUNIT_ASSERT_EQUAL(3685, f.audioProperties()->lengthInMilliseconds());
    CPPUNIT_ASSERT_EQUAL(9, f.audioProperties()->bitrate());
    CPPUNIT_ASSERT_EQUAL(2, f.audioProperties()->channels());
    CPPUNIT_ASSERT_EQUAL(44100, f.audioProperties()->sampleRate());
    CPPUNIT_ASSERT_EQUAL(0, f.audioProperties()->vorbisVersion());
    CPPUNIT_ASSERT_EQUAL(0, f.audioProperties()->bitrateMaximum());
    CPPUNIT_ASSERT_EQUAL(112000, f.audioProperties()->bitrateNominal());
    CPPUNIT_ASSERT_EQUAL(0, f.audioProperties()->bitrateMinimum());
  }

  void testPageChecksum()
  {
    ScopedFileCopy copy("empty", ".ogg");

    {
      Vorbis::File f(copy.fileName().c_str());
      f.tag()->setArtist("The Artist");
      f.save();

      f.seek(0x50);
      CPPUNIT_ASSERT_EQUAL((TagLib::uint)0x3d3bd92d, f.readBlock(4).toUInt(0, true));
    }
    {
      Vorbis::File f(copy.fileName().c_str());
      f.tag()->setArtist("The Artist 2");
      f.save();

      f.seek(0x50);
      CPPUNIT_ASSERT_EQUAL((TagLib::uint)0xd985291c, f.readBlock(4).toUInt(0, true));
    }

  }

};

CPPUNIT_TEST_SUITE_REGISTRATION(TestOGG);
<|endoftext|>