<commit_before>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/register.h"
#include "kernel/sigtools.h"
#include "kernel/log.h"
#include "libs/subcircuit/subcircuit.h"
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>

namespace
{
	struct bit_ref_t {
		std::string cell, port;
		int bit;
	};

	bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, RTLIL::Design *sel = NULL)
	{
		SigMap sigmap(mod);
		std::map<RTLIL::SigChunk, bit_ref_t> sig_bit_ref;

		if (sel && !sel->selected(mod)) {
			log("  Skipping module %s as it is not selected.\n", mod->name.c_str());
			return false;
		}

		if (mod->memories.size() > 0 || mod->processes.size() > 0) {
			log("  Skipping module %s as it contains unprocessed memories or processes.\n", mod->name.c_str());
			return false;
		}

		// create graph nodes from cells
		for (auto &cell_it : mod->cells)
		{
			RTLIL::Cell *cell = cell_it.second;
			if (sel && !sel->selected(mod, cell))
				continue;

			std::string type = cell->type;
			if (sel == NULL && type.substr(0, 2) == "\\$")
				type = type.substr(1);
			graph.createNode(cell->name, type, (void*)cell);

			for (auto &conn : cell->connections)
			{
				RTLIL::SigSpec conn_sig = conn.second;
				sigmap.apply(conn_sig);
				conn_sig.expand();

				graph.createPort(cell->name, conn.first, conn.second.width);
				for (size_t i = 0; i < conn_sig.chunks.size(); i++)
				{
					auto &chunk = conn_sig.chunks[i];
					assert(chunk.width == 1);

					if (chunk.wire == NULL) {
						graph.createConstant(cell->name, conn.first, i, int(chunk.data.bits[0]));
						continue;
					}

					if (sig_bit_ref.count(chunk) == 0) {
						bit_ref_t &bit_ref = sig_bit_ref[chunk];
						bit_ref.cell = cell->name;
						bit_ref.port = conn.first;
						bit_ref.bit = i;
					}

					bit_ref_t &bit_ref = sig_bit_ref[chunk];
					graph.createConnection(bit_ref.cell, bit_ref.port, bit_ref.bit, cell->name, conn.first, i);
				}
			}
		}

		// mark external signals (used in non-selected cells)
		for (auto &cell_it : mod->cells)
		{
			RTLIL::Cell *cell = cell_it.second;
			if (sel && !sel->selected(mod, cell))
				for (auto &conn : cell->connections)
				{
					RTLIL::SigSpec conn_sig = conn.second;
					sigmap.apply(conn_sig);
					conn_sig.expand();

					for (auto &chunk : conn_sig.chunks)
						if (sig_bit_ref.count(chunk) != 0) {
							bit_ref_t &bit_ref = sig_bit_ref[chunk];
							graph.markExtern(bit_ref.cell, bit_ref.port, bit_ref.bit);
						}
				}
		}

		// mark external signals (used in module ports)
		for (auto &wire_it : mod->wires)
		{
			RTLIL::Wire *wire = wire_it.second;
			if (wire->port_id > 0)
			{
				RTLIL::SigSpec conn_sig(wire);
				sigmap.apply(conn_sig);
				conn_sig.expand();

				for (auto &chunk : conn_sig.chunks)
					if (sig_bit_ref.count(chunk) != 0) {
						bit_ref_t &bit_ref = sig_bit_ref[chunk];
						graph.markExtern(bit_ref.cell, bit_ref.port, bit_ref.bit);
					}
			}
		}

		return true;
	}

	void replace(RTLIL::Module *needle, RTLIL::Module *haystack, SubCircuit::Solver::Result &match)
	{
		SigMap sigmap(needle);
		SigSet<std::pair<std::string, int>> sig2port;

		// create new cell
		RTLIL::Cell *cell = new RTLIL::Cell;
		cell->name = stringf("$extract$%s$%d", needle->name.c_str(), RTLIL::autoidx++);
		cell->type = needle->name;
		haystack->add(cell);

		// create cell ports
		for (auto &it : needle->wires) {
			RTLIL::Wire *wire = it.second;
			if (wire->port_id > 0) {
				for (int i = 0; i < wire->width; i++)
					sig2port.insert(sigmap(RTLIL::SigSpec(wire, 1, i)), std::pair<std::string, int>(wire->name, i));
				cell->connections[wire->name] = RTLIL::SigSpec(RTLIL::State::Sz, wire->width);
			}
		}

		// delete replaced cells and connect new ports
		for (auto &it : match.mappings)
		{
			auto &mapping = it.second;
			RTLIL::Cell *needle_cell = (RTLIL::Cell*)mapping.needleUserData;
			RTLIL::Cell *haystack_cell = (RTLIL::Cell*)mapping.haystackUserData;

			for (auto &conn : needle_cell->connections)
				if (mapping.portMapping.count(conn.first) > 0 && sig2port.has(conn.second))
				{
					RTLIL::SigSpec sig = sigmap(conn.second);
					sig.expand();

					for (int i = 0; i < sig.width; i++)
					for (auto &port : sig2port.find(sig.chunks[i])) {
						RTLIL::SigSpec bitsig = haystack_cell->connections.at(mapping.portMapping[conn.first]).extract(i, 1);
						cell->connections.at(port.first).replace(port.second, bitsig);
					}
				}

			haystack->cells.erase(haystack_cell->name);
			delete haystack_cell;
		}
	}
}

struct ExtractPass : public Pass {
	ExtractPass() : Pass("extract") { }
	virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
	{
		log_header("Executing EXTRACT pass (map subcircuits to cells).\n");
		log_push();

		std::string filename;
		bool verbose;

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++) {
			if (args[argidx] == "-map" && argidx+1 < args.size()) {
				filename = args[++argidx];
				continue;
			}
			if (args[argidx] == "-verbose") {
				verbose = true;
				continue;
			}
			break;
		}
		extra_args(args, argidx, design);

		if (filename.empty())
			log_cmd_error("Missing option -map <verilog_or_ilang_file>.\n");

		RTLIL::Design *map = new RTLIL::Design;
		FILE *f = fopen(filename.c_str(), "rt");
		if (f == NULL)
			log_error("Can't open map file `%s'\n", filename.c_str());
		if (filename.size() > 3 && filename.substr(filename.size()-3) == ".il")
			Frontend::frontend_call(map, f, filename, "ilang");
		else
			Frontend::frontend_call(map, f, filename, "verilog");
		fclose(f);

		SubCircuit::Solver solver;
		std::vector<SubCircuit::Solver::Result> results;

		if (verbose)
			solver.setVerbose();

		std::map<std::string, RTLIL::Module*> needle_map, haystack_map;

		log_header("Creating graphs for SubCircuit library.\n");

		for (auto &mod_it : map->modules) {
			SubCircuit::Graph mod_graph;
			std::string graph_name = "needle_" + mod_it.first.substr(mod_it.first[0] == '\\' ? 1 : 0);
			log("Creating needle graph %s.\n", graph_name.c_str());
			if (module2graph(mod_graph, mod_it.second)) {
				solver.addGraph(graph_name, mod_graph);
				needle_map[graph_name] = mod_it.second;
			}
		}

		for (auto &mod_it : design->modules) {
			SubCircuit::Graph mod_graph;
			std::string graph_name = "haystack_" + mod_it.first.substr(mod_it.first[0] == '\\' ? 1 : 0);
			log("Creating haystack graph %s.\n", graph_name.c_str());
			if (module2graph(mod_graph, mod_it.second, design)) {
				solver.addGraph(graph_name, mod_graph);
				haystack_map[graph_name] = mod_it.second;
			}
		}

		log_header("Running solver from SubCircuit library.\n");

		for (auto &needle_it : needle_map)
		for (auto &haystack_it : haystack_map) {
			log("Solving for %s in %s.\n", needle_it.first.c_str(), haystack_it.first.c_str());
			solver.solve(results, needle_it.first, haystack_it.first, false);
		}
		log("Found %zd matches.\n", results.size());

		if (results.size() > 0)
		{
			log_header("Substitute SubCircuits with cells.\n");

			for (int i = 0; i < int(results.size()); i++) {
				auto &result = results[i];
				log("\nMatch #%d: (%s in %s)\n", i, result.needleGraphId.c_str(), result.haystackGraphId.c_str());
				for (const auto &it : result.mappings) {
					log("  %s -> %s", it.first.c_str(), it.second.haystackNodeId.c_str());
					for (const auto & it2 : it.second.portMapping)
						log(" %s:%s", it2.first.c_str(), it2.second.c_str());
					log("\n");
				}
				replace(needle_map.at(result.needleGraphId), haystack_map.at(result.haystackGraphId), result);
			}
		}

		delete map;
		log_pop();
	}
} ExtractPass;

<commit_msg>Fixed "extract" pass for non-optimized needles<commit_after>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/register.h"
#include "kernel/sigtools.h"
#include "kernel/log.h"
#include "libs/subcircuit/subcircuit.h"
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>

namespace
{
	struct bit_ref_t {
		std::string cell, port;
		int bit;
	};

	bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, RTLIL::Design *sel = NULL)
	{
		SigMap sigmap(mod);
		std::map<RTLIL::SigChunk, bit_ref_t> sig_bit_ref;

		if (sel && !sel->selected(mod)) {
			log("  Skipping module %s as it is not selected.\n", mod->name.c_str());
			return false;
		}

		if (mod->memories.size() > 0 || mod->processes.size() > 0) {
			log("  Skipping module %s as it contains unprocessed memories or processes.\n", mod->name.c_str());
			return false;
		}

		// create graph nodes from cells
		for (auto &cell_it : mod->cells)
		{
			RTLIL::Cell *cell = cell_it.second;
			if (sel && !sel->selected(mod, cell))
				continue;

			std::string type = cell->type;
			if (sel == NULL && type.substr(0, 2) == "\\$")
				type = type.substr(1);
			graph.createNode(cell->name, type, (void*)cell);

			for (auto &conn : cell->connections)
			{
				RTLIL::SigSpec conn_sig = conn.second;
				sigmap.apply(conn_sig);
				conn_sig.expand();

				graph.createPort(cell->name, conn.first, conn.second.width);
				for (size_t i = 0; i < conn_sig.chunks.size(); i++)
				{
					auto &chunk = conn_sig.chunks[i];
					assert(chunk.width == 1);

					if (chunk.wire == NULL) {
						graph.createConstant(cell->name, conn.first, i, int(chunk.data.bits[0]));
						continue;
					}

					if (sig_bit_ref.count(chunk) == 0) {
						bit_ref_t &bit_ref = sig_bit_ref[chunk];
						bit_ref.cell = cell->name;
						bit_ref.port = conn.first;
						bit_ref.bit = i;
					}

					bit_ref_t &bit_ref = sig_bit_ref[chunk];
					graph.createConnection(bit_ref.cell, bit_ref.port, bit_ref.bit, cell->name, conn.first, i);
				}
			}
		}

		// mark external signals (used in non-selected cells)
		for (auto &cell_it : mod->cells)
		{
			RTLIL::Cell *cell = cell_it.second;
			if (sel && !sel->selected(mod, cell))
				for (auto &conn : cell->connections)
				{
					RTLIL::SigSpec conn_sig = conn.second;
					sigmap.apply(conn_sig);
					conn_sig.expand();

					for (auto &chunk : conn_sig.chunks)
						if (sig_bit_ref.count(chunk) != 0) {
							bit_ref_t &bit_ref = sig_bit_ref[chunk];
							graph.markExtern(bit_ref.cell, bit_ref.port, bit_ref.bit);
						}
				}
		}

		// mark external signals (used in module ports)
		for (auto &wire_it : mod->wires)
		{
			RTLIL::Wire *wire = wire_it.second;
			if (wire->port_id > 0)
			{
				RTLIL::SigSpec conn_sig(wire);
				sigmap.apply(conn_sig);
				conn_sig.expand();

				for (auto &chunk : conn_sig.chunks)
					if (sig_bit_ref.count(chunk) != 0) {
						bit_ref_t &bit_ref = sig_bit_ref[chunk];
						graph.markExtern(bit_ref.cell, bit_ref.port, bit_ref.bit);
					}
			}
		}

		return true;
	}

	void replace(RTLIL::Module *needle, RTLIL::Module *haystack, SubCircuit::Solver::Result &match)
	{
		SigMap sigmap(needle);
		SigSet<std::pair<std::string, int>> sig2port;

		// create new cell
		RTLIL::Cell *cell = new RTLIL::Cell;
		cell->name = stringf("$extract$%s$%d", needle->name.c_str(), RTLIL::autoidx++);
		cell->type = needle->name;
		haystack->add(cell);

		// create cell ports
		for (auto &it : needle->wires) {
			RTLIL::Wire *wire = it.second;
			if (wire->port_id > 0) {
				for (int i = 0; i < wire->width; i++)
					sig2port.insert(sigmap(RTLIL::SigSpec(wire, 1, i)), std::pair<std::string, int>(wire->name, i));
				cell->connections[wire->name] = RTLIL::SigSpec(RTLIL::State::Sz, wire->width);
			}
		}

		// delete replaced cells and connect new ports
		for (auto &it : match.mappings)
		{
			auto &mapping = it.second;
			RTLIL::Cell *needle_cell = (RTLIL::Cell*)mapping.needleUserData;
			RTLIL::Cell *haystack_cell = (RTLIL::Cell*)mapping.haystackUserData;

			for (auto &conn : needle_cell->connections) {
				RTLIL::SigSpec sig = sigmap(conn.second);
				if (mapping.portMapping.count(conn.first) > 0 && sig2port.has(sigmap(sig))) {
					sig.expand();
					for (int i = 0; i < sig.width; i++)
					for (auto &port : sig2port.find(sig.chunks[i])) {
						RTLIL::SigSpec bitsig = haystack_cell->connections.at(mapping.portMapping[conn.first]).extract(i, 1);
						cell->connections.at(port.first).replace(port.second, bitsig);
					}
				}
			}

			haystack->cells.erase(haystack_cell->name);
			delete haystack_cell;
		}
	}
}

struct ExtractPass : public Pass {
	ExtractPass() : Pass("extract") { }
	virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
	{
		log_header("Executing EXTRACT pass (map subcircuits to cells).\n");
		log_push();

		std::string filename;
		bool verbose;

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++) {
			if (args[argidx] == "-map" && argidx+1 < args.size()) {
				filename = args[++argidx];
				continue;
			}
			if (args[argidx] == "-verbose") {
				verbose = true;
				continue;
			}
			break;
		}
		extra_args(args, argidx, design);

		if (filename.empty())
			log_cmd_error("Missing option -map <verilog_or_ilang_file>.\n");

		RTLIL::Design *map = new RTLIL::Design;
		FILE *f = fopen(filename.c_str(), "rt");
		if (f == NULL)
			log_error("Can't open map file `%s'\n", filename.c_str());
		if (filename.size() > 3 && filename.substr(filename.size()-3) == ".il")
			Frontend::frontend_call(map, f, filename, "ilang");
		else
			Frontend::frontend_call(map, f, filename, "verilog");
		fclose(f);

		SubCircuit::Solver solver;
		std::vector<SubCircuit::Solver::Result> results;

		if (verbose)
			solver.setVerbose();

		std::map<std::string, RTLIL::Module*> needle_map, haystack_map;

		log_header("Creating graphs for SubCircuit library.\n");

		for (auto &mod_it : map->modules) {
			SubCircuit::Graph mod_graph;
			std::string graph_name = "needle_" + mod_it.first.substr(mod_it.first[0] == '\\' ? 1 : 0);
			log("Creating needle graph %s.\n", graph_name.c_str());
			if (module2graph(mod_graph, mod_it.second)) {
				solver.addGraph(graph_name, mod_graph);
				needle_map[graph_name] = mod_it.second;
			}
		}

		for (auto &mod_it : design->modules) {
			SubCircuit::Graph mod_graph;
			std::string graph_name = "haystack_" + mod_it.first.substr(mod_it.first[0] == '\\' ? 1 : 0);
			log("Creating haystack graph %s.\n", graph_name.c_str());
			if (module2graph(mod_graph, mod_it.second, design)) {
				solver.addGraph(graph_name, mod_graph);
				haystack_map[graph_name] = mod_it.second;
			}
		}

		log_header("Running solver from SubCircuit library.\n");

		for (auto &needle_it : needle_map)
		for (auto &haystack_it : haystack_map) {
			log("Solving for %s in %s.\n", needle_it.first.c_str(), haystack_it.first.c_str());
			solver.solve(results, needle_it.first, haystack_it.first, false);
		}
		log("Found %zd matches.\n", results.size());

		if (results.size() > 0)
		{
			log_header("Substitute SubCircuits with cells.\n");

			for (int i = 0; i < int(results.size()); i++) {
				auto &result = results[i];
				log("\nMatch #%d: (%s in %s)\n", i, result.needleGraphId.c_str(), result.haystackGraphId.c_str());
				for (const auto &it : result.mappings) {
					log("  %s -> %s", it.first.c_str(), it.second.haystackNodeId.c_str());
					for (const auto & it2 : it.second.portMapping)
						log(" %s:%s", it2.first.c_str(), it2.second.c_str());
					log("\n");
				}
				replace(needle_map.at(result.needleGraphId), haystack_map.at(result.haystackGraphId), result);
			}
		}

		delete map;
		log_pop();
	}
} ExtractPass;

<|endoftext|>


<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/test/test_timeouts.h"

#include "base/command_line.h"
#include "base/logging.h"
#include "base/string_number_conversions.h"
#include "base/test/test_switches.h"

namespace {

// Sets value to the greatest of:
// 1) value's current value.
// 2) min_value.
// 3) the numerical value given by switch_name on the command line.
void InitializeTimeout(const char* switch_name, int min_value, int* value) {
  DCHECK(value);
  if (CommandLine::ForCurrentProcess()->HasSwitch(switch_name)) {
    std::string string_value(
        CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switch_name));
    int timeout;
    base::StringToInt(string_value, &timeout);
    *value = std::max(*value, timeout);
  }
  *value = std::max(*value, min_value);
}

// Sets value to the greatest of:
// 1) value's current value.
// 2) 0
// 3) the numerical value given by switch_name on the command line.
void InitializeTimeout(const char* switch_name, int* value) {
  InitializeTimeout(switch_name, 0, value);
}

}  // namespace

// static
bool TestTimeouts::initialized_ = false;

// The timeout values should increase in the order they appear in this block.
// static
int TestTimeouts::tiny_timeout_ms_ = 100;
int TestTimeouts::action_timeout_ms_ = 2000;
int TestTimeouts::action_max_timeout_ms_ = 31000;
int TestTimeouts::large_test_timeout_ms_ = 3 * 60 * 1000;
int TestTimeouts::huge_test_timeout_ms_ = 10 * 60 * 1000;

// static
int TestTimeouts::live_operation_timeout_ms_ = 45000;

// static
void TestTimeouts::Initialize() {
  if (initialized_) {
    NOTREACHED();
    return;
  }
  initialized_ = true;

  // Note that these timeouts MUST be initialized in the correct order as
  // per the CHECKS below.
  InitializeTimeout(switches::kTestTinyTimeout, &tiny_timeout_ms_);
  InitializeTimeout(switches::kUiTestActionTimeout, tiny_timeout_ms_,
                    &action_timeout_ms_);
  InitializeTimeout(switches::kUiTestActionMaxTimeout, action_timeout_ms_,
                    &action_max_timeout_ms_);
  // TODO(phajdan.jr): Fix callers and remove kTestTerminateTimeout.
  InitializeTimeout(switches::kTestTerminateTimeout, &action_max_timeout_ms_);
  InitializeTimeout(switches::kTestLargeTimeout, action_max_timeout_ms_,
                    &large_test_timeout_ms_);
  InitializeTimeout(switches::kUiTestTimeout, large_test_timeout_ms_,
                    &huge_test_timeout_ms_);

  // The timeout values should be increasing in the right order.
  CHECK(tiny_timeout_ms_ <= action_timeout_ms_);
  CHECK(action_timeout_ms_ <= action_max_timeout_ms_);
  CHECK(action_max_timeout_ms_ <= large_test_timeout_ms_);
  CHECK(large_test_timeout_ms_ <= huge_test_timeout_ms_);

  InitializeTimeout(switches::kLiveOperationTimeout,
                    &live_operation_timeout_ms_);
}
<commit_msg>Increase test timeout to 45s.<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/test/test_timeouts.h"

#include "base/command_line.h"
#include "base/logging.h"
#include "base/string_number_conversions.h"
#include "base/test/test_switches.h"

namespace {

// Sets value to the greatest of:
// 1) value's current value.
// 2) min_value.
// 3) the numerical value given by switch_name on the command line.
void InitializeTimeout(const char* switch_name, int min_value, int* value) {
  DCHECK(value);
  if (CommandLine::ForCurrentProcess()->HasSwitch(switch_name)) {
    std::string string_value(
        CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switch_name));
    int timeout;
    base::StringToInt(string_value, &timeout);
    *value = std::max(*value, timeout);
  }
  *value = std::max(*value, min_value);
}

// Sets value to the greatest of:
// 1) value's current value.
// 2) 0
// 3) the numerical value given by switch_name on the command line.
void InitializeTimeout(const char* switch_name, int* value) {
  InitializeTimeout(switch_name, 0, value);
}

}  // namespace

// static
bool TestTimeouts::initialized_ = false;

// The timeout values should increase in the order they appear in this block.
// static
int TestTimeouts::tiny_timeout_ms_ = 100;
int TestTimeouts::action_timeout_ms_ = 2000;
int TestTimeouts::action_max_timeout_ms_ = 45000;
int TestTimeouts::large_test_timeout_ms_ = 3 * 60 * 1000;
int TestTimeouts::huge_test_timeout_ms_ = 10 * 60 * 1000;

// static
int TestTimeouts::live_operation_timeout_ms_ = 45000;

// static
void TestTimeouts::Initialize() {
  if (initialized_) {
    NOTREACHED();
    return;
  }
  initialized_ = true;

  // Note that these timeouts MUST be initialized in the correct order as
  // per the CHECKS below.
  InitializeTimeout(switches::kTestTinyTimeout, &tiny_timeout_ms_);
  InitializeTimeout(switches::kUiTestActionTimeout, tiny_timeout_ms_,
                    &action_timeout_ms_);
  InitializeTimeout(switches::kUiTestActionMaxTimeout, action_timeout_ms_,
                    &action_max_timeout_ms_);
  // TODO(phajdan.jr): Fix callers and remove kTestTerminateTimeout.
  InitializeTimeout(switches::kTestTerminateTimeout, &action_max_timeout_ms_);
  InitializeTimeout(switches::kTestLargeTimeout, action_max_timeout_ms_,
                    &large_test_timeout_ms_);
  InitializeTimeout(switches::kUiTestTimeout, large_test_timeout_ms_,
                    &huge_test_timeout_ms_);

  // The timeout values should be increasing in the right order.
  CHECK(tiny_timeout_ms_ <= action_timeout_ms_);
  CHECK(action_timeout_ms_ <= action_max_timeout_ms_);
  CHECK(action_max_timeout_ms_ <= large_test_timeout_ms_);
  CHECK(large_test_timeout_ms_ <= huge_test_timeout_ms_);

  InitializeTimeout(switches::kLiveOperationTimeout,
                    &live_operation_timeout_ms_);
}
<|endoftext|>


<commit_before>#include "model.h"
#include "recognition.h"
#include <memory>
#include <algorithm>
#include <vector>

using std::min;
using std::max;
using std::make_shared;
using std::dynamic_pointer_cast;

int FIGURE_SELECT_GAP = -1;
int CLOSED_FIGURE_GAP = -1;
const int TRACK_FIT_GAP = 10;
const int DELETION_MOVE_MINIMAL_LENGTH = 5;
const int DELETION_MOVE_MAX_ANGLE = 30;
const int DELETION_MOVE_MIN_COUNT = 3;
const double SQUARING_MIN_RATIO = 0.8;
const double MIN_FIT_POINTS_AMOUNT = 0.75;

void setRecognitionPreset(RecognitionPreset preset) {
    switch (preset) {
    case RecognitionPreset::Mouse:
        FIGURE_SELECT_GAP = 10;
        CLOSED_FIGURE_GAP = 10;
        break;
    case RecognitionPreset::Touch:
        FIGURE_SELECT_GAP = 30;
        CLOSED_FIGURE_GAP = 50;
        break;
    };
}

BoundingBox getBoundingBox(const Track &track) {
    BoundingBox res;
    res.leftUp = res.rightDown = track[0];
    for (Point p : track.points) {
        res.leftUp.x = min(res.leftUp.x, p.x);
        res.leftUp.y = min(res.leftUp.y, p.y);
        res.rightDown.x = max(res.rightDown.x, p.x);
        res.rightDown.y = max(res.rightDown.y, p.y);
    }
    return res;
}

double getCircumference(const Track &track) {
    double res = 0;
    for (size_t i = 0; i + 1 < track.size(); i++) {
        res += (track[i + 1] - track[i]).length();
    }
    return res;
}
double getClosedCircumference(const Track &track) {
    double res = getCircumference(track);
    res += (track[0] - track[track.size() - 1]).length();
    return res;
}

bool cutToClosed(Track &track) {
    auto &points = track.points;
    auto it = points.begin();
    while (it != points.end() && (points[0] - *it).length() <= CLOSED_FIGURE_GAP) {
        it++;
    }
    while (it != points.end() && (points[0] - *it).length() > CLOSED_FIGURE_GAP) {
        it++;
    }
    if (it == points.end()) {
        return false;
    }
    while (it != points.end() && (points[0] - *it).length() <= CLOSED_FIGURE_GAP) {
        it++;
    }
    points.erase(it, points.end());
    return true;
}

double fitsToTrack(const Track &track, const PFigure &figure) {
    BoundingBox box = getBoundingBox(track);
    double maxDistance = TRACK_FIT_GAP;
    maxDistance = std::min(maxDistance, std::min(box.width(), box.height()) * 0.2);

    int goodCount = 0;
    for (Point p : track.points) {
        goodCount += figure->getApproximateDistanceToBorder(p) <= maxDistance;
    }

    return goodCount * 1.0 / track.size();
}

using namespace figures;

bool isDeletionTrack(const Track &track) {
    int cnt = 0;
    std::cout << "new\n";
    for (int i = 0; i < (int)track.size(); i++) {
        int prevPoint = i - 1;
        while (prevPoint >= 0 && (track[i] - track[prevPoint]).length() < DELETION_MOVE_MINIMAL_LENGTH) {
            prevPoint--;
        }
        int nextPoint = i + 1;
        while (nextPoint < (int)track.size() && (track[i] - track[nextPoint]).length() < DELETION_MOVE_MINIMAL_LENGTH) {
            nextPoint++;
        }
        if (prevPoint >= 0 && nextPoint < (int)track.size()) {
            Point vec1 = track[nextPoint] - track[i];
            Point vec2 = track[prevPoint] - track[i];
            double ang = acos(Point::dotProduct(vec1, vec2) / (vec1.length() * vec2.length()));
            if (ang <= PI * DELETION_MOVE_MAX_ANGLE / 180) {
                cnt++;
                i = nextPoint;
            }
        }
    }
    std::cout << "deletion cnt = " << cnt << "\n";
    return cnt >= DELETION_MOVE_MIN_COUNT;
}

PFigure recognizeConnections(const Track &track, Model &model) {
    Point start = track[0];
    Point end = track[track.size() - 1];

    for (auto it = model.begin(); it != model.end(); it++) {
        PFigure figure = *it;
        auto figA = dynamic_pointer_cast<BoundedFigure>(figure);
        if (!figA) { continue; }
        if (!figure->isInsideOrOnBorder(start)) { continue; }
        for (PFigure figure2 : model) {
            if (figure == figure2) {
                continue;
            }
            auto figB = dynamic_pointer_cast<BoundedFigure>(figure2);
            if (figB && figB->isInsideOrOnBorder(end)) {
                auto result = make_shared<SegmentConnection>(figA, figB);
                model.addFigure(result);
                return result;
            }
        }
    }
    return nullptr;
}

PFigure recognizeGrabs(const Track &track, Model &model) {
    Point start = track[0];
    Point end = track[track.size() - 1];

    for (auto it = model.begin(); it != model.end(); it++) {
        PFigure figure = *it;
        if (figure->getApproximateDistanceToBorder(start) <= FIGURE_SELECT_GAP) { // grabbed
            // recognize deletion
            if (isDeletionTrack(track)) {
                model.removeFigure(it);
                return figure;
            }

            // try connection
            auto figA = dynamic_pointer_cast<BoundedFigure>(figure);
            if (figA) {
                for (PFigure figure2 : model) {
                    if (figure == figure2) {
                        continue;
                    }
                    auto figB = dynamic_pointer_cast<BoundedFigure>(figure2);
                    if (figB && figB->getApproximateDistanceToBorder(end) <= FIGURE_SELECT_GAP) {
                        auto result = make_shared<SegmentConnection>(figA, figB);
                        model.addFigure(result);
                        return result;
                    }
                }
            }

            // now we try translation
            figure->translate(end - start);
            model.recalculate();
            return figure;
        }
    }
    return nullptr;
}

void squareBoundedFigure(PBoundedFigure figure) {
    BoundingBox box = figure->getBoundingBox();
    double siz1 = box.width();
    double siz2 = box.height();
    if (siz1 > siz2) {
        std::swap(siz1, siz2);
    }
    std::cout << "bounded size=" << siz1 << ";" << siz2 << "; k=" << (siz1 / siz2) << "\n";
    if (siz1 / siz2 < SQUARING_MIN_RATIO) { return; }

    double siz = (siz1 + siz2) / 2;
    box.rightDown = box.leftUp + Point(siz, siz);
    figure->setBoundingBox(box);
}

struct SelectionFit {
    bool isSegment;
    double distance;
    PFigure figure;

    SelectionFit() : isSegment(false), distance(HUGE_VAL), figure(nullptr) {}
    bool operator<(const SelectionFit &other) const {
        if (isSegment != other.isSegment) { return isSegment > other.isSegment; }
        return distance < other.distance;
    }
};
PFigure recognizeClicks(const Point &click, Model &model) {
    SelectionFit bestFit;
    for (PFigure figure : model) {
        SelectionFit currentFit;
        currentFit.isSegment = !!dynamic_pointer_cast<Segment>(figure);
        currentFit.distance = figure->getApproximateDistanceToBorder(click);
        currentFit.figure = figure;
        if (currentFit.distance >= FIGURE_SELECT_GAP) { continue; }
        bestFit = min(bestFit, currentFit);
    }
    if (bestFit.figure) {
        model.selectedFigure = bestFit.figure;
    }

    std::shared_ptr<Segment> segm = dynamic_pointer_cast<Segment>(model.selectedFigure);
    if (segm) {
        if ((click - segm->getA()).length() <= FIGURE_SELECT_GAP) {
            segm->setArrowedA(!segm->getArrowedA());
        }
        if ((click - segm->getB()).length() <= FIGURE_SELECT_GAP) {
            segm->setArrowedB(!segm->getArrowedB());
        }
        return segm;
    }
    return nullptr;
}

/*
 * Consider a continuos polyline. This function returns its center of mass.
 * Please note that this differs from center of mass of all points of track,
 * we calculate weighted sum of segments' centers (weight == length of segment)
 */
Point getWeightedCenter(const Track &track) {
    Point result;
    double summaryLength = 0;
    for (size_t i = 0; i < track.size(); i++) {
        Point a = track[i];
        Point b = track[(i + 1) % track.size()];
        Point middle = (a + b) * 0.5;
        double length = (b - a).length();
        result += middle * length;
        summaryLength += length;
    }
    result = result * (1.0 / summaryLength);
    return result;
}

/*
 * Calculates best rectangle which will fit the track
 * For example, it considers that there may be some
 * outliners (they happen near corners when drawing on touch devices)
 * First, it calculate approximate center of the rectangle and then
 * it calculates average 'width' and 'height' of the rectangle.
 * Points which differ from the center no more than width/4 are
 * considered 'horizontal segments' and vice-versa for vertical.
 */
BoundingBox getBestFitRectangle(const Track &track) {
    BoundingBox total = getBoundingBox(track);
    double maxDx = total.width() / 4;
    double maxDy = total.height() / 4;
    Point center = getWeightedCenter(track);

    double sumDx = 0, sumDy = 0;
    int countDx = 0, countDy = 0;
    for (Point p : track.points) {
        double dx = fabs(p.x - center.x);
        double dy = fabs(p.y - center.y);
        if (dx < maxDx && dy >= maxDy) {
            sumDy += dy;
            countDy++;
        }
        if (dy < maxDy && dx >= maxDx) {
            sumDx += dx;
            countDx++;
        }
    }
    Point diff(
        countDx ? sumDx / countDx : maxDx,
        countDy ? sumDy / countDy : maxDy
    );
    return BoundingBox({ center - diff, center + diff });
}

PFigure recognize(const Track &_track, Model &model) {
    if (FIGURE_SELECT_GAP < 0 || CLOSED_FIGURE_GAP < 0) {
        throw std::logic_error("Recognition preset is not selected");
    }

    // this is to preserve the API (const Track&) and make future optimizations possible
    // i.e. avoid copying if it's not necessary
    Track track = _track;
    if (track.empty()) { return nullptr; }

    // Very small tracks are clicks
    if (getClosedCircumference(track) <= CLOSED_FIGURE_GAP) {
        return recognizeClicks(track[0], model);
    }

    // Connecting interior-->interior
    if (PFigure result = recognizeConnections(track, model)) {
        return result;
    }

    // Moving and connecting
    if (PFigure result = recognizeGrabs(track, model)) {
        return result;
    }

    // Drawing new figures
    std::vector<PFigure> candidates;
    if (!cutToClosed(track))  {
        candidates.push_back(make_shared<Segment>(track[0], track[track.size() - 1]));
    } else {
        candidates.push_back(make_shared<Ellipse>(getBoundingBox(track)));
        candidates.push_back(make_shared<Rectangle>(getBestFitRectangle(track)));
    }

    if (candidates.empty()) { return nullptr; }

    std::vector<double> fits;
    for (PFigure figure : candidates) {
        fits.push_back(fitsToTrack(track, figure));
    }
    size_t id = max_element(fits.begin(), fits.end()) - fits.begin();
    std::cout << "max_fit = " << fits[id] << "; id = " << id << "\n";
    if (fits[id] >= MIN_FIT_POINTS_AMOUNT) { // we allow some of points to fall out of our track
        auto boundedFigure = dynamic_pointer_cast<BoundedFigure>(candidates[id]);
        if (boundedFigure) {
            squareBoundedFigure(boundedFigure);
        }
        model.addFigure(candidates[id]);
        return candidates[id];
    }
    return nullptr;
}
<commit_msg>recognition: recognizeClicks is now called before recognizeConnections to allow moving one figure inside another<commit_after>#include "model.h"
#include "recognition.h"
#include <memory>
#include <algorithm>
#include <vector>

using std::min;
using std::max;
using std::make_shared;
using std::dynamic_pointer_cast;

int FIGURE_SELECT_GAP = -1;
int CLOSED_FIGURE_GAP = -1;
const int TRACK_FIT_GAP = 10;
const int DELETION_MOVE_MINIMAL_LENGTH = 5;
const int DELETION_MOVE_MAX_ANGLE = 30;
const int DELETION_MOVE_MIN_COUNT = 3;
const double SQUARING_MIN_RATIO = 0.8;
const double MIN_FIT_POINTS_AMOUNT = 0.75;

void setRecognitionPreset(RecognitionPreset preset) {
    switch (preset) {
    case RecognitionPreset::Mouse:
        FIGURE_SELECT_GAP = 10;
        CLOSED_FIGURE_GAP = 10;
        break;
    case RecognitionPreset::Touch:
        FIGURE_SELECT_GAP = 30;
        CLOSED_FIGURE_GAP = 50;
        break;
    };
}

BoundingBox getBoundingBox(const Track &track) {
    BoundingBox res;
    res.leftUp = res.rightDown = track[0];
    for (Point p : track.points) {
        res.leftUp.x = min(res.leftUp.x, p.x);
        res.leftUp.y = min(res.leftUp.y, p.y);
        res.rightDown.x = max(res.rightDown.x, p.x);
        res.rightDown.y = max(res.rightDown.y, p.y);
    }
    return res;
}

double getCircumference(const Track &track) {
    double res = 0;
    for (size_t i = 0; i + 1 < track.size(); i++) {
        res += (track[i + 1] - track[i]).length();
    }
    return res;
}
double getClosedCircumference(const Track &track) {
    double res = getCircumference(track);
    res += (track[0] - track[track.size() - 1]).length();
    return res;
}

bool cutToClosed(Track &track) {
    auto &points = track.points;
    auto it = points.begin();
    while (it != points.end() && (points[0] - *it).length() <= CLOSED_FIGURE_GAP) {
        it++;
    }
    while (it != points.end() && (points[0] - *it).length() > CLOSED_FIGURE_GAP) {
        it++;
    }
    if (it == points.end()) {
        return false;
    }
    while (it != points.end() && (points[0] - *it).length() <= CLOSED_FIGURE_GAP) {
        it++;
    }
    points.erase(it, points.end());
    return true;
}

double fitsToTrack(const Track &track, const PFigure &figure) {
    BoundingBox box = getBoundingBox(track);
    double maxDistance = TRACK_FIT_GAP;
    maxDistance = std::min(maxDistance, std::min(box.width(), box.height()) * 0.2);

    int goodCount = 0;
    for (Point p : track.points) {
        goodCount += figure->getApproximateDistanceToBorder(p) <= maxDistance;
    }

    return goodCount * 1.0 / track.size();
}

using namespace figures;

bool isDeletionTrack(const Track &track) {
    int cnt = 0;
    std::cout << "new\n";
    for (int i = 0; i < (int)track.size(); i++) {
        int prevPoint = i - 1;
        while (prevPoint >= 0 && (track[i] - track[prevPoint]).length() < DELETION_MOVE_MINIMAL_LENGTH) {
            prevPoint--;
        }
        int nextPoint = i + 1;
        while (nextPoint < (int)track.size() && (track[i] - track[nextPoint]).length() < DELETION_MOVE_MINIMAL_LENGTH) {
            nextPoint++;
        }
        if (prevPoint >= 0 && nextPoint < (int)track.size()) {
            Point vec1 = track[nextPoint] - track[i];
            Point vec2 = track[prevPoint] - track[i];
            double ang = acos(Point::dotProduct(vec1, vec2) / (vec1.length() * vec2.length()));
            if (ang <= PI * DELETION_MOVE_MAX_ANGLE / 180) {
                cnt++;
                i = nextPoint;
            }
        }
    }
    std::cout << "deletion cnt = " << cnt << "\n";
    return cnt >= DELETION_MOVE_MIN_COUNT;
}

PFigure recognizeConnections(const Track &track, Model &model) {
    Point start = track[0];
    Point end = track[track.size() - 1];

    for (auto it = model.begin(); it != model.end(); it++) {
        PFigure figure = *it;
        auto figA = dynamic_pointer_cast<BoundedFigure>(figure);
        if (!figA) { continue; }
        if (!figure->isInsideOrOnBorder(start)) { continue; }
        for (PFigure figure2 : model) {
            if (figure == figure2) {
                continue;
            }
            auto figB = dynamic_pointer_cast<BoundedFigure>(figure2);
            if (figB && figB->isInsideOrOnBorder(end)) {
                auto result = make_shared<SegmentConnection>(figA, figB);
                model.addFigure(result);
                return result;
            }
        }
    }
    return nullptr;
}

PFigure recognizeGrabs(const Track &track, Model &model) {
    Point start = track[0];
    Point end = track[track.size() - 1];

    for (auto it = model.begin(); it != model.end(); it++) {
        PFigure figure = *it;
        if (figure->getApproximateDistanceToBorder(start) <= FIGURE_SELECT_GAP) { // grabbed
            // recognize deletion
            if (isDeletionTrack(track)) {
                model.removeFigure(it);
                return figure;
            }

            // try connection
            auto figA = dynamic_pointer_cast<BoundedFigure>(figure);
            if (figA) {
                for (PFigure figure2 : model) {
                    if (figure == figure2) {
                        continue;
                    }
                    auto figB = dynamic_pointer_cast<BoundedFigure>(figure2);
                    if (figB && figB->getApproximateDistanceToBorder(end) <= FIGURE_SELECT_GAP) {
                        auto result = make_shared<SegmentConnection>(figA, figB);
                        model.addFigure(result);
                        return result;
                    }
                }
            }

            // now we try translation
            figure->translate(end - start);
            model.recalculate();
            return figure;
        }
    }
    return nullptr;
}

void squareBoundedFigure(PBoundedFigure figure) {
    BoundingBox box = figure->getBoundingBox();
    double siz1 = box.width();
    double siz2 = box.height();
    if (siz1 > siz2) {
        std::swap(siz1, siz2);
    }
    std::cout << "bounded size=" << siz1 << ";" << siz2 << "; k=" << (siz1 / siz2) << "\n";
    if (siz1 / siz2 < SQUARING_MIN_RATIO) { return; }

    double siz = (siz1 + siz2) / 2;
    box.rightDown = box.leftUp + Point(siz, siz);
    figure->setBoundingBox(box);
}

struct SelectionFit {
    bool isSegment;
    double distance;
    PFigure figure;

    SelectionFit() : isSegment(false), distance(HUGE_VAL), figure(nullptr) {}
    bool operator<(const SelectionFit &other) const {
        if (isSegment != other.isSegment) { return isSegment > other.isSegment; }
        return distance < other.distance;
    }
};
PFigure recognizeClicks(const Point &click, Model &model) {
    SelectionFit bestFit;
    for (PFigure figure : model) {
        SelectionFit currentFit;
        currentFit.isSegment = !!dynamic_pointer_cast<Segment>(figure);
        currentFit.distance = figure->getApproximateDistanceToBorder(click);
        currentFit.figure = figure;
        if (currentFit.distance >= FIGURE_SELECT_GAP) { continue; }
        bestFit = min(bestFit, currentFit);
    }
    if (bestFit.figure) {
        model.selectedFigure = bestFit.figure;
    }

    std::shared_ptr<Segment> segm = dynamic_pointer_cast<Segment>(model.selectedFigure);
    if (segm) {
        if ((click - segm->getA()).length() <= FIGURE_SELECT_GAP) {
            segm->setArrowedA(!segm->getArrowedA());
        }
        if ((click - segm->getB()).length() <= FIGURE_SELECT_GAP) {
            segm->setArrowedB(!segm->getArrowedB());
        }
        return segm;
    }
    return nullptr;
}

/*
 * Consider a continuos polyline. This function returns its center of mass.
 * Please note that this differs from center of mass of all points of track,
 * we calculate weighted sum of segments' centers (weight == length of segment)
 */
Point getWeightedCenter(const Track &track) {
    Point result;
    double summaryLength = 0;
    for (size_t i = 0; i < track.size(); i++) {
        Point a = track[i];
        Point b = track[(i + 1) % track.size()];
        Point middle = (a + b) * 0.5;
        double length = (b - a).length();
        result += middle * length;
        summaryLength += length;
    }
    result = result * (1.0 / summaryLength);
    return result;
}

/*
 * Calculates best rectangle which will fit the track
 * For example, it considers that there may be some
 * outliners (they happen near corners when drawing on touch devices)
 * First, it calculate approximate center of the rectangle and then
 * it calculates average 'width' and 'height' of the rectangle.
 * Points which differ from the center no more than width/4 are
 * considered 'horizontal segments' and vice-versa for vertical.
 */
BoundingBox getBestFitRectangle(const Track &track) {
    BoundingBox total = getBoundingBox(track);
    double maxDx = total.width() / 4;
    double maxDy = total.height() / 4;
    Point center = getWeightedCenter(track);

    double sumDx = 0, sumDy = 0;
    int countDx = 0, countDy = 0;
    for (Point p : track.points) {
        double dx = fabs(p.x - center.x);
        double dy = fabs(p.y - center.y);
        if (dx < maxDx && dy >= maxDy) {
            sumDy += dy;
            countDy++;
        }
        if (dy < maxDy && dx >= maxDx) {
            sumDx += dx;
            countDx++;
        }
    }
    Point diff(
        countDx ? sumDx / countDx : maxDx,
        countDy ? sumDy / countDy : maxDy
    );
    return BoundingBox({ center - diff, center + diff });
}

PFigure recognize(const Track &_track, Model &model) {
    if (FIGURE_SELECT_GAP < 0 || CLOSED_FIGURE_GAP < 0) {
        throw std::logic_error("Recognition preset is not selected");
    }

    // this is to preserve the API (const Track&) and make future optimizations possible
    // i.e. avoid copying if it's not necessary
    Track track = _track;
    if (track.empty()) { return nullptr; }

    // Very small tracks are clicks
    if (getClosedCircumference(track) <= CLOSED_FIGURE_GAP) {
        return recognizeClicks(track[0], model);
    }

    // Moving and connecting
    if (PFigure result = recognizeGrabs(track, model)) {
        return result;
    }

    // Connecting interior-->interior
    if (PFigure result = recognizeConnections(track, model)) {
        return result;
    }

    // Drawing new figures
    std::vector<PFigure> candidates;
    if (!cutToClosed(track))  {
        candidates.push_back(make_shared<Segment>(track[0], track[track.size() - 1]));
    } else {
        candidates.push_back(make_shared<Ellipse>(getBoundingBox(track)));
        candidates.push_back(make_shared<Rectangle>(getBestFitRectangle(track)));
    }

    if (candidates.empty()) { return nullptr; }

    std::vector<double> fits;
    for (PFigure figure : candidates) {
        fits.push_back(fitsToTrack(track, figure));
    }
    size_t id = max_element(fits.begin(), fits.end()) - fits.begin();
    std::cout << "max_fit = " << fits[id] << "; id = " << id << "\n";
    if (fits[id] >= MIN_FIT_POINTS_AMOUNT) { // we allow some of points to fall out of our track
        auto boundedFigure = dynamic_pointer_cast<BoundedFigure>(candidates[id]);
        if (boundedFigure) {
            squareBoundedFigure(boundedFigure);
        }
        model.addFigure(candidates[id]);
        return candidates[id];
    }
    return nullptr;
}
<|endoftext|>


<commit_before>#ifndef EMULATOR_VERSION_H
#define EMULATOR_VERSION_H

/* Name of the Emulator */
#define EMULATOR_NAME "LIBPSX"

/* Emulator version */
#define EMULATOR_MAJOR_VERSION (1)
#define EMULATOR_MINOR_VERSION (139)

/* Compile date and time */
#define EMULATOR_COMPILE_DATE (__DATE__)
#define EMULATOR_COMPILE_TIME (__TIME__)

/* Psy-Q version */
#define PSYQ_MAJOR_VERSION (4)
#define PSYQ_MINOR_VERSION (7)

#endif<commit_msg>[Emu]: Implement FntLoad.<commit_after>#ifndef EMULATOR_VERSION_H
#define EMULATOR_VERSION_H

/* Name of the Emulator */
#define EMULATOR_NAME "LIBPSX"

/* Emulator version */
#define EMULATOR_MAJOR_VERSION (1)
#define EMULATOR_MINOR_VERSION (140)

/* Compile date and time */
#define EMULATOR_COMPILE_DATE (__DATE__)
#define EMULATOR_COMPILE_TIME (__TIME__)

/* Psy-Q version */
#define PSYQ_MAJOR_VERSION (4)
#define PSYQ_MINOR_VERSION (7)

#endif<|endoftext|>


<commit_before>#include <iostream>
#include <vector>

using namespace std;

class prime
{
public:
    static const vector<array<long long, 1000>> *pPrimeTable;

};

int main(int argc, char *argv[])
{
    cout << "Hello World!" << endl;
    return 0;
}<commit_msg>WIP: processing prime, leave _expand unfinished<commit_after>#include <iostream>
#include <vector>
#include <array>
#include <ostream>
#include <stdexcept>

using namespace std;

typedef long long lld;
typedef unsigned long long llu;

class prime
{
public:
    typedef llu value_type;
    typedef size_t size_type;
    typedef ptrdiff_t difference_type;
    typedef const value_type& const_reference;
    typedef const value_type* const_pointer;

private:
    difference_type end_index;
    static vector<array<llu, 1000>> prime_table;
    static size_type prime_size;
    static llu max_prime;

public:
    class prime_iterator : public iterator<random_access_iterator_tag, llu>
    {
        friend class prime;

        size_type iter_index;
    public:
        prime_iterator(size_t n = 0) : iter_index(n)
        {
        }

        reference operator*() const {
            return prime_table[iter_index / 1000][iter_index % 1000];
        }

        prime_iterator& operator++() {
            ++iter_index;
            return *this;
        }

        prime_iterator operator++(int) {
            return prime_iterator(iter_index++);
        }

        prime_iterator& operator--() {
            --iter_index;
            return *this;
        }

        prime_iterator operator--(int) {
            return prime_iterator(iter_index--);
        }

        bool operator==(const prime_iterator& other)const {
            return iter_index == other.iter_index;
        }

        bool operator!=(const prime_iterator& other)const {
            return iter_index != other.iter_index;
        }
    };

    typedef prime_iterator const_iterator;
    typedef reverse_iterator<const_iterator> const_reverse_iterator;

    class primeException : public out_of_range
    {
        friend class prime;

        primeException() : out_of_range("Index out of range\n")
        {
        }
    };

private:
    static void _expand(size_type n)
    {
        // TODO
    }

public:

    prime(size_type n = 1000)
    {
        if (max_prime < n)
        {
            _expand(n);
        }
        end_index = prime_size;
    }

    prime(const prime &other) : end_index(other.end_index)
    {
    }

    prime(prime &&other) : end_index(other.end_index)
    {
    }

    ~prime()
    {
    }

    prime& operator=(const prime &other) {
        end_index = other.end_index;
        return *this;
    }

    prime& operator=(prime &&other) {
        end_index = other.end_index;
        return *this;
    }

    llu operator[](size_type k) const
    {
        if (k > prime_size)
        {
            throw primeException();
        }
        return prime_table[k / 1000][k % 1000];
    }

    void clear() const
    {
        prime_table.clear();
    }

    void print(ostream &out = cout) const
    {
        for (auto prime : *this)
        {
            out << prime << '\t';
        }
        out << endl;
    }

    llu maxPrime() const
    {
        return max_prime;
    }

    size_type primeCount() const
    {
        return prime_size;
    }

    difference_type expand(size_type n) const
    {
        if (n <= max_prime)
        {
            return 0;
        }
        else
        {
            auto old_size = prime_size;
            _expand(n);
            return prime_size - old_size;
        }
    }

    const_iterator begin() const {
        return const_iterator();
    }

    const_iterator cbegin() const {
        return const_iterator();
    }

    const_iterator end() const {
        return const_iterator(prime_size);
    }

    const_iterator cend() const {
        return const_iterator(prime_size);
    }

    const_reverse_iterator rbegin() const
    {
        return const_reverse_iterator(end());
    }

    const_reverse_iterator crbegin() const
    {
        return const_reverse_iterator(end());
    }

    const_reverse_iterator rend() const
    {
        return const_reverse_iterator(begin());
    }

    const_reverse_iterator crend() const
    {
        return const_reverse_iterator(begin());
    }
};

vector<array<llu, 1000>> prime::prime_table = vector<array<llu, 1000>>();
prime::size_type prime::prime_size = 0;
llu prime::max_prime = 0;

void Test()
{
    prime tmp(2000);
    tmp.print();
}

int main(int argc, char *argv[])
{
    prime myPrime(20000);
    prime hisPrime(200);
    prime herPrime(200000);
    auto itsPrime = myPrime;
    cout << itsPrime[100] << endl;

    for (auto iter = myPrime.begin(); iter != myPrime.end(); ++iter)
    {
        cout << *iter << "\t";
    }

    cout << myPrime.maxPrime() << endl;
    cout << myPrime.primeCount() << endl;
    cout << myPrime.expand(1000000) << endl;

    return 0;
}<|endoftext|>


<commit_before>/**
 *
 * Emerald (kbi/elude @2012-2015)
 *
 */
#include "test_shader.h"
#include "gtest/gtest.h"
#include "shared.h"
#include "system/system_hashed_ansi_string.h"
#include "ogl/ogl_context.h"
#include "ogl/ogl_rendering_handler.h"
#include "ogl/ogl_program.h"
#include "ogl/ogl_shader.h"
#include "system/system_matrix4x4.h"
#include "system/system_pixel_format.h"
#include "system/system_window.h"

bool             triangle_test_is_first_frame             = true;
GLuint           triangle_test_position_bo_id             = -1;
GLuint           triangle_test_position_vao_id            = -1;
GLint            triangle_test_position_location          = -1;
GLint            triangle_test_program_id                 = -1;
system_matrix4x4 triangle_test_projection_matrix          = NULL;
GLint            triangle_test_projection_matrix_location = -1;
system_matrix4x4 triangle_test_view_matrix                = NULL;
GLint            triangle_test_view_matrix_location       = -1;

GLfloat triangle_test_position_data[] = { 0.0f,  0.5f, -1.0f, 1.0f,
                                          1.0f, -1.0f, -1.0f, 1.0f,
                                         -1.0f, -1.0f, -1.0f, 1.0f};

static void _on_render_frame_triangle_test_callback(ogl_context context,
                                                    uint32_t    n_frames_rendered,
                                                    system_time frame_time,
                                                    const int*  rendering_area_px_topdown,
                                                    void*)
{
    const ogl_context_gl_entrypoints* entry_points = NULL;

    ogl_context_get_property(context,
                             OGL_CONTEXT_PROPERTY_ENTRYPOINTS_GL,
                            &entry_points);

    /* Got to do a couple of things if this is the first frame */
    if (triangle_test_is_first_frame)
    {
        entry_points->pGLUseProgram(triangle_test_program_id);

        /* Set up the uniforms */
        entry_points->pGLProgramUniformMatrix4fv(triangle_test_program_id,
                                                 triangle_test_projection_matrix_location,
                                                 1,     /* count */
                                                 false, /* transpose */
                                                 system_matrix4x4_get_row_major_data(triangle_test_projection_matrix) );
        entry_points->pGLProgramUniformMatrix4fv(triangle_test_program_id, triangle_test_view_matrix_location,
                                                 1,    /* count */
                                                 true, /* transpose */
                                                 system_matrix4x4_get_row_major_data(triangle_test_view_matrix) );
        ASSERT_EQ                               (entry_points->pGLGetError(),
                                                 GL_NO_ERROR);

        /* Set up buffer object for position data */
        entry_points->pGLGenBuffers(1,
                                   &triangle_test_position_bo_id);
        ASSERT_NE                  (triangle_test_position_bo_id,
                                    -1);
        ASSERT_EQ                  (entry_points->pGLGetError(),
                                    GL_NO_ERROR);

        entry_points->pGLBindBuffer(GL_ARRAY_BUFFER,
                                    triangle_test_position_bo_id);
        ASSERT_EQ                  (entry_points->pGLGetError(),
                                    GL_NO_ERROR);
        entry_points->pGLBufferData(GL_ARRAY_BUFFER,
                                    sizeof(triangle_test_position_data),
                                    triangle_test_position_data,
                                    GL_STATIC_DRAW);
        ASSERT_EQ                  (entry_points->pGLGetError(),
                                    GL_NO_ERROR);

        /* Set up VAOs */
        entry_points->pGLGenVertexArrays(1,
                                        &triangle_test_position_vao_id);
        ASSERT_NE                       (triangle_test_position_vao_id,
                                         -1);

        entry_points->pGLBindVertexArray(triangle_test_position_vao_id);

        entry_points->pGLEnableVertexAttribArray(triangle_test_position_location);
        entry_points->pGLVertexAttribPointer    (triangle_test_position_location,
                                                 4,        /* size */
                                                 GL_FLOAT,
                                                 0,        /* normalized */
                                                 0,        /* stride */
                                                 0);       /* pointer */

        /* Set up clear color */
        entry_points->pGLClearColor(1.0f,  /* red   */
                                    0,     /* green */
                                    1.0f,  /* blue  */
                                    1);    /* alpha */

        /* Good. */
        triangle_test_is_first_frame = false;
    }

    entry_points->pGLClear          (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    entry_points->pGLBindVertexArray(triangle_test_position_vao_id);
    entry_points->pGLDrawArrays     (GL_TRIANGLES,
                                     0,  /* first */
                                     3); /* count */
}

static void _on_render_frame_creation_test_callback(ogl_context context,
                                                    uint32_t    n_frames_rendered,
                                                    system_time frame_time,
                                                    const int*  rendering_area_px_topdown,
                                                    void*)
{
    const ogl_context_gl_entrypoints* entry_points = NULL;

    ogl_context_get_property(context,
                             OGL_CONTEXT_PROPERTY_ENTRYPOINTS_GL,
                            &entry_points);

    entry_points->pGLClearColor(0.75f, /* red */
                                0,     /* green */
                                0,     /* blue */
                                1.0f); /* alpha */
    entry_points->pGLClear     (GL_COLOR_BUFFER_BIT);
}

TEST(ShaderTest, CreationTest)
{
    /* Create the window */
    const int           xywh[]        = {0, 0, 320, 240};
    system_pixel_format window_pf     = system_pixel_format_create         (8,  /* color_buffer_red_bits   */
                                                                            8,  /* color_buffer_green_bits */
                                                                            8,  /* color_buffer_blue_bits  */
                                                                            0,  /* color_buffer_alpha_bits */
                                                                            0,  /* depth_buffer_bits       */
                                                                            1,  /* n_samples               */
                                                                            0); /* stencil_buffer_bits     */
    system_window       window_handle = system_window_create_not_fullscreen(OGL_CONTEXT_TYPE_GL,
                                                                            xywh,
                                                                            system_hashed_ansi_string_create("Test window"),
                                                                            false,
                                                                            true,  /* vsync_enabled */
                                                                            false, /* visible */
                                                                            window_pf);

#ifdef _WIN32
    HWND          window_sys_handle = 0;
#endif

    ASSERT_TRUE(window_handle != NULL);

#ifdef _WIN32
    system_window_get_property(window_handle,
                               SYSTEM_WINDOW_PROPERTY_HANDLE,
                              &window_sys_handle);
    ASSERT_EQ                (::IsWindow(window_sys_handle),
                              TRUE);
#endif

    /* Create a rendering handler */
    ogl_rendering_handler rendering_handler = ogl_rendering_handler_create_with_max_performance_policy(system_hashed_ansi_string_create("rendering handler"),
                                                                                _on_render_frame_creation_test_callback,
                                                                                0); /* argument */

    ASSERT_TRUE(rendering_handler != NULL);

    /* Bind the handler to the window */
    system_window_set_property(window_handle,
                               SYSTEM_WINDOW_PROPERTY_RENDERING_HANDLER,
                              &rendering_handler);

    /* Create the test shader */
    ogl_context gl_context  = NULL;
    ogl_shader  test_shader = NULL;

    system_window_get_property(window_handle,
                               SYSTEM_WINDOW_PROPERTY_RENDERING_CONTEXT,
                              &gl_context);

    test_shader = ogl_shader_create(gl_context,
                                    SHADER_TYPE_FRAGMENT,
                                    system_hashed_ansi_string_create("test shader") );

    ASSERT_TRUE(test_shader != NULL);

    ogl_shader_set_body(test_shader,
                        system_hashed_ansi_string_create("void main()\n"
                                                         "{\n"
                                                         "  gl_FragColor.xyz = vec3(0, 0.25, 0.5);\n"
                                                         "}")
                       );
    ASSERT_TRUE(ogl_shader_compile(test_shader) );

    ogl_shader_release(test_shader);

    /* Destroy the window in a blunt way */
    ASSERT_TRUE(system_window_close(window_handle) );

#ifdef _WIN32
    ASSERT_EQ  (::IsWindow         (window_sys_handle),
                FALSE);
#endif
}

TEST(ShaderTest, FullViewportTriangleTest)
{
    /* Create the window */
    const int           xywh[]        = {0, 0, 320, 240};
    system_pixel_format window_pf     = system_pixel_format_create         (8,  /* color_buffer_red_bits   */
                                                                            8,  /* color_buffer_green_bits */
                                                                            8,  /* color_buffer_blue_bits  */
                                                                            0,  /* color_buffer_alpha_bits */
                                                                            0,  /* depth_buffer_bits       */
                                                                            16, /* n_samples               */
                                                                            0); /* stencil_buffer_bits     */
    system_window       window_handle = system_window_create_not_fullscreen(OGL_CONTEXT_TYPE_GL,
                                                                            xywh,
                                                                            system_hashed_ansi_string_create("Test window"),
                                                                            false,
                                                                            false, /* vsync_enabled */
                                                                            true,  /* visible */
                                                                            window_pf);

#ifdef _WIN32
    HWND          window_sys_handle = 0;

    ASSERT_TRUE(window_handle != NULL);

    system_window_get_property(window_handle,
                               SYSTEM_WINDOW_PROPERTY_HANDLE,
                              &window_sys_handle);
    ASSERT_EQ                (::IsWindow(window_sys_handle),
                              TRUE);
#endif

    /* Create a rendering handler */
    ogl_rendering_handler rendering_handler = ogl_rendering_handler_create_with_max_performance_policy(system_hashed_ansi_string_create("rendering handler"),
                                                                                _on_render_frame_triangle_test_callback,
                                                                                0); /* argument */

    ASSERT_TRUE(rendering_handler != NULL);

    /* Bind the handler to the window */
    system_window_set_property(window_handle,
                               SYSTEM_WINDOW_PROPERTY_RENDERING_HANDLER,
                              &rendering_handler);

    /* Create the test vertex shader */
    ogl_context gl_context         = NULL;
    ogl_shader  test_vertex_shader = NULL;

    system_window_get_property(window_handle,
                               SYSTEM_WINDOW_PROPERTY_RENDERING_CONTEXT,
                              &gl_context);

    test_vertex_shader = ogl_shader_create(gl_context,
                                           SHADER_TYPE_VERTEX,
                                           system_hashed_ansi_string_create("test vertex shader") );

    ASSERT_TRUE(test_vertex_shader != NULL);

    ogl_shader_set_body(test_vertex_shader,
                        system_hashed_ansi_string_create("#version 430 core\n"
                                                         "\n"
                                                         "uniform mat4 view_matrix;\n"
                                                         "uniform mat4 projection_matrix;\n"
                                                         "\n"
                                                         "in vec4 position;\n"
                                                         "\n"
                                                         "void main()\n"
                                                         "{\n"
                                                         "gl_Position = projection_matrix * view_matrix * position;"
                                                         "}\n"
                                                        )
                       );

    ASSERT_TRUE(ogl_shader_compile(test_vertex_shader) );

    /* Create the test fragment shader */
    ogl_shader test_fragment_shader = ogl_shader_create(gl_context,
                                                        SHADER_TYPE_FRAGMENT,
                                                        system_hashed_ansi_string_create("test fragment shader") );

    ASSERT_TRUE(test_fragment_shader != NULL);

    ogl_shader_set_body(test_fragment_shader,
                        system_hashed_ansi_string_create("void main()\n"
                                                         "{\n"
                                                         "  gl_FragColor.xyz = vec3((gl_FragCoord.x - 0.5)/320.0, (gl_FragCoord.y - 0.5) / 240.0, 0.5);\n"
                                                         "}")
                       );

    ASSERT_TRUE(ogl_shader_compile(test_fragment_shader) );

    /* Create the test program */
    ogl_program test_program = ogl_program_create(gl_context,
                                                  system_hashed_ansi_string_create("test program") );
    ASSERT_TRUE(test_program != NULL);

    ASSERT_TRUE(ogl_program_attach_shader(test_program,
                                          test_vertex_shader) );
    ASSERT_TRUE(ogl_program_attach_shader(test_program,
                                          test_fragment_shader) );
    ASSERT_TRUE(ogl_program_link         (test_program) );

    /* Retrieve test program id */
    triangle_test_program_id = ogl_program_get_id(test_program);

    ASSERT_NE(triangle_test_program_id, -1);

    /* Retrieve uniform locations */
    const ogl_program_variable* projection_matrix_uniform_descriptor = NULL;
    const ogl_program_variable* view_matrix_uniform_descriptor       = NULL;

    ASSERT_TRUE(ogl_program_get_uniform_by_name(test_program,
                                                system_hashed_ansi_string_create("view_matrix"),
                                               &view_matrix_uniform_descriptor) );
    ASSERT_TRUE(ogl_program_get_uniform_by_name(test_program,
                                                system_hashed_ansi_string_create("projection_matrix"),
                                               &projection_matrix_uniform_descriptor) );

    triangle_test_projection_matrix_location = projection_matrix_uniform_descriptor->location;
    triangle_test_view_matrix_location       = view_matrix_uniform_descriptor->location;

    ASSERT_NE(triangle_test_projection_matrix_location,
              -1);
    ASSERT_NE(triangle_test_view_matrix_location,
              -1);

    /* Retrieve attribute location */
    const ogl_program_attribute_descriptor* position_attribute_descriptor = NULL;

    ASSERT_TRUE(ogl_program_get_attribute_by_name(test_program,
                                                  system_hashed_ansi_string_create("position"),
                                                 &position_attribute_descriptor) );

    triangle_test_position_location = position_attribute_descriptor->location;

    ASSERT_NE(triangle_test_position_location,
              -1);

    /* Create a projection matrix */
    triangle_test_projection_matrix = system_matrix4x4_create_perspective_projection_matrix(53.0f,           /* fov_y */
                                                                                320.0f / 240.0f, /* ar */
                                                                                0.05f,           /* z_near */
                                                                                25);             /* z_far */

    ASSERT_TRUE(triangle_test_projection_matrix != NULL);

    /* Create a view matrix */
    triangle_test_view_matrix = system_matrix4x4_create();

    system_matrix4x4_set_to_identity(triangle_test_view_matrix);

    /* Let's render a couple of frames. */
    ASSERT_TRUE(ogl_rendering_handler_play(rendering_handler,
                                           0) );

#ifdef _WIN32
    ::Sleep(1000);
#else
    sleep(1);
#endif

    /* Stop playing so that we can release */
    ASSERT_TRUE(ogl_rendering_handler_stop(rendering_handler) );

    /* Release */
    ogl_program_release     (test_program);
    ogl_shader_release      (test_fragment_shader);
    ogl_shader_release      (test_vertex_shader);
    system_matrix4x4_release(triangle_test_projection_matrix);
    system_matrix4x4_release(triangle_test_view_matrix);

    /* Destroy the window in a blunt way */
    ASSERT_TRUE(system_window_close(window_handle) );

#ifdef _WIN32
    ASSERT_EQ  (::IsWindow(window_sys_handle),
                FALSE);
#endif
}

<commit_msg>Functional tests: Adjusted FullViewportTriangleTest test impl so that it works on arch's not supporting 16 samples for the requested pixel format.<commit_after>/**
 *
 * Emerald (kbi/elude @2012-2015)
 *
 */
#include "test_shader.h"
#include "gtest/gtest.h"
#include "shared.h"
#include "system/system_hashed_ansi_string.h"
#include "ogl/ogl_context.h"
#include "ogl/ogl_rendering_handler.h"
#include "ogl/ogl_program.h"
#include "ogl/ogl_shader.h"
#include "system/system_matrix4x4.h"
#include "system/system_pixel_format.h"
#include "system/system_window.h"

bool             triangle_test_is_first_frame             = true;
GLuint           triangle_test_position_bo_id             = -1;
GLuint           triangle_test_position_vao_id            = -1;
GLint            triangle_test_position_location          = -1;
GLint            triangle_test_program_id                 = -1;
system_matrix4x4 triangle_test_projection_matrix          = NULL;
GLint            triangle_test_projection_matrix_location = -1;
system_matrix4x4 triangle_test_view_matrix                = NULL;
GLint            triangle_test_view_matrix_location       = -1;

GLfloat triangle_test_position_data[] = { 0.0f,  0.5f, -1.0f, 1.0f,
                                          1.0f, -1.0f, -1.0f, 1.0f,
                                         -1.0f, -1.0f, -1.0f, 1.0f};

static void _on_render_frame_triangle_test_callback(ogl_context context,
                                                    uint32_t    n_frames_rendered,
                                                    system_time frame_time,
                                                    const int*  rendering_area_px_topdown,
                                                    void*)
{
    const ogl_context_gl_entrypoints* entry_points = NULL;

    ogl_context_get_property(context,
                             OGL_CONTEXT_PROPERTY_ENTRYPOINTS_GL,
                            &entry_points);

    /* Got to do a couple of things if this is the first frame */
    if (triangle_test_is_first_frame)
    {
        entry_points->pGLUseProgram(triangle_test_program_id);

        /* Set up the uniforms */
        entry_points->pGLProgramUniformMatrix4fv(triangle_test_program_id,
                                                 triangle_test_projection_matrix_location,
                                                 1,     /* count */
                                                 false, /* transpose */
                                                 system_matrix4x4_get_row_major_data(triangle_test_projection_matrix) );
        entry_points->pGLProgramUniformMatrix4fv(triangle_test_program_id, triangle_test_view_matrix_location,
                                                 1,    /* count */
                                                 true, /* transpose */
                                                 system_matrix4x4_get_row_major_data(triangle_test_view_matrix) );
        ASSERT_EQ                               (entry_points->pGLGetError(),
                                                 GL_NO_ERROR);

        /* Set up buffer object for position data */
        entry_points->pGLGenBuffers(1,
                                   &triangle_test_position_bo_id);
        ASSERT_NE                  (triangle_test_position_bo_id,
                                    -1);
        ASSERT_EQ                  (entry_points->pGLGetError(),
                                    GL_NO_ERROR);

        entry_points->pGLBindBuffer(GL_ARRAY_BUFFER,
                                    triangle_test_position_bo_id);
        ASSERT_EQ                  (entry_points->pGLGetError(),
                                    GL_NO_ERROR);
        entry_points->pGLBufferData(GL_ARRAY_BUFFER,
                                    sizeof(triangle_test_position_data),
                                    triangle_test_position_data,
                                    GL_STATIC_DRAW);
        ASSERT_EQ                  (entry_points->pGLGetError(),
                                    GL_NO_ERROR);

        /* Set up VAOs */
        entry_points->pGLGenVertexArrays(1,
                                        &triangle_test_position_vao_id);
        ASSERT_NE                       (triangle_test_position_vao_id,
                                         -1);

        entry_points->pGLBindVertexArray(triangle_test_position_vao_id);

        entry_points->pGLEnableVertexAttribArray(triangle_test_position_location);
        entry_points->pGLVertexAttribPointer    (triangle_test_position_location,
                                                 4,        /* size */
                                                 GL_FLOAT,
                                                 0,        /* normalized */
                                                 0,        /* stride */
                                                 0);       /* pointer */

        /* Set up clear color */
        entry_points->pGLClearColor(1.0f,  /* red   */
                                    0,     /* green */
                                    1.0f,  /* blue  */
                                    1);    /* alpha */

        /* Good. */
        triangle_test_is_first_frame = false;
    }

    entry_points->pGLClear          (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    entry_points->pGLBindVertexArray(triangle_test_position_vao_id);
    entry_points->pGLDrawArrays     (GL_TRIANGLES,
                                     0,  /* first */
                                     3); /* count */
}

static void _on_render_frame_creation_test_callback(ogl_context context,
                                                    uint32_t    n_frames_rendered,
                                                    system_time frame_time,
                                                    const int*  rendering_area_px_topdown,
                                                    void*)
{
    const ogl_context_gl_entrypoints* entry_points = NULL;

    ogl_context_get_property(context,
                             OGL_CONTEXT_PROPERTY_ENTRYPOINTS_GL,
                            &entry_points);

    entry_points->pGLClearColor(0.75f, /* red */
                                0,     /* green */
                                0,     /* blue */
                                1.0f); /* alpha */
    entry_points->pGLClear     (GL_COLOR_BUFFER_BIT);
}

TEST(ShaderTest, CreationTest)
{
    /* Create the window */
    const int           xywh[]        = {0, 0, 320, 240};
    system_pixel_format window_pf     = system_pixel_format_create         (8,  /* color_buffer_red_bits   */
                                                                            8,  /* color_buffer_green_bits */
                                                                            8,  /* color_buffer_blue_bits  */
                                                                            0,  /* color_buffer_alpha_bits */
                                                                            0,  /* depth_buffer_bits       */
                                                                            1,  /* n_samples               */
                                                                            0); /* stencil_buffer_bits     */
    system_window       window_handle = system_window_create_not_fullscreen(OGL_CONTEXT_TYPE_GL,
                                                                            xywh,
                                                                            system_hashed_ansi_string_create("Test window"),
                                                                            false,
                                                                            true,  /* vsync_enabled */
                                                                            false, /* visible */
                                                                            window_pf);

#ifdef _WIN32
    HWND          window_sys_handle = 0;
#endif

    ASSERT_TRUE(window_handle != NULL);

#ifdef _WIN32
    system_window_get_property(window_handle,
                               SYSTEM_WINDOW_PROPERTY_HANDLE,
                              &window_sys_handle);
    ASSERT_EQ                (::IsWindow(window_sys_handle),
                              TRUE);
#endif

    /* Create a rendering handler */
    ogl_rendering_handler rendering_handler = ogl_rendering_handler_create_with_max_performance_policy(system_hashed_ansi_string_create("rendering handler"),
                                                                                _on_render_frame_creation_test_callback,
                                                                                0); /* argument */

    ASSERT_TRUE(rendering_handler != NULL);

    /* Bind the handler to the window */
    system_window_set_property(window_handle,
                               SYSTEM_WINDOW_PROPERTY_RENDERING_HANDLER,
                              &rendering_handler);

    /* Create the test shader */
    ogl_context gl_context  = NULL;
    ogl_shader  test_shader = NULL;

    system_window_get_property(window_handle,
                               SYSTEM_WINDOW_PROPERTY_RENDERING_CONTEXT,
                              &gl_context);

    test_shader = ogl_shader_create(gl_context,
                                    SHADER_TYPE_FRAGMENT,
                                    system_hashed_ansi_string_create("test shader") );

    ASSERT_TRUE(test_shader != NULL);

    ogl_shader_set_body(test_shader,
                        system_hashed_ansi_string_create("void main()\n"
                                                         "{\n"
                                                         "  gl_FragColor.xyz = vec3(0, 0.25, 0.5);\n"
                                                         "}")
                       );
    ASSERT_TRUE(ogl_shader_compile(test_shader) );

    ogl_shader_release(test_shader);

    /* Destroy the window in a blunt way */
    ASSERT_TRUE(system_window_close(window_handle) );

#ifdef _WIN32
    ASSERT_EQ  (::IsWindow         (window_sys_handle),
                FALSE);
#endif
}

TEST(ShaderTest, FullViewportTriangleTest)
{
    /* Create the window */
    const int           xywh[]        = {0, 0, 320, 240};
    system_pixel_format window_pf     = system_pixel_format_create         (8,  /* color_buffer_red_bits   */
                                                                            8,  /* color_buffer_green_bits */
                                                                            8,  /* color_buffer_blue_bits  */
                                                                            0,  /* color_buffer_alpha_bits */
                                                                            0,  /* depth_buffer_bits       */
                                                                            SYSTEM_PIXEL_FORMAT_USE_MAXIMUM_NUMBER_OF_SAMPLES,
                                                                            0); /* stencil_buffer_bits     */
    system_window       window_handle = system_window_create_not_fullscreen(OGL_CONTEXT_TYPE_GL,
                                                                            xywh,
                                                                            system_hashed_ansi_string_create("Test window"),
                                                                            false,
                                                                            false, /* vsync_enabled */
                                                                            true,  /* visible */
                                                                            window_pf);

#ifdef _WIN32
    HWND          window_sys_handle = 0;

    ASSERT_TRUE(window_handle != NULL);

    system_window_get_property(window_handle,
                               SYSTEM_WINDOW_PROPERTY_HANDLE,
                              &window_sys_handle);
    ASSERT_EQ                (::IsWindow(window_sys_handle),
                              TRUE);
#endif

    /* Create a rendering handler */
    ogl_rendering_handler rendering_handler = ogl_rendering_handler_create_with_max_performance_policy(system_hashed_ansi_string_create("rendering handler"),
                                                                                _on_render_frame_triangle_test_callback,
                                                                                0); /* argument */

    ASSERT_TRUE(rendering_handler != NULL);

    /* Bind the handler to the window */
    system_window_set_property(window_handle,
                               SYSTEM_WINDOW_PROPERTY_RENDERING_HANDLER,
                              &rendering_handler);

    /* Create the test vertex shader */
    ogl_context gl_context         = NULL;
    ogl_shader  test_vertex_shader = NULL;

    system_window_get_property(window_handle,
                               SYSTEM_WINDOW_PROPERTY_RENDERING_CONTEXT,
                              &gl_context);

    test_vertex_shader = ogl_shader_create(gl_context,
                                           SHADER_TYPE_VERTEX,
                                           system_hashed_ansi_string_create("test vertex shader") );

    ASSERT_TRUE(test_vertex_shader != NULL);

    ogl_shader_set_body(test_vertex_shader,
                        system_hashed_ansi_string_create("#version 430 core\n"
                                                         "\n"
                                                         "uniform mat4 view_matrix;\n"
                                                         "uniform mat4 projection_matrix;\n"
                                                         "\n"
                                                         "in vec4 position;\n"
                                                         "\n"
                                                         "void main()\n"
                                                         "{\n"
                                                         "gl_Position = projection_matrix * view_matrix * position;"
                                                         "}\n"
                                                        )
                       );

    ASSERT_TRUE(ogl_shader_compile(test_vertex_shader) );

    /* Create the test fragment shader */
    ogl_shader test_fragment_shader = ogl_shader_create(gl_context,
                                                        SHADER_TYPE_FRAGMENT,
                                                        system_hashed_ansi_string_create("test fragment shader") );

    ASSERT_TRUE(test_fragment_shader != NULL);

    ogl_shader_set_body(test_fragment_shader,
                        system_hashed_ansi_string_create("void main()\n"
                                                         "{\n"
                                                         "  gl_FragColor.xyz = vec3((gl_FragCoord.x - 0.5)/320.0, (gl_FragCoord.y - 0.5) / 240.0, 0.5);\n"
                                                         "}")
                       );

    ASSERT_TRUE(ogl_shader_compile(test_fragment_shader) );

    /* Create the test program */
    ogl_program test_program = ogl_program_create(gl_context,
                                                  system_hashed_ansi_string_create("test program") );
    ASSERT_TRUE(test_program != NULL);

    ASSERT_TRUE(ogl_program_attach_shader(test_program,
                                          test_vertex_shader) );
    ASSERT_TRUE(ogl_program_attach_shader(test_program,
                                          test_fragment_shader) );
    ASSERT_TRUE(ogl_program_link         (test_program) );

    /* Retrieve test program id */
    triangle_test_program_id = ogl_program_get_id(test_program);

    ASSERT_NE(triangle_test_program_id, -1);

    /* Retrieve uniform locations */
    const ogl_program_variable* projection_matrix_uniform_descriptor = NULL;
    const ogl_program_variable* view_matrix_uniform_descriptor       = NULL;

    ASSERT_TRUE(ogl_program_get_uniform_by_name(test_program,
                                                system_hashed_ansi_string_create("view_matrix"),
                                               &view_matrix_uniform_descriptor) );
    ASSERT_TRUE(ogl_program_get_uniform_by_name(test_program,
                                                system_hashed_ansi_string_create("projection_matrix"),
                                               &projection_matrix_uniform_descriptor) );

    triangle_test_projection_matrix_location = projection_matrix_uniform_descriptor->location;
    triangle_test_view_matrix_location       = view_matrix_uniform_descriptor->location;

    ASSERT_NE(triangle_test_projection_matrix_location,
              -1);
    ASSERT_NE(triangle_test_view_matrix_location,
              -1);

    /* Retrieve attribute location */
    const ogl_program_attribute_descriptor* position_attribute_descriptor = NULL;

    ASSERT_TRUE(ogl_program_get_attribute_by_name(test_program,
                                                  system_hashed_ansi_string_create("position"),
                                                 &position_attribute_descriptor) );

    triangle_test_position_location = position_attribute_descriptor->location;

    ASSERT_NE(triangle_test_position_location,
              -1);

    /* Create a projection matrix */
    triangle_test_projection_matrix = system_matrix4x4_create_perspective_projection_matrix(53.0f,           /* fov_y */
                                                                                320.0f / 240.0f, /* ar */
                                                                                0.05f,           /* z_near */
                                                                                25);             /* z_far */

    ASSERT_TRUE(triangle_test_projection_matrix != NULL);

    /* Create a view matrix */
    triangle_test_view_matrix = system_matrix4x4_create();

    system_matrix4x4_set_to_identity(triangle_test_view_matrix);

    /* Let's render a couple of frames. */
    ASSERT_TRUE(ogl_rendering_handler_play(rendering_handler,
                                           0) );

#ifdef _WIN32
    ::Sleep(1000);
#else
    sleep(1);
#endif

    /* Stop playing so that we can release */
    ASSERT_TRUE(ogl_rendering_handler_stop(rendering_handler) );

    /* Release */
    ogl_program_release     (test_program);
    ogl_shader_release      (test_fragment_shader);
    ogl_shader_release      (test_vertex_shader);
    system_matrix4x4_release(triangle_test_projection_matrix);
    system_matrix4x4_release(triangle_test_view_matrix);

    /* Destroy the window in a blunt way */
    ASSERT_TRUE(system_window_close(window_handle) );

#ifdef _WIN32
    ASSERT_EQ  (::IsWindow(window_sys_handle),
                FALSE);
#endif
}

<|endoftext|>


<commit_before>/*
 * This file is part of TelepathyQt4Yell
 *
 * Copyright © 2009-2011 Collabora Ltd. <http://www.collabora.co.uk/>
 * Copyright © 2009 Nokia Corporation
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <TelepathyQt4Yell/Farsight/Channel>

#include <TelepathyQt4/Channel>
#include <TelepathyQt4/Connection>
#include <TelepathyQt4Yell/CallChannel>
#include <TelepathyQt4Yell/Farsight/global.h>

#include <telepathy-glib/channel.h>
#include <telepathy-glib/connection.h>
#include <telepathy-glib/dbus.h>

namespace Tpy
{

FarsightChannel::FarsightChannel() :
    mTfChannel(0)
{
}

FarsightChannel::~FarsightChannel()
{
}

void FarsightChannel::createFarsightChannel(const CallChannelPtr &channel)
{
    if (!channel->handlerStreamingRequired()) {
        qWarning() << "Handler streaming not required";
        Q_EMIT farsightChannelCreated(true);
        return;
    }

    TpDBusDaemon *dbus = tp_dbus_daemon_dup(0);
    if (!dbus) {
        qWarning() << "Unable to connect to D-Bus";
        Q_EMIT farsightChannelCreated(true);
        return;
    }

    Tp::ConnectionPtr connection = channel->connection();
    TpConnection *gconnection = tp_connection_new(dbus,
            connection->busName().toAscii(),
            connection->objectPath().toAscii(),
            0);
    g_object_unref(dbus);
    dbus = 0;
    if (!gconnection) {
        qWarning() << "Unable to construct TpConnection";
        Q_EMIT farsightChannelCreated(true);
        return;
    }

    TpChannel *gchannel = tp_channel_new(gconnection,
            channel->objectPath().toAscii(),
            TP_QT4_YELL_IFACE_CHANNEL_TYPE_CALL.latin1(),
            (TpHandleType) channel->targetHandleType(),
            channel->targetHandle(),
            0);
    g_object_unref(gconnection);
    gconnection = 0;

    if (!gchannel) {
        qWarning() << "Unable to construct TpChannel";
        Q_EMIT farsightChannelCreated(true);
        return;
    }

    tf_channel_new_async(gchannel, FarsightChannel::on_tf_channel_new_finish, this);
}

void FarsightChannel::on_tf_channel_new_finish (GObject *source_object, GAsyncResult *res, gpointer user_data)
{
    qDebug() << "FarsightChannel::on_tf_channel_new_finish: ";
    qDebug() << "    source_object=" << source_object;
    qDebug() << "    result=" << res;

    // TfChannel *ret =
    //g_object_unref(gchannel);
    //gchannel = 0;
}

TfChannel *FarsightChannel::farsightChannel()
{
    return mTfChannel;
}

} // Tpy
<commit_msg>The moc files need to be included with cmake<commit_after>/*
 * This file is part of TelepathyQt4Yell
 *
 * Copyright © 2009-2011 Collabora Ltd. <http://www.collabora.co.uk/>
 * Copyright © 2009 Nokia Corporation
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <TelepathyQt4Yell/Farsight/Channel>

#include <TelepathyQt4/Channel>
#include <TelepathyQt4/Connection>
#include <TelepathyQt4Yell/CallChannel>
#include <TelepathyQt4Yell/Farsight/global.h>

#include <telepathy-glib/channel.h>
#include <telepathy-glib/connection.h>
#include <telepathy-glib/dbus.h>

#include "TelepathyQt4Yell/Farsight/_gen/channel.moc.hpp"

namespace Tpy
{

FarsightChannel::FarsightChannel() :
    mTfChannel(0)
{
}

FarsightChannel::~FarsightChannel()
{
}

void FarsightChannel::createFarsightChannel(const CallChannelPtr &channel)
{
    if (!channel->handlerStreamingRequired()) {
        qWarning() << "Handler streaming not required";
        Q_EMIT farsightChannelCreated(true);
        return;
    }

    TpDBusDaemon *dbus = tp_dbus_daemon_dup(0);
    if (!dbus) {
        qWarning() << "Unable to connect to D-Bus";
        Q_EMIT farsightChannelCreated(true);
        return;
    }

    Tp::ConnectionPtr connection = channel->connection();
    TpConnection *gconnection = tp_connection_new(dbus,
            connection->busName().toAscii(),
            connection->objectPath().toAscii(),
            0);
    g_object_unref(dbus);
    dbus = 0;
    if (!gconnection) {
        qWarning() << "Unable to construct TpConnection";
        Q_EMIT farsightChannelCreated(true);
        return;
    }

    TpChannel *gchannel = tp_channel_new(gconnection,
            channel->objectPath().toAscii(),
            TP_QT4_YELL_IFACE_CHANNEL_TYPE_CALL.latin1(),
            (TpHandleType) channel->targetHandleType(),
            channel->targetHandle(),
            0);
    g_object_unref(gconnection);
    gconnection = 0;

    if (!gchannel) {
        qWarning() << "Unable to construct TpChannel";
        Q_EMIT farsightChannelCreated(true);
        return;
    }

    tf_channel_new_async(gchannel, FarsightChannel::on_tf_channel_new_finish, this);
}

void FarsightChannel::on_tf_channel_new_finish (GObject *source_object, GAsyncResult *res, gpointer user_data)
{
    qDebug() << "FarsightChannel::on_tf_channel_new_finish: ";
    qDebug() << "    source_object=" << source_object;
    qDebug() << "    result=" << res;

    // TfChannel *ret =
    //g_object_unref(gchannel);
    //gchannel = 0;
}

TfChannel *FarsightChannel::farsightChannel()
{
    return mTfChannel;
}

} // Tpy
<|endoftext|>