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

// nsltest.cpp : Defines the entry point for the console application.
//
#include <string>
#include <iostream>
#include <fstream>
#include <stdlib.h> // for rand()

#include <sstream>

#include "nslobject.h"
#include "nslobjectfactory.h"

#include "cparser.h"
#include "physics.h"
#include "container.h"

#include <stdio.h>
#include <math.h>

using namespace std;

int testparser();
void testnslobject ( void );
void testfactory(void);
void testnslparsing ( void );
void testvectors(void);

void testray(void);

class newobject : public nslobject {
public:
	newobject() { objecttype = "newobject"; return; }
	class Factory : public nslobjectfactory {
		nslobject *create() { return new newobject; }
	};
};

int main (int argc, string argv)
{
	//testparser();
	//return 0;

try {

	/*ifstream infile("d:\\testparse.nsl");
	cparser parser(&infile);
	anobject.parse(parser);
	*/
	testnslobject();

	testfactory();

	testvectors();

//	testnslparsing();

	testray();

	cout << endl << "All tests completed successfully." << endl;

} catch (runtime_error runt) {
	cout << endl << "\aA runtime error has occured ";
	if (runt.what())
		cout << ": " << runt.what();
	cout << endl << "Terminating program." << endl;
} catch (...) {
	cout << "\aAn unrecoverable, unidentified exception occured - terminating program." << endl;
}

	// Hold at the end of execution until they hit enter
	getchar();

	return 0;
}

int testparser()
{
	ifstream in("./scripts/parsenum.txt");
	cparser parser(&in);

	if (in)
		cout << "File opened successfully" << endl;
	else
		cout << "Error reading file." << endl;

	cout << "Status: " << in.bad() << in.eof() << in.fail() << in.good() << endl;

	//string stest;
	//parser >> stest;
	//cout << endl << "argh";
	do {
		cout << parser.gettoken() << endl;
	} while (!parser.eof());

	//cout << EOF << endl;

	cout << endl << "Press enter to continue....";
	getchar();

	return 0;
}

void testnslobject ( void )
{
	cout << endl << "===== Testing nslobject class =====" << endl;

	nslobject anobject, *secondobject;
	string a;
	secondobject = new nslobject;

	// Test we can set and get properties
	cout << "Testing object property setting and retrieval: ";
	anobject.set("something", "Success");
	a = anobject.get("something");
	if (a == "Success")
		cout << a << endl;
	else
		throw runtime_error("Faliure manipulating object properties");

	// Set up the names
	anobject.set("name", "baseobject");
	secondobject->set("name", "secondobject");

	cout << "Testing adding subobjects:" << endl;
	anobject.add(*secondobject);
	anobject.tree();

}

void testfactory ( void )
{
	cout << endl << "===== Testing class factory =====" << endl;
		int otypecount;
	// Test adding some objects to the factory
	otypecount = nslobjectfactory::count();
	cout << "Testing adding object to class factory: ";
	nslobjectfactory::add("newobject", new newobject::Factory);

	if (nslobjectfactory::count() != otypecount + 1)
		throw runtime_error("Failed to add test object to object factory");
	else
		cout << "Success." << endl;

	nslobjectfactory::add("container", new newobject::Factory);
	nslobjectfactory::add("particle", new newobject::Factory);
	nslobjectfactory::add("volume_cylinder", new newobject::Factory);
	nslobjectfactory::add("bfield", new newobject::Factory);

	// Testing adding a duplicate
	cout << "Testing that adding duplicate objects doesn't: ";
	otypecount = nslobjectfactory::count();
	nslobjectfactory::add("newobject", new newobject::Factory);
	if (nslobjectfactory::count() != otypecount)
		throw runtime_error("Adding duplicate object somehow succeeded");
	else
		cout << "Success." << endl;

	// Print a list of particle types
	nslobjectfactory::list();

	// Test removing of a specially added object
	cout << "Testing removing added object: ";
	nslobjectfactory::add("testobject", new newobject::Factory);
	otypecount = nslobjectfactory::count();
	nslobjectfactory::remove("testobject");
	if (nslobjectfactory::count() == otypecount - 1)
		cout << "Success." << endl;
	else
		throw runtime_error("Test object not successfully removed.");

	// Now test removing an item that never existed
	cout << "Testing removing unadded object: ";
	nslobjectfactory::remove("unadded object");
	if (nslobjectfactory::count() != otypecount - 1)
		throw runtime_error("Removing an unadded object from the factory caused a list change");
	else
		cout << "Success." << endl;

}

void testnslparsing ( void )
{
	cout << endl << "===== Testing parsing data file =====" << endl;

	// Set up the object
	nslobject anobject;
	anobject.set("name", "Root Object");

	anobject.parse("./scripts/testparse.nsl");

	cout << "Testing finding an object by name: ";
	// find an object and rename it
	nslobject *retval = anobject.findbyname("subsub1");
	if (retval) {
		retval->set("name", "subsub1 renamed");
		cout << "Success." << endl;
	} else
		throw runtime_error("Cannot find object to rename");

	// Search for a "newobject" from this found object
	cout << "Testing finding by type from this object: ";
	retval = retval->findbytype("newobject");
	if (retval) {
		retval->set("name", "Found by type from subsub1");
		cout << "Success." << endl;
	} else
		throw runtime_error("Cannot find object by type");

	cout << "Parsed Tree: " << endl;
	anobject.tree();

	cout << endl << "Testing regeneration: " << endl;
	anobject.regenerate(cout);
}

void testvectors ( void )
{
	cout << endl << "===== Testing vectors =====" << endl;

	vector3 a(1.0, 1.0, 1.0), b(1.0, 1.0, 1.0), c;

	cout << "Streaming Vector: " << a << endl;

	cout << "Adding: \t";
	if (a+b == vector3(2.0, 2.0, 2.0))
		cout << "Success." << endl;
	else
		throw runtime_error("Adding vectors produced incorrect answer");

	cout << "Subtracting: \t";
	if (a-b == vector3(0, 0, 0))
		cout << "Success." << endl;
	else
		throw runtime_error("Subtracting vectors produced incorrect answer");

	cout << "Scaling: \t";
	if ( vector3(2, 2, 2)*3.5 == vector3(7, 7, 7))
		cout << "Success." << endl;
	else
		throw runtime_error("Scaling Vector produced incorrect answer");

	cout << "Scaling to:\t";
	a.scaleto(1.0);
	if (a.mod() == 1.0)
		cout << "Success.";
	else
		throw runtime_error("Scaling to produced incorrect results");
	//cout << a << " |a| = " << a.mod() << endl;

	/*cout << "Assignment: ";
	long double out = a.mod();
	if ((out - 1.0)*(out - 1.0) < 1e-10)
		cout << "Success." << endl;
	else
		throw runtime_error("Assignment to long double went wrong");
*/
//	c.print();
	cout << endl;

}

void testray(void)
{
	cout << endl << "======= Testing ray intersection tests =======" << endl;

	container box;
	volume_cylinder cylind, cylin2, cylin3;
	// Create a cylinder object and attach it to the box
	cylind.set("radius", "1"); cylind.set("height", "2"); cylind.set("type", "negative");
	cylind.set("name", "Cylinder"); cylind.set("z", "-1"); box.set("name", "Box");

	cylin2.set("radius", "1"); cylin2.set("height", "2"); cylin2.set("type", "positive");
	cylin2.set("name", "cylin2er"); cylin2.set("z", "-1.7"); cylin2.set("x", "1.5");

	cylin3.set("radius", "0.5"); cylin3.set("height", "0.5"); cylin3.set("type", "negative");
	cylin3.set("name", "Cylinder3"); cylin3.set("z", "-1.5");

	box.add(cylind);
	box.add(cylin2);
	//box.add(cylin3);

	box.prepare();

	// Print out the tree
	box.tree();

	ofstream out("./rayout.txt");

	// Make a couple of vectors for the ray and direction
	vector3 raypos(-0.1,0.0,0);
	vector3 rayvec(1,0.6,1);
	const long double velocity = 1000.0;

	rayvec.scaleto(velocity);
	//rayvec.scaleto(1000.0);

	//raypos = cylind.getposition("center");

	out << raypos << endl;

	intercept icept = box.cast(raypos, rayvec);

	cout << "First collides at: " << icept.time << "; " << raypos + rayvec*icept.time;

	for (long i = 0; i < 10000; i++)//490
	{
		if (i == 5)
			cout << "it" << endl;

		// Build a new ray directions
		raypos += rayvec * icept.time;

//		raypos += rayvec * (-adjust);
		out << raypos << endl;

		//Rout = Rin - 2N(N.Rin)
		icept.normal.scaleto(1.0);

		//long double t2 = (icept.normal * rayvec);
		//vector3 tmp = ;

		// Calculate the reflection
		rayvec = rayvec - ((icept.normal * 2.)*(icept.normal * rayvec));
		rayvec.x = rand()-(RAND_MAX/2);
		rayvec.y = rand()-(RAND_MAX/2);
		rayvec.z = rand()-(RAND_MAX/2);
		rayvec.scaleto(velocity);

		if (dot(rayvec, icept.normal) < 0)
			rayvec *= -1.0;

		//rayvec.scaleto(1.0);

		icept = box.cast(raypos, rayvec);
	}
	raypos += rayvec * icept.time;
	out << raypos << endl;
	cout << "End rayvec size" << rayvec.mod() << endl;

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

// nsltest.cpp : Defines the entry point for the console application.
//
#include <string>
#include <iostream>
#include <fstream>
#include <stdlib.h> // for rand()

#include <sstream>

#include "nslobject.h"
#include "nslobjectfactory.h"

#include "cparser.h"
#include "physics.h"
#include "container.h"

#include <stdio.h>
#include <math.h>

using namespace std;

int testparser();
void testnslobject ( void );
void testfactory(void);
void testnslparsing ( void );
void testvectors(void);

void testray(void);

class newobject : public nslobject {
public:
	newobject() { objecttype = "newobject"; return; }
	class Factory : public nslobjectfactory {
		nslobject *create() { return new newobject; }
	};
};

int main (int argc, char ** argv)
{
	//testparser();
	//return 0;

try {

	/*ifstream infile("d:\\testparse.nsl");
	cparser parser(&infile);
	anobject.parse(parser);
	*/
	testnslobject();

	testfactory();

	testvectors();

//	testnslparsing();

	testray();

	cout << endl << "All tests completed successfully." << endl;

} catch (runtime_error runt) {
	cout << endl << "\aA runtime error has occured ";
	if (runt.what())
		cout << ": " << runt.what();
	cout << endl << "Terminating program." << endl;
} catch (...) {
	cout << "\aAn unrecoverable, unidentified exception occured - terminating program." << endl;
}

	// Hold at the end of execution until they hit enter
	getchar();

	return 0;
}

int testparser()
{
	ifstream in("./scripts/parsenum.txt");
	cparser parser(&in);

	if (in)
		cout << "File opened successfully" << endl;
	else
		cout << "Error reading file." << endl;

	cout << "Status: " << in.bad() << in.eof() << in.fail() << in.good() << endl;

	//string stest;
	//parser >> stest;
	//cout << endl << "argh";
	do {
		cout << parser.gettoken() << endl;
	} while (!parser.eof());

	//cout << EOF << endl;

	cout << endl << "Press enter to continue....";
	getchar();

	return 0;
}

void testnslobject ( void )
{
	cout << endl << "===== Testing nslobject class =====" << endl;

	nslobject anobject, *secondobject;
	string a;
	secondobject = new nslobject;

	// Test we can set and get properties
	cout << "Testing object property setting and retrieval: ";
	anobject.set("something", "Success");
	a = anobject.get("something");
	if (a == "Success")
		cout << a << endl;
	else
		throw runtime_error("Faliure manipulating object properties");

	// Set up the names
	anobject.set("name", "baseobject");
	secondobject->set("name", "secondobject");

	cout << "Testing adding subobjects:" << endl;
	anobject.add(*secondobject);
	anobject.tree();

}

void testfactory ( void )
{
	cout << endl << "===== Testing class factory =====" << endl;
		int otypecount;
	// Test adding some objects to the factory
	otypecount = nslobjectfactory::count();
	cout << "Testing adding object to class factory: ";
	nslobjectfactory::add("newobject", new newobject::Factory);

	if (nslobjectfactory::count() != otypecount + 1)
		throw runtime_error("Failed to add test object to object factory");
	else
		cout << "Success." << endl;

	nslobjectfactory::add("container", new newobject::Factory);
	nslobjectfactory::add("particle", new newobject::Factory);
	nslobjectfactory::add("volume_cylinder", new newobject::Factory);
	nslobjectfactory::add("bfield", new newobject::Factory);

	// Testing adding a duplicate
	cout << "Testing that adding duplicate objects doesn't: ";
	otypecount = nslobjectfactory::count();
	nslobjectfactory::add("newobject", new newobject::Factory);
	if (nslobjectfactory::count() != otypecount)
		throw runtime_error("Adding duplicate object somehow succeeded");
	else
		cout << "Success." << endl;

	// Print a list of particle types
	nslobjectfactory::list();

	// Test removing of a specially added object
	cout << "Testing removing added object: ";
	nslobjectfactory::add("testobject", new newobject::Factory);
	otypecount = nslobjectfactory::count();
	nslobjectfactory::remove("testobject");
	if (nslobjectfactory::count() == otypecount - 1)
		cout << "Success." << endl;
	else
		throw runtime_error("Test object not successfully removed.");

	// Now test removing an item that never existed
	cout << "Testing removing unadded object: ";
	nslobjectfactory::remove("unadded object");
	if (nslobjectfactory::count() != otypecount - 1)
		throw runtime_error("Removing an unadded object from the factory caused a list change");
	else
		cout << "Success." << endl;

}

void testnslparsing ( void )
{
	cout << endl << "===== Testing parsing data file =====" << endl;

	// Set up the object
	nslobject anobject;
	anobject.set("name", "Root Object");

	anobject.parse("./scripts/testparse.nsl");

	cout << "Testing finding an object by name: ";
	// find an object and rename it
	nslobject *retval = anobject.findbyname("subsub1");
	if (retval) {
		retval->set("name", "subsub1 renamed");
		cout << "Success." << endl;
	} else
		throw runtime_error("Cannot find object to rename");

	// Search for a "newobject" from this found object
	cout << "Testing finding by type from this object: ";
	retval = retval->findbytype("newobject");
	if (retval) {
		retval->set("name", "Found by type from subsub1");
		cout << "Success." << endl;
	} else
		throw runtime_error("Cannot find object by type");

	cout << "Parsed Tree: " << endl;
	anobject.tree();

	cout << endl << "Testing regeneration: " << endl;
	anobject.regenerate(cout);
}

void testvectors ( void )
{
	cout << endl << "===== Testing vectors =====" << endl;

	vector3 a(1.0, 1.0, 1.0), b(1.0, 1.0, 1.0), c;

	cout << "Streaming Vector: " << a << endl;

	cout << "Adding: \t";
	if (a+b == vector3(2.0, 2.0, 2.0))
		cout << "Success." << endl;
	else
		throw runtime_error("Adding vectors produced incorrect answer");

	cout << "Subtracting: \t";
	if (a-b == vector3(0, 0, 0))
		cout << "Success." << endl;
	else
		throw runtime_error("Subtracting vectors produced incorrect answer");

	cout << "Scaling: \t";
	if ( vector3(2, 2, 2)*3.5 == vector3(7, 7, 7))
		cout << "Success." << endl;
	else
		throw runtime_error("Scaling Vector produced incorrect answer");

	cout << "Scaling to:\t";
	a.scaleto(1.0);
	if (a.mod() == 1.0)
		cout << "Success.";
	else
		throw runtime_error("Scaling to produced incorrect results");
	//cout << a << " |a| = " << a.mod() << endl;

	/*cout << "Assignment: ";
	long double out = a.mod();
	if ((out - 1.0)*(out - 1.0) < 1e-10)
		cout << "Success." << endl;
	else
		throw runtime_error("Assignment to long double went wrong");
*/
//	c.print();
	cout << endl;

}

void testray(void)
{
	cout << endl << "======= Testing ray intersection tests =======" << endl;

	container box;
	volume_cylinder cylind, cylin2, cylin3;
	// Create a cylinder object and attach it to the box
	cylind.set("radius", "1"); cylind.set("height", "2"); cylind.set("type", "negative");
	cylind.set("name", "Cylinder"); cylind.set("z", "-1"); box.set("name", "Box");

	cylin2.set("radius", "1"); cylin2.set("height", "2"); cylin2.set("type", "positive");
	cylin2.set("name", "cylin2er"); cylin2.set("z", "-1.7"); cylin2.set("x", "1.5");

	cylin3.set("radius", "0.5"); cylin3.set("height", "0.5"); cylin3.set("type", "negative");
	cylin3.set("name", "Cylinder3"); cylin3.set("z", "-1.5");

	box.add(cylind);
	box.add(cylin2);
	//box.add(cylin3);

	box.prepare();

	// Print out the tree
	box.tree();

	ofstream out("./rayout.txt");

	// Make a couple of vectors for the ray and direction
	vector3 raypos(-0.1,0.0,0);
	vector3 rayvec(1,0.6,1);
	const long double velocity = 1000.0;

	rayvec.scaleto(velocity);
	//rayvec.scaleto(1000.0);

	//raypos = cylind.getposition("center");

	out << raypos << endl;

	intercept icept = box.cast(raypos, rayvec);

	cout << "First collides at: " << icept.time << "; " << raypos + rayvec*icept.time;

	for (long i = 0; i < 10000; i++)//490
	{
		if (i == 5)
			cout << "it" << endl;

		// Build a new ray directions
		raypos += rayvec * icept.time;

//		raypos += rayvec * (-adjust);
		out << raypos << endl;

		//Rout = Rin - 2N(N.Rin)
		icept.normal.scaleto(1.0);

		//long double t2 = (icept.normal * rayvec);
		//vector3 tmp = ;

		// Calculate the reflection
		rayvec = rayvec - ((icept.normal * 2.)*(icept.normal * rayvec));
		rayvec.x = rand()-(RAND_MAX/2);
		rayvec.y = rand()-(RAND_MAX/2);
		rayvec.z = rand()-(RAND_MAX/2);
		rayvec.scaleto(velocity);

		if (dot(rayvec, icept.normal) < 0)
			rayvec *= -1.0;

		//rayvec.scaleto(1.0);

		icept = box.cast(raypos, rayvec);
	}
	raypos += rayvec * icept.time;
	out << raypos << endl;
	cout << "End rayvec size" << rayvec.mod() << endl;

}
<|endoftext|>


<commit_before>//===============================================================================
// @ IvMainOGL.cpp
//
// Start up and main event loop for OpenGL
// ------------------------------------------------------------------------------
// Copyright (C) 2008-2015 by James M. Van Verth and Lars M. Bishop.
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
//===============================================================================

//-------------------------------------------------------------------------------
//-- Dependencies ---------------------------------------------------------------
//-------------------------------------------------------------------------------

#include <stdlib.h>

#if !defined(__APPLE__) || !defined(__MACH__)
#include <GL/glew.h>
#endif
#include <GLFW/glfw3.h>

#include <IvGame.h>
#include <IvDebugger.h>
#include <IvEventHandler.h>
#include <OGL/IvRendererOGL.h>

static void visibilityCallback(GLFWwindow* window, int vis);
static void reshapeCallback(GLFWwindow* window, int w, int h);

static void keyboardCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
static void mouseCallback(GLFWwindow* window, int button, int action, int mods);

static void error_callback(int error, const char* description)
{
    ERROR_OUT(description << std::endl);
}

static GLFWwindow* window = nullptr;

//-------------------------------------------------------------------------------
// @ main()
//-------------------------------------------------------------------------------
// Where it all begins
//-------------------------------------------------------------------------------
int main(int argc, char *argv[])
{
    gDebugger.DumpToFile( "Debug.txt" );
    glfwSetErrorCallback(error_callback);

    if (!glfwInit())
    {
        ERROR_OUT("Error: could not initialize GLFW" << std::endl);
    }

    // set up for core profile
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_SRGB_CAPABLE, GL_TRUE);

    // set up display
    bool fullscreen = false;
    if (fullscreen)
    {
        window = glfwCreateWindow(640, 480, "Example", glfwGetPrimaryMonitor(), nullptr);
    }
    else
    {
        window = glfwCreateWindow(640, 480, "Example", nullptr, nullptr);
    }
    if (nullptr == window)
    {
        ERROR_OUT("Error: could not create window" << std::endl);
        glfwTerminate();
        return 1;
    }
    glfwMakeContextCurrent(window);

#if !defined(__APPLE__) || !defined(__MACH__)
    glewExperimental = GL_TRUE;
    GLenum err = glewInit();
    if ( GLEW_OK != err )
    {
        ERROR_OUT("Error: " << glewGetErrorString(err) << std::endl);
        glfwDestroyWindow(window);
        glfwTerminate();
        return 1;
    }

    // check for version compatibility
    if ( !GLEW_VERSION_3_2 )
    {
        ERROR_OUT("Error: OpenGL version 3.2 is not supported." << std::endl);
        glfwDestroyWindow(window);
        glfwTerminate();
        return 1;
    }

    DEBUG_OUT("Using GLEW " << glewGetString(GLEW_VERSION));
#endif

    // set up game
    if (!IvGame::Create() || !IvGame::mGame->PreRendererInitialize( argc, argv ))
    {
        IvGame::Destroy();
        glfwDestroyWindow(window);
        glfwTerminate();
        return 1;
    }

    // set up renderer

    int width;
    int height;
    glfwGetFramebufferSize(window, &width, &height);

    if (!IvRendererOGL::Create() || !IvRendererOGL::mRenderer->Initialize( width, height ))
    {
        IvRenderer::Destroy();
        IvGame::Destroy();
        glfwDestroyWindow(window);
        glfwTerminate();
        return 1;
    }

    // Set the background dark blue
    IvRenderer::mRenderer->SetClearColor( 0.0f, 0.0f, 0.10f, 1.0f );

    // Do post-renderer creation initialization
    if (!IvGame::mGame->PostRendererInitialize())
    {
        IvRenderer::Destroy();
        IvGame::Destroy();
        glfwDestroyWindow(window);
        glfwTerminate();
        return 1;
    }

    // set up display callbacks
    glfwSetWindowFocusCallback(window, visibilityCallback);
    glfwSetWindowSizeCallback(window, reshapeCallback);

    // set up event handlers
    glfwSetKeyCallback(window, keyboardCallback);
    glfwSetMouseButtonCallback(window, mouseCallback);

    // run it!
    while (!glfwWindowShouldClose(window))
    {
        // game does everything it needs to do
        IvGame::mGame->Update();

        // clear the back buffer
        IvRenderer::mRenderer->ClearBuffers(kColorDepthClear);

        // render the world
        if ( IvRenderer::mRenderer->IsActive() )
        {
            IvGame::mGame->Display();
        }

        // swap graphics buffers
        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    IvGame::Destroy();

    glfwDestroyWindow(window);
    glfwTerminate();

    return 0;

}   // End of main()

static void
visibilityCallback(GLFWwindow* window, int vis)
{
    IvRenderer::mRenderer->Activate( vis == GL_TRUE );
}

static void
reshapeCallback(GLFWwindow* window, int w, int h)
{
    IvRenderer::mRenderer->Resize( w, h );
}

static void
keyboardCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    // Handle Extended ASCII only
    if (key > 255)
    {
        return;
    }

    if (action == GLFW_PRESS || action == GLFW_REPEAT)
    {
        IvGame::mGame->mEventHandler->OnKeyDown( key );   // Handle key down event
    }
    else
    {
        IvGame::mGame->mEventHandler->OnKeyUp( key ); // Handle key up event
    }

}

static void
mouseCallback(GLFWwindow* window, int button, int action, int mods)
{
    if ( button == GLFW_MOUSE_BUTTON_LEFT )
    {
        if ( action == GLFW_PRESS )
        {
            double x, y;
            glfwGetCursorPos(window, &x, &y);
            IvGame::mGame->mEventHandler->OnMouseDown( (int)x, (int)y );
        }
        else
        {
            IvGame::mGame->mEventHandler->OnMouseUp();
        }
    }
}

//-------------------------------------------------------------------------------
// @ GetTime()
//-------------------------------------------------------------------------------
// Get current system time in milliseconds
//-------------------------------------------------------------------------------
unsigned int
GetTime()
{
    return static_cast<unsigned int>(glfwGetTime()*1000.0f);
}

//-------------------------------------------------------------------------------
// @ SetWindowTitle()
//-------------------------------------------------------------------------------
// Set the current window title to the string value
//-------------------------------------------------------------------------------
void
SetWindowTitle( const char* title )
{
    glfwSetWindowTitle( window, title );
}

<commit_msg>Fix picking on Mac Retina displays<commit_after>//===============================================================================
// @ IvMainOGL.cpp
//
// Start up and main event loop for OpenGL
// ------------------------------------------------------------------------------
// Copyright (C) 2008-2015 by James M. Van Verth and Lars M. Bishop.
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
//===============================================================================

//-------------------------------------------------------------------------------
//-- Dependencies ---------------------------------------------------------------
//-------------------------------------------------------------------------------

#include <stdlib.h>

#if !defined(__APPLE__) || !defined(__MACH__)
#include <GL/glew.h>
#endif
#include <GLFW/glfw3.h>

#include <IvGame.h>
#include <IvDebugger.h>
#include <IvEventHandler.h>
#include <OGL/IvRendererOGL.h>

static void visibilityCallback(GLFWwindow* window, int vis);
static void reshapeCallback(GLFWwindow* window, int w, int h);

static void keyboardCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
static void mouseCallback(GLFWwindow* window, int button, int action, int mods);

static void error_callback(int error, const char* description)
{
    ERROR_OUT(description << std::endl);
}

static GLFWwindow* window = nullptr;

//-------------------------------------------------------------------------------
// @ main()
//-------------------------------------------------------------------------------
// Where it all begins
//-------------------------------------------------------------------------------
int main(int argc, char *argv[])
{
    gDebugger.DumpToFile( "Debug.txt" );
    glfwSetErrorCallback(error_callback);

    if (!glfwInit())
    {
        ERROR_OUT("Error: could not initialize GLFW" << std::endl);
    }

    // set up for core profile
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_SRGB_CAPABLE, GL_TRUE);

    // set up display
    bool fullscreen = false;
    if (fullscreen)
    {
        window = glfwCreateWindow(640, 480, "Example", glfwGetPrimaryMonitor(), nullptr);
    }
    else
    {
        window = glfwCreateWindow(640, 480, "Example", nullptr, nullptr);
    }
    if (nullptr == window)
    {
        ERROR_OUT("Error: could not create window" << std::endl);
        glfwTerminate();
        return 1;
    }
    glfwMakeContextCurrent(window);

#if !defined(__APPLE__) || !defined(__MACH__)
    glewExperimental = GL_TRUE;
    GLenum err = glewInit();
    if ( GLEW_OK != err )
    {
        ERROR_OUT("Error: " << glewGetErrorString(err) << std::endl);
        glfwDestroyWindow(window);
        glfwTerminate();
        return 1;
    }

    // check for version compatibility
    if ( !GLEW_VERSION_3_2 )
    {
        ERROR_OUT("Error: OpenGL version 3.2 is not supported." << std::endl);
        glfwDestroyWindow(window);
        glfwTerminate();
        return 1;
    }

    DEBUG_OUT("Using GLEW " << glewGetString(GLEW_VERSION));
#endif

    // set up game
    if (!IvGame::Create() || !IvGame::mGame->PreRendererInitialize( argc, argv ))
    {
        IvGame::Destroy();
        glfwDestroyWindow(window);
        glfwTerminate();
        return 1;
    }

    // set up renderer

    int width;
    int height;
    glfwGetFramebufferSize(window, &width, &height);

    if (!IvRendererOGL::Create() || !IvRendererOGL::mRenderer->Initialize( width, height ))
    {
        IvRenderer::Destroy();
        IvGame::Destroy();
        glfwDestroyWindow(window);
        glfwTerminate();
        return 1;
    }

    // Set the background dark blue
    IvRenderer::mRenderer->SetClearColor( 0.0f, 0.0f, 0.10f, 1.0f );

    // Do post-renderer creation initialization
    if (!IvGame::mGame->PostRendererInitialize())
    {
        IvRenderer::Destroy();
        IvGame::Destroy();
        glfwDestroyWindow(window);
        glfwTerminate();
        return 1;
    }

    // set up display callbacks
    glfwSetWindowFocusCallback(window, visibilityCallback);
    glfwSetWindowSizeCallback(window, reshapeCallback);

    // set up event handlers
    glfwSetKeyCallback(window, keyboardCallback);
    glfwSetMouseButtonCallback(window, mouseCallback);

    // run it!
    while (!glfwWindowShouldClose(window))
    {
        // game does everything it needs to do
        IvGame::mGame->Update();

        // clear the back buffer
        IvRenderer::mRenderer->ClearBuffers(kColorDepthClear);

        // render the world
        if ( IvRenderer::mRenderer->IsActive() )
        {
            IvGame::mGame->Display();
        }

        // swap graphics buffers
        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    IvGame::Destroy();

    glfwDestroyWindow(window);
    glfwTerminate();

    return 0;

}   // End of main()

static void
visibilityCallback(GLFWwindow* window, int vis)
{
    IvRenderer::mRenderer->Activate( vis == GL_TRUE );
}

static void
reshapeCallback(GLFWwindow* window, int w, int h)
{
    int width;
    int height;
    glfwGetFramebufferSize(window, &width, &height);
    IvRenderer::mRenderer->Resize( width, height );
}

static void
keyboardCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    // Handle Extended ASCII only
    if (key > 255)
    {
        return;
    }

    if (action == GLFW_PRESS || action == GLFW_REPEAT)
    {
        IvGame::mGame->mEventHandler->OnKeyDown( key );   // Handle key down event
    }
    else
    {
        IvGame::mGame->mEventHandler->OnKeyUp( key ); // Handle key up event
    }

}

static void
mouseCallback(GLFWwindow* window, int button, int action, int mods)
{
    if ( button == GLFW_MOUSE_BUTTON_LEFT )
    {
        if ( action == GLFW_PRESS )
        {
            double x, y;
            glfwGetCursorPos(window, &x, &y);

            int width;
            int height;
            glfwGetFramebufferSize(window, &width, &height);

            int windowWidth;
            int windowHeight;
            glfwGetWindowSize(window, &windowWidth, &windowHeight);

            double scaleX = width/(float)windowWidth;
            double scaleY = height/(float)windowHeight;

            IvGame::mGame->mEventHandler->OnMouseDown( (int)scaleX*x, (int)scaleY*y );
        }
        else
        {
            IvGame::mGame->mEventHandler->OnMouseUp();
        }
    }
}

//-------------------------------------------------------------------------------
// @ GetTime()
//-------------------------------------------------------------------------------
// Get current system time in milliseconds
//-------------------------------------------------------------------------------
unsigned int
GetTime()
{
    return static_cast<unsigned int>(glfwGetTime()*1000.0f);
}

//-------------------------------------------------------------------------------
// @ SetWindowTitle()
//-------------------------------------------------------------------------------
// Set the current window title to the string value
//-------------------------------------------------------------------------------
void
SetWindowTitle( const char* title )
{
    glfwSetWindowTitle( window, title );
}

<|endoftext|>


<commit_before>
#include "NewExprHandler.h"

namespace
{
  /**
   * True if placement new (we don't care about that)
   */
  bool isPlacementNew(const clang::CXXNewExpr* expr)
  {
    // Regular new expressions aren't placement new
    if (expr->getNumPlacementArgs() == 0)
      return false;
    return true;
  }

}

namespace typegrind
{

  NewExprHandler::NewExprHandler(clang::Rewriter*& rewriter, SpecializationHandler& specializationHandler)
          : BaseExprHandler(rewriter, specializationHandler)
  {
  }

  void NewExprHandler::run(const clang::ast_matchers::MatchFinder::MatchResult &result)
  {
    const clang::CXXNewExpr* newExpr = result.Nodes.getNodeAs<clang::CXXNewExpr>("newStmt");
    if (nullptr == newExpr)
    {
      llvm::errs() << "Internal error: couldn't convert newStmt to newExpr!\n";
      return;
    }

    clang::SourceLocation startLoc = newExpr->getStartLoc();
    clang::SourceLocation endLoc = newExpr->getEndLoc();

    // Add info for every non dependent type
    auto ptr = newExpr->getAllocatedType().getTypePtr();
    if (!ptr->isInstantiationDependentType() && !ptr->hasUnnamedOrLocalType())
    {
      handleSpecializedType(newExpr->getAllocatedType(), startLoc.getRawEncoding());
    }

    if (!processingLocation(startLoc)) {
      return;
    }

    if (isPlacementNew(newExpr)) return;

    MacroAdder newLoggerMacro(
            newExpr->isArray() ? "TYPEGRIND_LOG_NEW_ARRAY" : "TYPEGRIND_LOG_NEW",
            startLoc,
            endLoc,
            mRewriter
    );

    // 2nd and 3rd paramter: name of the type.
    addTypeInformationParameters(newLoggerMacro, newExpr->getAllocatedType(), startLoc.getRawEncoding());

    // 4th parameter: sizeof type
    addSizeOfParameter(newLoggerMacro, newExpr->getAllocatedType());

    // if this is as array, there is an 5th parameter, the array size
    if (newExpr->isArray())
    {
      // TODO: this assumes that the size expression is const, which isn't always true! => extract expression to a variable ?
      newExpr->getArraySize()->printPretty(newLoggerMacro.startBuffer(), nullptr, clang::PrintingPolicy(result.Context->getPrintingPolicy()));
      newLoggerMacro.startBuffer() << ", ";
    }

    // last parameter: the constructor expression
    // parenthesis around it, for multiple template parameters
    newLoggerMacro.startBuffer() << "(";
    newLoggerMacro.endBuffer() << ")";

    newLoggerMacro.commitAroundLocations();
  }
}
<commit_msg>ignoring placement new sooner<commit_after>
#include "NewExprHandler.h"

namespace
{
  /**
   * True if placement new (we don't care about that)
   */
  bool isPlacementNew(const clang::CXXNewExpr* expr)
  {
    // Regular new expressions aren't placement new
    if (expr->getNumPlacementArgs() == 0)
      return false;
    return true;
  }

}

namespace typegrind
{

  NewExprHandler::NewExprHandler(clang::Rewriter*& rewriter, SpecializationHandler& specializationHandler)
          : BaseExprHandler(rewriter, specializationHandler)
  {
  }

  void NewExprHandler::run(const clang::ast_matchers::MatchFinder::MatchResult &result)
  {
    const clang::CXXNewExpr* newExpr = result.Nodes.getNodeAs<clang::CXXNewExpr>("newStmt");
    if (nullptr == newExpr)
    {
      llvm::errs() << "Internal error: couldn't convert newStmt to newExpr!\n";
      return;
    }

    if (isPlacementNew(newExpr)) return;

    clang::SourceLocation startLoc = newExpr->getStartLoc();
    clang::SourceLocation endLoc = newExpr->getEndLoc();

    // Add info for every non dependent type
    auto ptr = newExpr->getAllocatedType().getTypePtr();
    if (!ptr->isInstantiationDependentType() && !ptr->hasUnnamedOrLocalType())
    {
      handleSpecializedType(newExpr->getAllocatedType(), startLoc.getRawEncoding());
    }

    if (!processingLocation(startLoc)) {
      return;
    }

    MacroAdder newLoggerMacro(
            newExpr->isArray() ? "TYPEGRIND_LOG_NEW_ARRAY" : "TYPEGRIND_LOG_NEW",
            startLoc,
            endLoc,
            mRewriter
    );

    // 2nd and 3rd paramter: name of the type.
    addTypeInformationParameters(newLoggerMacro, newExpr->getAllocatedType(), startLoc.getRawEncoding());

    // 4th parameter: sizeof type
    addSizeOfParameter(newLoggerMacro, newExpr->getAllocatedType());

    // if this is as array, there is an 5th parameter, the array size
    if (newExpr->isArray())
    {
      // TODO: this assumes that the size expression is const, which isn't always true! => extract expression to a variable ?
      newExpr->getArraySize()->printPretty(newLoggerMacro.startBuffer(), nullptr, clang::PrintingPolicy(result.Context->getPrintingPolicy()));
      newLoggerMacro.startBuffer() << ", ";
    }

    // last parameter: the constructor expression
    // parenthesis around it, for multiple template parameters
    newLoggerMacro.startBuffer() << "(";
    newLoggerMacro.endBuffer() << ")";

    newLoggerMacro.commitAroundLocations();
  }
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "compilation_unit.h"

#include "compiled_method.h"
#include "file.h"
#include "instruction_set.h"
#include "ir_builder.h"
#include "logging.h"
#include "os.h"

#include "runtime_support_builder_arm.h"
#include "runtime_support_builder_thumb2.h"
#include "runtime_support_builder_x86.h"

#include <llvm/ADT/OwningPtr.h>
#include <llvm/ADT/StringSet.h>
#include <llvm/ADT/Triple.h>
#include <llvm/Analysis/CallGraph.h>
#include <llvm/Analysis/DebugInfo.h>
#include <llvm/Analysis/Dominators.h>
#include <llvm/Analysis/LoopInfo.h>
#include <llvm/Analysis/LoopPass.h>
#include <llvm/Analysis/RegionPass.h>
#include <llvm/Analysis/ScalarEvolution.h>
#include <llvm/Analysis/Verifier.h>
#include <llvm/Assembly/PrintModulePass.h>
#include <llvm/Bitcode/ReaderWriter.h>
#include <llvm/CallGraphSCCPass.h>
#include <llvm/CodeGen/MachineFrameInfo.h>
#include <llvm/CodeGen/MachineFunction.h>
#include <llvm/CodeGen/MachineFunctionPass.h>
#include <llvm/DerivedTypes.h>
#include <llvm/LLVMContext.h>
#include <llvm/Module.h>
#include <llvm/PassManager.h>
#include <llvm/Support/Debug.h>
#include <llvm/Support/FormattedStream.h>
#include <llvm/Support/ManagedStatic.h>
#include <llvm/Support/MemoryBuffer.h>
#include <llvm/Support/PassNameParser.h>
#include <llvm/Support/PluginLoader.h>
#include <llvm/Support/PrettyStackTrace.h>
#include <llvm/Support/Signals.h>
#include <llvm/Support/SystemUtils.h>
#include <llvm/Support/TargetRegistry.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/Support/ToolOutputFile.h>
#include <llvm/Support/raw_ostream.h>
#include <llvm/Support/system_error.h>
#include <llvm/Target/TargetData.h>
#include <llvm/Target/TargetLibraryInfo.h>
#include <llvm/Target/TargetMachine.h>
#include <llvm/Transforms/IPO.h>
#include <llvm/Transforms/IPO/PassManagerBuilder.h>
#include <llvm/Transforms/Scalar.h>

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#include <string>

namespace {

class UpdateFrameSizePass : public llvm::MachineFunctionPass {
 public:
  static char ID;

  UpdateFrameSizePass() : llvm::MachineFunctionPass(ID), cunit_(NULL) {
    LOG(FATAL) << "Unexpected instantiation of UpdateFrameSizePass";
    // NOTE: We have to declare this constructor for llvm::RegisterPass, but
    // this constructor won't work because we have no information on
    // CompilationUnit.  Thus, we should place a LOG(FATAL) here.
  }

  UpdateFrameSizePass(art::compiler_llvm::CompilationUnit* cunit)
    : llvm::MachineFunctionPass(ID), cunit_(cunit) {
  }

  virtual bool runOnMachineFunction(llvm::MachineFunction &MF) {
    cunit_->UpdateFrameSizeInBytes(MF.getFunction(),
                                   MF.getFrameInfo()->getStackSize());
    return false;
  }

 private:
  art::compiler_llvm::CompilationUnit* cunit_;
};

char UpdateFrameSizePass::ID = 0;

llvm::RegisterPass<UpdateFrameSizePass> reg_update_frame_size_pass_(
  "update-frame-size", "Update frame size pass", false, false);

// TODO: We may need something to manage these passes.
// TODO: We need high-level IR to analysis and do this at the IRBuilder level.
class AddSuspendCheckToLoopLatchPass : public llvm::LoopPass {
 public:
  static char ID;

  AddSuspendCheckToLoopLatchPass() : llvm::LoopPass(ID), irb_(NULL) {
    LOG(FATAL) << "Unexpected instantiation of AddSuspendCheckToLoopLatchPass";
    // NOTE: We have to declare this constructor for llvm::RegisterPass, but
    // this constructor won't work because we have no information on
    // IRBuilder.  Thus, we should place a LOG(FATAL) here.
  }

  AddSuspendCheckToLoopLatchPass(art::compiler_llvm::IRBuilder* irb)
    : llvm::LoopPass(ID), irb_(irb) {
  }

  virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const {
    AU.addRequiredID(llvm::LoopSimplifyID);

    AU.addPreserved<llvm::DominatorTree>();
    AU.addPreserved<llvm::LoopInfo>();
    AU.addPreservedID(llvm::LoopSimplifyID);
    AU.addPreserved<llvm::ScalarEvolution>();
    AU.addPreservedID(llvm::BreakCriticalEdgesID);
  }

  virtual bool runOnLoop(llvm::Loop *loop, llvm::LPPassManager &lpm) {
    CHECK_EQ(loop->getNumBackEdges(), 1U) << "Loop must be simplified!";
    llvm::BasicBlock* bb = loop->getLoopLatch();
    CHECK_NE(bb, static_cast<void*>(NULL)) << "A single loop latch must exist.";

    irb_->SetInsertPoint(bb->getTerminator());

    using art::compiler_llvm::runtime_support::TestSuspend;
    llvm::Value* runtime_func = irb_->GetRuntime(TestSuspend);
    irb_->CreateCall(runtime_func, irb_->getJNull());

    return true;
  }

 private:
  art::compiler_llvm::IRBuilder* irb_;
};

char AddSuspendCheckToLoopLatchPass::ID = 0;

llvm::RegisterPass<AddSuspendCheckToLoopLatchPass> reg_add_suspend_check_to_loop_latch_pass_(
  "add-suspend-check-to-loop-latch", "Add suspend check to loop latch pass", false, false);

} // end anonymous namespace

namespace art {
namespace compiler_llvm {

llvm::Module* makeLLVMModuleContents(llvm::Module* module);

CompilationUnit::CompilationUnit(InstructionSet insn_set, size_t elf_idx)
: cunit_lock_("compilation_unit_lock"), insn_set_(insn_set), elf_idx_(elf_idx),
  context_(new llvm::LLVMContext()), compiled_methods_map_(new CompiledMethodMap()),
  mem_usage_(0), num_elf_funcs_(0) {

  // Create the module and include the runtime function declaration
  module_ = new llvm::Module("art", *context_);
  makeLLVMModuleContents(module_);

  // Create IRBuilder
  irb_.reset(new IRBuilder(*context_, *module_));

  // We always need a switch case, so just use a normal function.
  switch(insn_set_) {
  default:
    runtime_support_.reset(new RuntimeSupportBuilder(*context_, *module_, *irb_));
    break;
  case kArm:
    runtime_support_.reset(new RuntimeSupportBuilderARM(*context_, *module_, *irb_));
    break;
  case kThumb2:
    runtime_support_.reset(new RuntimeSupportBuilderThumb2(*context_, *module_, *irb_));
    break;
  case kX86:
    runtime_support_.reset(new RuntimeSupportBuilderX86(*context_, *module_, *irb_));
    break;
  }

  runtime_support_->OptimizeRuntimeSupport();

  irb_->SetRuntimeSupport(runtime_support_.get());
}

CompilationUnit::~CompilationUnit() {
}

bool CompilationUnit::Materialize(size_t thread_count) {
  MutexLock GUARD(cunit_lock_);

  // Materialize the bitcode to elf_image_
  llvm::raw_string_ostream str_os(elf_image_);
  bool success = MaterializeToFile(str_os);
  LOG(INFO) << "Compilation Unit: " << elf_idx_ << (success ? " (done)" : " (failed)");

  // Free the resources
  context_.reset(NULL);
  irb_.reset(NULL);
  module_ = NULL;
  runtime_support_.reset(NULL);
  compiled_methods_map_.reset(NULL);

  return success;
}

void CompilationUnit::RegisterCompiledMethod(const llvm::Function* func,
                                             CompiledMethod* compiled_method) {
  MutexLock GUARD(cunit_lock_);
  compiled_methods_map_->Put(func, compiled_method);
}

void CompilationUnit::UpdateFrameSizeInBytes(const llvm::Function* func,
                                             size_t frame_size_in_bytes) {
  MutexLock GUARD(cunit_lock_);
  SafeMap<const llvm::Function*, CompiledMethod*>::iterator iter =
    compiled_methods_map_->find(func);

  if (iter != compiled_methods_map_->end()) {
    CompiledMethod* compiled_method = iter->second;
    compiled_method->SetFrameSizeInBytes(frame_size_in_bytes);

    if (frame_size_in_bytes > 1728u) {
      LOG(WARNING) << "Huge frame size: " << frame_size_in_bytes
                   << " elf_idx=" << compiled_method->GetElfIndex()
                   << " elf_func_idx=" << compiled_method->GetElfFuncIndex();
    }
  }
}

bool CompilationUnit::MaterializeToFile(llvm::raw_ostream& out_stream) {
  // Lookup the LLVM target
  char const* target_triple = NULL;
  char const* target_attr = NULL;

  switch (insn_set_) {
  case kThumb2:
    target_triple = "thumb-none-linux-gnueabi";
    target_attr = "+thumb2,+neon,+neonfp,+vfp3,+db";
    break;

  case kArm:
    target_triple = "armv7-none-linux-gnueabi";
    // TODO: Fix for Xoom.
    target_attr = "+v7,+neon,+neonfp,+vfp3,+db";
    break;

  case kX86:
    target_triple = "i386-pc-linux-gnu";
    target_attr = "";
    break;

  case kMips:
    target_triple = "mipsel-unknown-linux";
    target_attr = "mips32r2";
    break;

  default:
    LOG(FATAL) << "Unknown instruction set: " << insn_set_;
  }

  std::string errmsg;
  llvm::Target const* target =
    llvm::TargetRegistry::lookupTarget(target_triple, errmsg);

  CHECK(target != NULL) << errmsg;

  // Target options
  llvm::TargetOptions target_options;
  target_options.FloatABIType = llvm::FloatABI::Soft;
  target_options.NoFramePointerElim = true;
  target_options.NoFramePointerElimNonLeaf = true;
  target_options.UseSoftFloat = false;
  target_options.EnableFastISel = false;

  // Create the llvm::TargetMachine
  llvm::OwningPtr<llvm::TargetMachine> target_machine(
    target->createTargetMachine(target_triple, "", target_attr, target_options,
                                llvm::Reloc::Static, llvm::CodeModel::Small,
                                llvm::CodeGenOpt::Aggressive));

  CHECK(target_machine.get() != NULL) << "Failed to create target machine";

  // Add target data
  llvm::TargetData const* target_data = target_machine->getTargetData();

  // PassManager for code generation passes
  llvm::PassManager pm;
  pm.add(new llvm::TargetData(*target_data));

  // FunctionPassManager for optimization pass
  llvm::FunctionPassManager fpm(module_);
  fpm.add(new llvm::TargetData(*target_data));

  if (bitcode_filename_.empty()) {
    // If we don't need write the bitcode to file, add the AddSuspendCheckToLoopLatchPass to the
    // regular FunctionPass.
    fpm.add(new ::AddSuspendCheckToLoopLatchPass(irb_.get()));
  } else {
    // Run AddSuspendCheckToLoopLatchPass before we write the bitcode to file.
    llvm::FunctionPassManager fpm2(module_);
    fpm2.add(new ::AddSuspendCheckToLoopLatchPass(irb_.get()));
    fpm2.doInitialization();
    for (llvm::Module::iterator F = module_->begin(), E = module_->end();
         F != E; ++F) {
      fpm2.run(*F);
    }
    fpm2.doFinalization();

    // Write bitcode to file
    std::string errmsg;

    llvm::OwningPtr<llvm::tool_output_file> out_file(
      new llvm::tool_output_file(bitcode_filename_.c_str(), errmsg,
                                 llvm::raw_fd_ostream::F_Binary));

    if (!errmsg.empty()) {
      LOG(ERROR) << "Failed to create bitcode output file: " << errmsg;
      return false;
    }

    llvm::WriteBitcodeToFile(module_, out_file->os());
    out_file->keep();
  }

  // Add optimization pass
  llvm::PassManagerBuilder pm_builder;
  //pm_builder.Inliner = llvm::createFunctionInliningPass();
  pm_builder.Inliner = llvm::createAlwaysInlinerPass();
  //pm_builder.Inliner = llvm::createPartialInliningPass();
  pm_builder.OptLevel = 3;
  pm_builder.DisableSimplifyLibCalls = 1;
  pm_builder.DisableUnitAtATime = 1;
  pm_builder.populateFunctionPassManager(fpm);
  pm_builder.populateModulePassManager(pm);
  pm.add(llvm::createStripDeadPrototypesPass());

  // Add passes to emit ELF image
  {
    llvm::formatted_raw_ostream formatted_os(out_stream, false);

    // Ask the target to add backend passes as necessary.
    if (target_machine->addPassesToEmitFile(pm,
                                            formatted_os,
                                            llvm::TargetMachine::CGFT_ObjectFile,
                                            true)) {
      LOG(FATAL) << "Unable to generate ELF for this target";
      return false;
    }

    // FIXME: Unable to run the UpdateFrameSizePass pass since it tries to
    //        update the value reside in the different address space.
    // Add pass to update the frame_size_in_bytes_
    //pm.add(new ::UpdateFrameSizePass(this));

    // Run the per-function optimization
    fpm.doInitialization();
    for (llvm::Module::iterator F = module_->begin(), E = module_->end();
         F != E; ++F) {
      fpm.run(*F);
    }
    fpm.doFinalization();

    // Run the code generation passes
    pm.run(*module_);
  }

  return true;
}

} // namespace compiler_llvm
} // namespace art
<commit_msg>am 53519bf6: Set Target CPU.<commit_after>/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "compilation_unit.h"

#include "compiled_method.h"
#include "file.h"
#include "instruction_set.h"
#include "ir_builder.h"
#include "logging.h"
#include "os.h"

#include "runtime_support_builder_arm.h"
#include "runtime_support_builder_thumb2.h"
#include "runtime_support_builder_x86.h"

#include <llvm/ADT/OwningPtr.h>
#include <llvm/ADT/StringSet.h>
#include <llvm/ADT/Triple.h>
#include <llvm/Analysis/CallGraph.h>
#include <llvm/Analysis/DebugInfo.h>
#include <llvm/Analysis/Dominators.h>
#include <llvm/Analysis/LoopInfo.h>
#include <llvm/Analysis/LoopPass.h>
#include <llvm/Analysis/RegionPass.h>
#include <llvm/Analysis/ScalarEvolution.h>
#include <llvm/Analysis/Verifier.h>
#include <llvm/Assembly/PrintModulePass.h>
#include <llvm/Bitcode/ReaderWriter.h>
#include <llvm/CallGraphSCCPass.h>
#include <llvm/CodeGen/MachineFrameInfo.h>
#include <llvm/CodeGen/MachineFunction.h>
#include <llvm/CodeGen/MachineFunctionPass.h>
#include <llvm/DerivedTypes.h>
#include <llvm/LLVMContext.h>
#include <llvm/Module.h>
#include <llvm/PassManager.h>
#include <llvm/Support/Debug.h>
#include <llvm/Support/FormattedStream.h>
#include <llvm/Support/ManagedStatic.h>
#include <llvm/Support/MemoryBuffer.h>
#include <llvm/Support/PassNameParser.h>
#include <llvm/Support/PluginLoader.h>
#include <llvm/Support/PrettyStackTrace.h>
#include <llvm/Support/Signals.h>
#include <llvm/Support/SystemUtils.h>
#include <llvm/Support/TargetRegistry.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/Support/ToolOutputFile.h>
#include <llvm/Support/raw_ostream.h>
#include <llvm/Support/system_error.h>
#include <llvm/Target/TargetData.h>
#include <llvm/Target/TargetLibraryInfo.h>
#include <llvm/Target/TargetMachine.h>
#include <llvm/Transforms/IPO.h>
#include <llvm/Transforms/IPO/PassManagerBuilder.h>
#include <llvm/Transforms/Scalar.h>

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#include <string>

namespace {

class UpdateFrameSizePass : public llvm::MachineFunctionPass {
 public:
  static char ID;

  UpdateFrameSizePass() : llvm::MachineFunctionPass(ID), cunit_(NULL) {
    LOG(FATAL) << "Unexpected instantiation of UpdateFrameSizePass";
    // NOTE: We have to declare this constructor for llvm::RegisterPass, but
    // this constructor won't work because we have no information on
    // CompilationUnit.  Thus, we should place a LOG(FATAL) here.
  }

  UpdateFrameSizePass(art::compiler_llvm::CompilationUnit* cunit)
    : llvm::MachineFunctionPass(ID), cunit_(cunit) {
  }

  virtual bool runOnMachineFunction(llvm::MachineFunction &MF) {
    cunit_->UpdateFrameSizeInBytes(MF.getFunction(),
                                   MF.getFrameInfo()->getStackSize());
    return false;
  }

 private:
  art::compiler_llvm::CompilationUnit* cunit_;
};

char UpdateFrameSizePass::ID = 0;

llvm::RegisterPass<UpdateFrameSizePass> reg_update_frame_size_pass_(
  "update-frame-size", "Update frame size pass", false, false);

// TODO: We may need something to manage these passes.
// TODO: We need high-level IR to analysis and do this at the IRBuilder level.
class AddSuspendCheckToLoopLatchPass : public llvm::LoopPass {
 public:
  static char ID;

  AddSuspendCheckToLoopLatchPass() : llvm::LoopPass(ID), irb_(NULL) {
    LOG(FATAL) << "Unexpected instantiation of AddSuspendCheckToLoopLatchPass";
    // NOTE: We have to declare this constructor for llvm::RegisterPass, but
    // this constructor won't work because we have no information on
    // IRBuilder.  Thus, we should place a LOG(FATAL) here.
  }

  AddSuspendCheckToLoopLatchPass(art::compiler_llvm::IRBuilder* irb)
    : llvm::LoopPass(ID), irb_(irb) {
  }

  virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const {
    AU.addRequiredID(llvm::LoopSimplifyID);

    AU.addPreserved<llvm::DominatorTree>();
    AU.addPreserved<llvm::LoopInfo>();
    AU.addPreservedID(llvm::LoopSimplifyID);
    AU.addPreserved<llvm::ScalarEvolution>();
    AU.addPreservedID(llvm::BreakCriticalEdgesID);
  }

  virtual bool runOnLoop(llvm::Loop *loop, llvm::LPPassManager &lpm) {
    CHECK_EQ(loop->getNumBackEdges(), 1U) << "Loop must be simplified!";
    llvm::BasicBlock* bb = loop->getLoopLatch();
    CHECK_NE(bb, static_cast<void*>(NULL)) << "A single loop latch must exist.";

    irb_->SetInsertPoint(bb->getTerminator());

    using art::compiler_llvm::runtime_support::TestSuspend;
    llvm::Value* runtime_func = irb_->GetRuntime(TestSuspend);
    irb_->CreateCall(runtime_func, irb_->getJNull());

    return true;
  }

 private:
  art::compiler_llvm::IRBuilder* irb_;
};

char AddSuspendCheckToLoopLatchPass::ID = 0;

llvm::RegisterPass<AddSuspendCheckToLoopLatchPass> reg_add_suspend_check_to_loop_latch_pass_(
  "add-suspend-check-to-loop-latch", "Add suspend check to loop latch pass", false, false);

} // end anonymous namespace

namespace art {
namespace compiler_llvm {

llvm::Module* makeLLVMModuleContents(llvm::Module* module);

CompilationUnit::CompilationUnit(InstructionSet insn_set, size_t elf_idx)
: cunit_lock_("compilation_unit_lock"), insn_set_(insn_set), elf_idx_(elf_idx),
  context_(new llvm::LLVMContext()), compiled_methods_map_(new CompiledMethodMap()),
  mem_usage_(0), num_elf_funcs_(0) {

  // Create the module and include the runtime function declaration
  module_ = new llvm::Module("art", *context_);
  makeLLVMModuleContents(module_);

  // Create IRBuilder
  irb_.reset(new IRBuilder(*context_, *module_));

  // We always need a switch case, so just use a normal function.
  switch(insn_set_) {
  default:
    runtime_support_.reset(new RuntimeSupportBuilder(*context_, *module_, *irb_));
    break;
  case kArm:
    runtime_support_.reset(new RuntimeSupportBuilderARM(*context_, *module_, *irb_));
    break;
  case kThumb2:
    runtime_support_.reset(new RuntimeSupportBuilderThumb2(*context_, *module_, *irb_));
    break;
  case kX86:
    runtime_support_.reset(new RuntimeSupportBuilderX86(*context_, *module_, *irb_));
    break;
  }

  runtime_support_->OptimizeRuntimeSupport();

  irb_->SetRuntimeSupport(runtime_support_.get());
}

CompilationUnit::~CompilationUnit() {
}

bool CompilationUnit::Materialize(size_t thread_count) {
  MutexLock GUARD(cunit_lock_);

  // Materialize the bitcode to elf_image_
  llvm::raw_string_ostream str_os(elf_image_);
  bool success = MaterializeToFile(str_os);
  LOG(INFO) << "Compilation Unit: " << elf_idx_ << (success ? " (done)" : " (failed)");

  // Free the resources
  context_.reset(NULL);
  irb_.reset(NULL);
  module_ = NULL;
  runtime_support_.reset(NULL);
  compiled_methods_map_.reset(NULL);

  return success;
}

void CompilationUnit::RegisterCompiledMethod(const llvm::Function* func,
                                             CompiledMethod* compiled_method) {
  MutexLock GUARD(cunit_lock_);
  compiled_methods_map_->Put(func, compiled_method);
}

void CompilationUnit::UpdateFrameSizeInBytes(const llvm::Function* func,
                                             size_t frame_size_in_bytes) {
  MutexLock GUARD(cunit_lock_);
  SafeMap<const llvm::Function*, CompiledMethod*>::iterator iter =
    compiled_methods_map_->find(func);

  if (iter != compiled_methods_map_->end()) {
    CompiledMethod* compiled_method = iter->second;
    compiled_method->SetFrameSizeInBytes(frame_size_in_bytes);

    if (frame_size_in_bytes > 1728u) {
      LOG(WARNING) << "Huge frame size: " << frame_size_in_bytes
                   << " elf_idx=" << compiled_method->GetElfIndex()
                   << " elf_func_idx=" << compiled_method->GetElfFuncIndex();
    }
  }
}

bool CompilationUnit::MaterializeToFile(llvm::raw_ostream& out_stream) {
  // Lookup the LLVM target
  char const* target_triple = NULL;
  char const* target_cpu = "";
  char const* target_attr = NULL;

  switch (insn_set_) {
  case kThumb2:
    target_triple = "thumb-none-linux-gnueabi";
    target_cpu = "cortex-a9";
    target_attr = "+thumb2,+neon,+neonfp,+vfp3,+db";
    break;

  case kArm:
    target_triple = "armv7-none-linux-gnueabi";
    // TODO: Fix for Nexus S.
    target_cpu = "cortex-a9";
    // TODO: Fix for Xoom.
    target_attr = "+v7,+neon,+neonfp,+vfp3,+db";
    break;

  case kX86:
    target_triple = "i386-pc-linux-gnu";
    target_attr = "";
    break;

  case kMips:
    target_triple = "mipsel-unknown-linux";
    target_attr = "mips32r2";
    break;

  default:
    LOG(FATAL) << "Unknown instruction set: " << insn_set_;
  }

  std::string errmsg;
  llvm::Target const* target =
    llvm::TargetRegistry::lookupTarget(target_triple, errmsg);

  CHECK(target != NULL) << errmsg;

  // Target options
  llvm::TargetOptions target_options;
  target_options.FloatABIType = llvm::FloatABI::Soft;
  target_options.NoFramePointerElim = true;
  target_options.NoFramePointerElimNonLeaf = true;
  target_options.UseSoftFloat = false;
  target_options.EnableFastISel = false;

  // Create the llvm::TargetMachine
  llvm::OwningPtr<llvm::TargetMachine> target_machine(
    target->createTargetMachine(target_triple, target_cpu, target_attr, target_options,
                                llvm::Reloc::Static, llvm::CodeModel::Small,
                                llvm::CodeGenOpt::Aggressive));

  CHECK(target_machine.get() != NULL) << "Failed to create target machine";

  // Add target data
  llvm::TargetData const* target_data = target_machine->getTargetData();

  // PassManager for code generation passes
  llvm::PassManager pm;
  pm.add(new llvm::TargetData(*target_data));

  // FunctionPassManager for optimization pass
  llvm::FunctionPassManager fpm(module_);
  fpm.add(new llvm::TargetData(*target_data));

  if (bitcode_filename_.empty()) {
    // If we don't need write the bitcode to file, add the AddSuspendCheckToLoopLatchPass to the
    // regular FunctionPass.
    fpm.add(new ::AddSuspendCheckToLoopLatchPass(irb_.get()));
  } else {
    // Run AddSuspendCheckToLoopLatchPass before we write the bitcode to file.
    llvm::FunctionPassManager fpm2(module_);
    fpm2.add(new ::AddSuspendCheckToLoopLatchPass(irb_.get()));
    fpm2.doInitialization();
    for (llvm::Module::iterator F = module_->begin(), E = module_->end();
         F != E; ++F) {
      fpm2.run(*F);
    }
    fpm2.doFinalization();

    // Write bitcode to file
    std::string errmsg;

    llvm::OwningPtr<llvm::tool_output_file> out_file(
      new llvm::tool_output_file(bitcode_filename_.c_str(), errmsg,
                                 llvm::raw_fd_ostream::F_Binary));

    if (!errmsg.empty()) {
      LOG(ERROR) << "Failed to create bitcode output file: " << errmsg;
      return false;
    }

    llvm::WriteBitcodeToFile(module_, out_file->os());
    out_file->keep();
  }

  // Add optimization pass
  llvm::PassManagerBuilder pm_builder;
  //pm_builder.Inliner = llvm::createFunctionInliningPass();
  pm_builder.Inliner = llvm::createAlwaysInlinerPass();
  //pm_builder.Inliner = llvm::createPartialInliningPass();
  pm_builder.OptLevel = 3;
  pm_builder.DisableSimplifyLibCalls = 1;
  pm_builder.DisableUnitAtATime = 1;
  pm_builder.populateFunctionPassManager(fpm);
  pm_builder.populateModulePassManager(pm);
  pm.add(llvm::createStripDeadPrototypesPass());

  // Add passes to emit ELF image
  {
    llvm::formatted_raw_ostream formatted_os(out_stream, false);

    // Ask the target to add backend passes as necessary.
    if (target_machine->addPassesToEmitFile(pm,
                                            formatted_os,
                                            llvm::TargetMachine::CGFT_ObjectFile,
                                            true)) {
      LOG(FATAL) << "Unable to generate ELF for this target";
      return false;
    }

    // FIXME: Unable to run the UpdateFrameSizePass pass since it tries to
    //        update the value reside in the different address space.
    // Add pass to update the frame_size_in_bytes_
    //pm.add(new ::UpdateFrameSizePass(this));

    // Run the per-function optimization
    fpm.doInitialization();
    for (llvm::Module::iterator F = module_->begin(), E = module_->end();
         F != E; ++F) {
      fpm.run(*F);
    }
    fpm.doFinalization();

    // Run the code generation passes
    pm.run(*module_);
  }

  return true;
}

} // namespace compiler_llvm
} // namespace art
<|endoftext|>


<commit_before>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2011 Ulrich von Zadow
//
//  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 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "VDPAUHelper.h"

#include "../base/Exception.h"
#include "../base/ConfigMgr.h"

#include "../graphics/Bitmap.h"

#include <dlfcn.h>

using namespace std;

namespace avg {

VdpGetProcAddress* vdp_get_proc_address;

VdpVideoSurfaceGetParameters* vdp_video_surface_get_parameters;
VdpVideoSurfaceGetBitsYCbCr* vdp_video_surface_get_bits_y_cb_cr;
VdpVideoSurfaceCreate* vdp_video_surface_create;
VdpVideoSurfaceDestroy* vdp_video_surface_destroy;

VdpDeviceDestroy* vdp_device_destroy;

VdpDecoderCreate* vdp_decoder_create;
VdpDecoderDestroy* vdp_decoder_destroy;
VdpDecoderRender* vdp_decoder_render;

VdpOutputSurfaceCreate* vdp_output_surface_create;
VdpOutputSurfaceDestroy* vdp_output_surface_destroy;
VdpOutputSurfaceGetBitsNative* vdp_output_surface_get_bits_native;
VdpOutputSurfaceGetParameters* vdp_output_surface_get_parameters;

VdpVideoMixerCreate* vdp_video_mixer_create;
VdpVideoMixerDestroy* vdp_video_mixer_destroy;
VdpVideoMixerRender* vdp_video_mixer_render;

VdpPresentationQueueCreate* vdp_presentation_queue_create;
VdpPresentationQueueDestroy* vdp_presentation_queue_destroy;
VdpPresentationQueueGetTime* vdp_presentation_queue_get_time;
VdpPresentationQueueTargetCreateX11* vdp_presentation_queue_target_create_x11;
VdpPresentationQueueQuerySurfaceStatus* vdp_presentation_queue_query_surface_status;
VdpPresentationQueueDisplay* vdp_presentation_queue_display;
VdpPresentationQueueBlockUntilSurfaceIdle*
        vdp_presentation_queue_block_until_surface_idle;

void safeGetProcAddress(VdpFuncId functionId, void** functionPointer)
{
    VdpStatus status;
    status = vdp_get_proc_address(getVDPAUDevice(), functionId, functionPointer);
    AVG_ASSERT(status == VDP_STATUS_OK);
}

VdpDevice getVDPAUDevice()
{
    static VdpDevice vdpDevice = 0;
    static bool bInitFailed = false;

    if (vdpDevice) {
        return vdpDevice;
    }

    if (bInitFailed) {
        return 0;
    }

    Display* pXDisplay = XOpenDisplay(0);
    AVG_ASSERT(pXDisplay);

    if (!(ConfigMgr::get()->getBoolOption("scr", "videoaccel", true))) {
        bInitFailed = true;
        return 0;
    }
    VdpStatus status;
    void* dll = dlopen("libvdpau_nvidia.so", RTLD_LAZY);
    if (!dll) {
        bInitFailed = true;
        return 0;
    }
    dlclose(dll);
    status = vdp_device_create_x11(pXDisplay, DefaultScreen(pXDisplay), &vdpDevice,
            &vdp_get_proc_address);
    if (status != VDP_STATUS_OK)
    {
        bInitFailed = true;
        return 0;
    }

    safeGetProcAddress(VDP_FUNC_ID_DEVICE_DESTROY, (void**)&vdp_device_destroy);
    safeGetProcAddress(VDP_FUNC_ID_OUTPUT_SURFACE_CREATE,
            (void**)&vdp_output_surface_create);
    safeGetProcAddress(VDP_FUNC_ID_OUTPUT_SURFACE_DESTROY,
            (void**)&vdp_output_surface_destroy);
    safeGetProcAddress(VDP_FUNC_ID_OUTPUT_SURFACE_GET_BITS_NATIVE,
            (void**)&vdp_output_surface_get_bits_native);
    safeGetProcAddress(VDP_FUNC_ID_VIDEO_SURFACE_CREATE,
            (void**)&vdp_video_surface_create);
    safeGetProcAddress(VDP_FUNC_ID_VIDEO_SURFACE_DESTROY,
            (void**)&vdp_video_surface_destroy);
    safeGetProcAddress(VDP_FUNC_ID_DECODER_CREATE, (void**)&vdp_decoder_create);
    safeGetProcAddress(VDP_FUNC_ID_DECODER_DESTROY, (void**)&vdp_decoder_destroy);
    safeGetProcAddress(VDP_FUNC_ID_DECODER_RENDER, (void**)&vdp_decoder_render);
    safeGetProcAddress(VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR,
            (void**)&vdp_video_surface_get_bits_y_cb_cr);
    safeGetProcAddress(VDP_FUNC_ID_VIDEO_MIXER_CREATE,
            (void**)&vdp_video_mixer_create);
    safeGetProcAddress(VDP_FUNC_ID_VIDEO_MIXER_DESTROY,
            (void**)&vdp_video_mixer_destroy);
    safeGetProcAddress(VDP_FUNC_ID_VIDEO_MIXER_RENDER,
            (void**)&vdp_video_mixer_render);
    safeGetProcAddress(VDP_FUNC_ID_PRESENTATION_QUEUE_CREATE,
            (void**)&vdp_presentation_queue_create);
    safeGetProcAddress(VDP_FUNC_ID_PRESENTATION_QUEUE_DESTROY,
            (void**)&vdp_presentation_queue_destroy);
    safeGetProcAddress(VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11,
            (void**)&vdp_presentation_queue_target_create_x11);
    safeGetProcAddress(VDP_FUNC_ID_PRESENTATION_QUEUE_QUERY_SURFACE_STATUS,
            (void**)&vdp_presentation_queue_query_surface_status);
    safeGetProcAddress(VDP_FUNC_ID_PRESENTATION_QUEUE_DISPLAY,
            (void**)&vdp_presentation_queue_display);
    safeGetProcAddress(VDP_FUNC_ID_PRESENTATION_QUEUE_GET_TIME,
            (void**)&vdp_presentation_queue_get_time);
    safeGetProcAddress(VDP_FUNC_ID_PRESENTATION_QUEUE_BLOCK_UNTIL_SURFACE_IDLE,
            (void**)&vdp_presentation_queue_block_until_surface_idle);
    safeGetProcAddress(VDP_FUNC_ID_VIDEO_SURFACE_GET_PARAMETERS,
            (void**)&vdp_video_surface_get_parameters);
    safeGetProcAddress(VDP_FUNC_ID_OUTPUT_SURFACE_GET_PARAMETERS,
            (void**)&vdp_output_surface_get_parameters);
    return vdpDevice;
}

void getPlanesFromVDPAU(vdpau_render_state* pRenderState, BitmapPtr pBmpY,
        BitmapPtr pBmpU, BitmapPtr pBmpV)
{
    VdpStatus status;
    void *dest[3] = {
        pBmpY->getPixels(),
        pBmpV->getPixels(),
        pBmpU->getPixels()
    };
    uint32_t pitches[3] = {
        pBmpY->getStride(),
        pBmpV->getStride(),
        pBmpU->getStride()
    };
    status = vdp_video_surface_get_bits_y_cb_cr(pRenderState->surface,
            VDP_YCBCR_FORMAT_YV12, dest, pitches);
    AVG_ASSERT(status == VDP_STATUS_OK);
    unlockVDPAUSurface(pRenderState);
}

void getBitmapFromVDPAU(vdpau_render_state* pRenderState, BitmapPtr pBmpDest)
{
    IntPoint YSize = pBmpDest->getSize();
    IntPoint UVSize(YSize.x/2, YSize.y/2);
    BitmapPtr pBmpY(new Bitmap(YSize, I8));
    BitmapPtr pBmpU(new Bitmap(UVSize, I8));
    BitmapPtr pBmpV(new Bitmap(UVSize, I8));
    getPlanesFromVDPAU(pRenderState, pBmpY, pBmpU, pBmpV);
    pBmpDest->copyYUVPixels(*pBmpY, *pBmpU, *pBmpV, false);
}

void unlockVDPAUSurface(vdpau_render_state* pRenderState)
{
    pRenderState->state &= ~FF_VDPAU_STATE_USED_FOR_REFERENCE;
}

}
<commit_msg>Fixed VDPAU detection.<commit_after>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2011 Ulrich von Zadow
//
//  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 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "VDPAUHelper.h"

#include "../base/Exception.h"
#include "../base/ConfigMgr.h"

#include "../graphics/Bitmap.h"

#include <dlfcn.h>

using namespace std;

namespace avg {

VdpGetProcAddress* vdp_get_proc_address;

VdpVideoSurfaceGetParameters* vdp_video_surface_get_parameters;
VdpVideoSurfaceGetBitsYCbCr* vdp_video_surface_get_bits_y_cb_cr;
VdpVideoSurfaceCreate* vdp_video_surface_create;
VdpVideoSurfaceDestroy* vdp_video_surface_destroy;

VdpDeviceDestroy* vdp_device_destroy;

VdpDecoderCreate* vdp_decoder_create;
VdpDecoderDestroy* vdp_decoder_destroy;
VdpDecoderRender* vdp_decoder_render;

VdpOutputSurfaceCreate* vdp_output_surface_create;
VdpOutputSurfaceDestroy* vdp_output_surface_destroy;
VdpOutputSurfaceGetBitsNative* vdp_output_surface_get_bits_native;
VdpOutputSurfaceGetParameters* vdp_output_surface_get_parameters;

VdpVideoMixerCreate* vdp_video_mixer_create;
VdpVideoMixerDestroy* vdp_video_mixer_destroy;
VdpVideoMixerRender* vdp_video_mixer_render;

VdpPresentationQueueCreate* vdp_presentation_queue_create;
VdpPresentationQueueDestroy* vdp_presentation_queue_destroy;
VdpPresentationQueueGetTime* vdp_presentation_queue_get_time;
VdpPresentationQueueTargetCreateX11* vdp_presentation_queue_target_create_x11;
VdpPresentationQueueQuerySurfaceStatus* vdp_presentation_queue_query_surface_status;
VdpPresentationQueueDisplay* vdp_presentation_queue_display;
VdpPresentationQueueBlockUntilSurfaceIdle*
        vdp_presentation_queue_block_until_surface_idle;

void safeGetProcAddress(VdpFuncId functionId, void** functionPointer)
{
    VdpStatus status;
    status = vdp_get_proc_address(getVDPAUDevice(), functionId, functionPointer);
    AVG_ASSERT(status == VDP_STATUS_OK);
}

VdpDevice getVDPAUDevice()
{
    static VdpDevice vdpDevice = 0;
    static bool bInitFailed = false;

    if (vdpDevice) {
        return vdpDevice;
    }

    if (bInitFailed) {
        return 0;
    }

    Display* pXDisplay = XOpenDisplay(0);
    AVG_ASSERT(pXDisplay);

    if (!(ConfigMgr::get()->getBoolOption("scr", "videoaccel", true))) {
        bInitFailed = true;
        return 0;
    }
    VdpStatus status;
    status = vdp_device_create_x11(pXDisplay, DefaultScreen(pXDisplay), &vdpDevice,
            &vdp_get_proc_address);
    if (status != VDP_STATUS_OK)
    {
        bInitFailed = true;
        return 0;
    }

    safeGetProcAddress(VDP_FUNC_ID_DEVICE_DESTROY, (void**)&vdp_device_destroy);
    safeGetProcAddress(VDP_FUNC_ID_OUTPUT_SURFACE_CREATE,
            (void**)&vdp_output_surface_create);
    safeGetProcAddress(VDP_FUNC_ID_OUTPUT_SURFACE_DESTROY,
            (void**)&vdp_output_surface_destroy);
    safeGetProcAddress(VDP_FUNC_ID_OUTPUT_SURFACE_GET_BITS_NATIVE,
            (void**)&vdp_output_surface_get_bits_native);
    safeGetProcAddress(VDP_FUNC_ID_VIDEO_SURFACE_CREATE,
            (void**)&vdp_video_surface_create);
    safeGetProcAddress(VDP_FUNC_ID_VIDEO_SURFACE_DESTROY,
            (void**)&vdp_video_surface_destroy);
    safeGetProcAddress(VDP_FUNC_ID_DECODER_CREATE, (void**)&vdp_decoder_create);
    safeGetProcAddress(VDP_FUNC_ID_DECODER_DESTROY, (void**)&vdp_decoder_destroy);
    safeGetProcAddress(VDP_FUNC_ID_DECODER_RENDER, (void**)&vdp_decoder_render);
    safeGetProcAddress(VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR,
            (void**)&vdp_video_surface_get_bits_y_cb_cr);
    safeGetProcAddress(VDP_FUNC_ID_VIDEO_MIXER_CREATE,
            (void**)&vdp_video_mixer_create);
    safeGetProcAddress(VDP_FUNC_ID_VIDEO_MIXER_DESTROY,
            (void**)&vdp_video_mixer_destroy);
    safeGetProcAddress(VDP_FUNC_ID_VIDEO_MIXER_RENDER,
            (void**)&vdp_video_mixer_render);
    safeGetProcAddress(VDP_FUNC_ID_PRESENTATION_QUEUE_CREATE,
            (void**)&vdp_presentation_queue_create);
    safeGetProcAddress(VDP_FUNC_ID_PRESENTATION_QUEUE_DESTROY,
            (void**)&vdp_presentation_queue_destroy);
    safeGetProcAddress(VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11,
            (void**)&vdp_presentation_queue_target_create_x11);
    safeGetProcAddress(VDP_FUNC_ID_PRESENTATION_QUEUE_QUERY_SURFACE_STATUS,
            (void**)&vdp_presentation_queue_query_surface_status);
    safeGetProcAddress(VDP_FUNC_ID_PRESENTATION_QUEUE_DISPLAY,
            (void**)&vdp_presentation_queue_display);
    safeGetProcAddress(VDP_FUNC_ID_PRESENTATION_QUEUE_GET_TIME,
            (void**)&vdp_presentation_queue_get_time);
    safeGetProcAddress(VDP_FUNC_ID_PRESENTATION_QUEUE_BLOCK_UNTIL_SURFACE_IDLE,
            (void**)&vdp_presentation_queue_block_until_surface_idle);
    safeGetProcAddress(VDP_FUNC_ID_VIDEO_SURFACE_GET_PARAMETERS,
            (void**)&vdp_video_surface_get_parameters);
    safeGetProcAddress(VDP_FUNC_ID_OUTPUT_SURFACE_GET_PARAMETERS,
            (void**)&vdp_output_surface_get_parameters);
    return vdpDevice;
}

void getPlanesFromVDPAU(vdpau_render_state* pRenderState, BitmapPtr pBmpY,
        BitmapPtr pBmpU, BitmapPtr pBmpV)
{
    VdpStatus status;
    void *dest[3] = {
        pBmpY->getPixels(),
        pBmpV->getPixels(),
        pBmpU->getPixels()
    };
    uint32_t pitches[3] = {
        pBmpY->getStride(),
        pBmpV->getStride(),
        pBmpU->getStride()
    };
    status = vdp_video_surface_get_bits_y_cb_cr(pRenderState->surface,
            VDP_YCBCR_FORMAT_YV12, dest, pitches);
    AVG_ASSERT(status == VDP_STATUS_OK);
    unlockVDPAUSurface(pRenderState);
}

void getBitmapFromVDPAU(vdpau_render_state* pRenderState, BitmapPtr pBmpDest)
{
    IntPoint YSize = pBmpDest->getSize();
    IntPoint UVSize(YSize.x/2, YSize.y/2);
    BitmapPtr pBmpY(new Bitmap(YSize, I8));
    BitmapPtr pBmpU(new Bitmap(UVSize, I8));
    BitmapPtr pBmpV(new Bitmap(UVSize, I8));
    getPlanesFromVDPAU(pRenderState, pBmpY, pBmpU, pBmpV);
    pBmpDest->copyYUVPixels(*pBmpY, *pBmpU, *pBmpV, false);
}

void unlockVDPAUSurface(vdpau_render_state* pRenderState)
{
    pRenderState->state &= ~FF_VDPAU_STATE_USED_FOR_REFERENCE;
}

}
<|endoftext|>


<commit_before><commit_msg>tubes: improve the hack to work outside the test suite!<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2012 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 "ui/base/win/hwnd_util.h"

#include "base/i18n/rtl.h"
#include "base/string_util.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/size.h"

namespace ui {

namespace {

// Adjust the window to fit, returning true if the window was resized or moved.
void AdjustWindowToFit(HWND hwnd, const RECT& bounds, bool fit_to_monitor) {
  if (fit_to_monitor) {
    // Get the monitor.
    HMONITOR hmon = MonitorFromRect(&bounds, MONITOR_DEFAULTTONEAREST);
    if (hmon) {
      MONITORINFO mi;
      mi.cbSize = sizeof(mi);
      GetMonitorInfo(hmon, &mi);
      gfx::Rect window_rect(bounds);
      gfx::Rect monitor_rect(mi.rcWork);
      gfx::Rect new_window_rect = window_rect.AdjustToFit(monitor_rect);
      if (!new_window_rect.Equals(window_rect)) {
        // Window doesn't fit on monitor, move and possibly resize.
        SetWindowPos(hwnd, 0, new_window_rect.x(), new_window_rect.y(),
                     new_window_rect.width(), new_window_rect.height(),
                     SWP_NOACTIVATE | SWP_NOZORDER);
        return;
      }
      // Else fall through.
    } else {
      NOTREACHED() << "Unable to find default monitor";
      // Fall through.
    }
  }  // Else fall through.

  // The window is not being fit to monitor, or the window fits on the monitor
  // as is, or we have no monitor info; reset the bounds.
  ::SetWindowPos(hwnd, 0, bounds.left, bounds.top,
                 bounds.right - bounds.left, bounds.bottom - bounds.top,
                 SWP_NOACTIVATE | SWP_NOZORDER);
}

}  // namespace

string16 GetClassName(HWND window) {
  // GetClassNameW will return a truncated result (properly null terminated) if
  // the given buffer is not large enough.  So, it is not possible to determine
  // that we got the entire class name if the result is exactly equal to the
  // size of the buffer minus one.
  DWORD buffer_size = MAX_PATH;
  while (true) {
    std::wstring output;
    DWORD size_ret =
        GetClassNameW(window, WriteInto(&output, buffer_size), buffer_size);
    if (size_ret == 0)
      break;
    if (size_ret < (buffer_size - 1)) {
      output.resize(size_ret);
      return output;
    }
    buffer_size *= 2;
  }
  return std::wstring();  // error
}

#pragma warning(push)
#pragma warning(disable:4312 4244)

WNDPROC SetWindowProc(HWND hwnd, WNDPROC proc) {
  // The reason we don't return the SetwindowLongPtr() value is that it returns
  // the orignal window procedure and not the current one. I don't know if it is
  // a bug or an intended feature.
  WNDPROC oldwindow_proc =
      reinterpret_cast<WNDPROC>(GetWindowLongPtr(hwnd, GWLP_WNDPROC));
  SetWindowLongPtr(hwnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(proc));
  return oldwindow_proc;
}

void* SetWindowUserData(HWND hwnd, void* user_data) {
  return
      reinterpret_cast<void*>(SetWindowLongPtr(hwnd, GWLP_USERDATA,
          reinterpret_cast<LONG_PTR>(user_data)));
}

void* GetWindowUserData(HWND hwnd) {
  DWORD process_id = 0;
  DWORD thread_id = GetWindowThreadProcessId(hwnd, &process_id);
  // A window outside the current process needs to be ignored.
  if (process_id != ::GetCurrentProcessId())
    return NULL;
  return reinterpret_cast<void*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
}

#pragma warning(pop)

bool DoesWindowBelongToActiveWindow(HWND window) {
  DCHECK(window);
  HWND top_window = ::GetAncestor(window, GA_ROOT);
  if (!top_window)
    return false;

  HWND active_top_window = ::GetAncestor(::GetForegroundWindow(), GA_ROOT);
  return (top_window == active_top_window);
}

void CenterAndSizeWindow(HWND parent,
                         HWND window,
                         const gfx::Size& pref) {
  DCHECK(window && pref.width() > 0 && pref.height() > 0);

  // Calculate the ideal bounds.
  RECT window_bounds;
  RECT center_bounds = {0};
  if (parent) {
    // If there is a parent, center over the parents bounds.
    ::GetWindowRect(parent, &center_bounds);
  }

  if (::IsRectEmpty(&center_bounds)) {
    // No parent or no parent rect. Center over the monitor the window is on.
    HMONITOR monitor = MonitorFromWindow(window, MONITOR_DEFAULTTONEAREST);
    if (monitor) {
      MONITORINFO mi = {0};
      mi.cbSize = sizeof(mi);
      GetMonitorInfo(monitor, &mi);
      center_bounds = mi.rcWork;
    } else {
      NOTREACHED() << "Unable to get default monitor";
    }
  }
  window_bounds.left = center_bounds.left +
      (center_bounds.right - center_bounds.left - pref.width()) / 2;
  window_bounds.right = window_bounds.left + pref.width();
  window_bounds.top = center_bounds.top +
      (center_bounds.bottom - center_bounds.top - pref.height()) / 2;
  window_bounds.bottom = window_bounds.top + pref.height();

  // If we're centering a child window, we are positioning in client
  // coordinates, and as such we need to offset the target rectangle by the
  // position of the parent window.
  if (::GetWindowLong(window, GWL_STYLE) & WS_CHILD) {
    DCHECK(parent && ::GetParent(window) == parent);
    POINT topleft = { window_bounds.left, window_bounds.top };
    ::MapWindowPoints(HWND_DESKTOP, parent, &topleft, 1);
    window_bounds.left = topleft.x;
    window_bounds.top = topleft.y;
    window_bounds.right = window_bounds.left + pref.width();
    window_bounds.bottom = window_bounds.top + pref.height();
  }

  AdjustWindowToFit(window, window_bounds, !parent);
}

void CheckWindowCreated(HWND hwnd) {
  if (!hwnd)
    LOG_GETLASTERROR(FATAL);
}

void ShowSystemMenu(HWND window, int screen_x, int screen_y) {
  UINT flags = TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RETURNCMD;
  if (base::i18n::IsRTL())
    flags |= TPM_RIGHTALIGN;
  HMENU system_menu = GetSystemMenu(window, FALSE);
  int command = TrackPopupMenu(system_menu, flags, screen_x, screen_y, 0,
                               window, NULL);
  if (command)
    SendMessage(window, WM_SYSCOMMAND, command, 0);
}

}  // namespace ui
<commit_msg>Windows: Don't try to center a popup over a parent window when the popup is bigger than the parent.<commit_after>// Copyright (c) 2012 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 "ui/base/win/hwnd_util.h"

#include "base/i18n/rtl.h"
#include "base/string_util.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/size.h"

namespace ui {

namespace {

// Adjust the window to fit.
void AdjustWindowToFit(HWND hwnd, const RECT& bounds, bool fit_to_monitor) {
  if (fit_to_monitor) {
    // Get the monitor.
    HMONITOR hmon = MonitorFromRect(&bounds, MONITOR_DEFAULTTONEAREST);
    if (hmon) {
      MONITORINFO mi;
      mi.cbSize = sizeof(mi);
      GetMonitorInfo(hmon, &mi);
      gfx::Rect window_rect(bounds);
      gfx::Rect monitor_rect(mi.rcWork);
      gfx::Rect new_window_rect = window_rect.AdjustToFit(monitor_rect);
      if (!new_window_rect.Equals(window_rect)) {
        // Window doesn't fit on monitor, move and possibly resize.
        SetWindowPos(hwnd, 0, new_window_rect.x(), new_window_rect.y(),
                     new_window_rect.width(), new_window_rect.height(),
                     SWP_NOACTIVATE | SWP_NOZORDER);
        return;
      }
      // Else fall through.
    } else {
      NOTREACHED() << "Unable to find default monitor";
      // Fall through.
    }
  }  // Else fall through.

  // The window is not being fit to monitor, or the window fits on the monitor
  // as is, or we have no monitor info; reset the bounds.
  ::SetWindowPos(hwnd, 0, bounds.left, bounds.top,
                 bounds.right - bounds.left, bounds.bottom - bounds.top,
                 SWP_NOACTIVATE | SWP_NOZORDER);
}

}  // namespace

string16 GetClassName(HWND window) {
  // GetClassNameW will return a truncated result (properly null terminated) if
  // the given buffer is not large enough.  So, it is not possible to determine
  // that we got the entire class name if the result is exactly equal to the
  // size of the buffer minus one.
  DWORD buffer_size = MAX_PATH;
  while (true) {
    std::wstring output;
    DWORD size_ret =
        GetClassNameW(window, WriteInto(&output, buffer_size), buffer_size);
    if (size_ret == 0)
      break;
    if (size_ret < (buffer_size - 1)) {
      output.resize(size_ret);
      return output;
    }
    buffer_size *= 2;
  }
  return std::wstring();  // error
}

#pragma warning(push)
#pragma warning(disable:4312 4244)

WNDPROC SetWindowProc(HWND hwnd, WNDPROC proc) {
  // The reason we don't return the SetwindowLongPtr() value is that it returns
  // the orignal window procedure and not the current one. I don't know if it is
  // a bug or an intended feature.
  WNDPROC oldwindow_proc =
      reinterpret_cast<WNDPROC>(GetWindowLongPtr(hwnd, GWLP_WNDPROC));
  SetWindowLongPtr(hwnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(proc));
  return oldwindow_proc;
}

void* SetWindowUserData(HWND hwnd, void* user_data) {
  return
      reinterpret_cast<void*>(SetWindowLongPtr(hwnd, GWLP_USERDATA,
          reinterpret_cast<LONG_PTR>(user_data)));
}

void* GetWindowUserData(HWND hwnd) {
  DWORD process_id = 0;
  DWORD thread_id = GetWindowThreadProcessId(hwnd, &process_id);
  // A window outside the current process needs to be ignored.
  if (process_id != ::GetCurrentProcessId())
    return NULL;
  return reinterpret_cast<void*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
}

#pragma warning(pop)

bool DoesWindowBelongToActiveWindow(HWND window) {
  DCHECK(window);
  HWND top_window = ::GetAncestor(window, GA_ROOT);
  if (!top_window)
    return false;

  HWND active_top_window = ::GetAncestor(::GetForegroundWindow(), GA_ROOT);
  return (top_window == active_top_window);
}

void CenterAndSizeWindow(HWND parent,
                         HWND window,
                         const gfx::Size& pref) {
  DCHECK(window && pref.width() > 0 && pref.height() > 0);

  // Calculate the ideal bounds.
  RECT window_bounds;
  RECT center_bounds = {0};
  if (parent) {
    // If there is a parent, center over the parents bounds.
    ::GetWindowRect(parent, &center_bounds);
  }

  if (::IsRectEmpty(&center_bounds)) {
    // No parent or no parent rect. Center over the monitor the window is on.
    HMONITOR monitor = MonitorFromWindow(window, MONITOR_DEFAULTTONEAREST);
    if (monitor) {
      MONITORINFO mi = {0};
      mi.cbSize = sizeof(mi);
      GetMonitorInfo(monitor, &mi);
      center_bounds = mi.rcWork;
    } else {
      NOTREACHED() << "Unable to get default monitor";
    }
  }

  window_bounds.left = center_bounds.left;
  if (pref.width() < (center_bounds.right - center_bounds.left)) {
    window_bounds.left +=
        (center_bounds.right - center_bounds.left - pref.width()) / 2;
  }
  window_bounds.right = window_bounds.left + pref.width();

  window_bounds.top = center_bounds.top;
  if (pref.height() < (center_bounds.bottom - center_bounds.top)) {
    window_bounds.top +=
        (center_bounds.bottom - center_bounds.top - pref.height()) / 2;
  }
  window_bounds.bottom = window_bounds.top + pref.height();

  // If we're centering a child window, we are positioning in client
  // coordinates, and as such we need to offset the target rectangle by the
  // position of the parent window.
  if (::GetWindowLong(window, GWL_STYLE) & WS_CHILD) {
    DCHECK(parent && ::GetParent(window) == parent);
    POINT topleft = { window_bounds.left, window_bounds.top };
    ::MapWindowPoints(HWND_DESKTOP, parent, &topleft, 1);
    window_bounds.left = topleft.x;
    window_bounds.top = topleft.y;
    window_bounds.right = window_bounds.left + pref.width();
    window_bounds.bottom = window_bounds.top + pref.height();
  }

  AdjustWindowToFit(window, window_bounds, !parent);
}

void CheckWindowCreated(HWND hwnd) {
  if (!hwnd)
    LOG_GETLASTERROR(FATAL);
}

void ShowSystemMenu(HWND window, int screen_x, int screen_y) {
  UINT flags = TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RETURNCMD;
  if (base::i18n::IsRTL())
    flags |= TPM_RIGHTALIGN;
  HMENU system_menu = GetSystemMenu(window, FALSE);
  int command = TrackPopupMenu(system_menu, flags, screen_x, screen_y, 0,
                               window, NULL);
  if (command)
    SendMessage(window, WM_SYSCOMMAND, command, 0);
}

}  // namespace ui
<|endoftext|>