<commit_before>/*
	Copyright (c) 2014, Madd Games.
	All rights reserved.

	Redistribution and use in source and binary forms, with or without
	modification, are permitted provided that the following conditions are met:

	* Redistributions of source code must retain the above copyright notice, this
	  list of conditions and the following disclaimer.

	* Redistributions in binary form must reproduce the above copyright notice,
	  this list of conditions and the following disclaimer in the documentation
	  and/or other materials provided with the distribution.

	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
	AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
	IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
	DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
	FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
	DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
	SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
	CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
	OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
	OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <Apoc/Video/StandardRenderHandler.h>
#include <Apoc/Entity/World.h>
#include <Apoc/Utils/Utils.h>

// Texture units:
// 0 = main (diffuse) texture
// 1 = directional light array
// 2 = point light array
// 3 = shadow map
// 4 = specular map
// 5 = normal map

extern "C" const char *stdVertexShader;
extern "C" const char *stdFragmentShader;
float lmatheight = -0.3;

const float defImageTexData[] = {
	0.3, 0.3, 1.0, 1.0,		1.0, 1.0, 1.0, 1.0,
	1.0, 1.0, 1.0, 1.0,		0.3, 0.3, 1.0, 1.0
};

const float defSpecularMapData[] = {
	1.0, 1.0, 1.0, 1.0
};

const float defNormalMapData[] = {
	0.5, 0.5, 1.0, 0.0
};

StandardRenderHandler::StandardRenderHandler(int screenWidth, int screenHeight)
	: numDirLights(0), numPointLights(0), screenWidth(screenWidth), screenHeight(screenHeight)
{
	renderProgram = createProgram(stdVertexShader, stdFragmentShader);

	// set up the directional light array buffer.
	glActiveTexture(GL_TEXTURE1);
	glGenTextures(1, &dirLightTex);
	glBindTexture(GL_TEXTURE_BUFFER, dirLightTex);
	glGenBuffers(1, &dirLightBuffer);
	glBindBuffer(GL_TEXTURE_BUFFER, dirLightBuffer);
	glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, dirLightBuffer);

	// set up the point light array buffer.
	glActiveTexture(GL_TEXTURE2);
	glGenTextures(1, &pointLightTex);
	glBindTexture(GL_TEXTURE_BUFFER, pointLightTex);
	glGenBuffers(1, &pointLightBuffer);
	glBindBuffer(GL_TEXTURE_BUFFER, pointLightBuffer);
	glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, pointLightBuffer);

	// default image texture.
	glGenTextures(1, &defImageTex);
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, defImageTex);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_FLOAT, defImageTexData);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

	// default specular map.
	glGenTextures(1, &defSpecularMap);
	glActiveTexture(GL_TEXTURE4);
	glBindTexture(GL_TEXTURE_2D, defSpecularMap);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_FLOAT, defSpecularMapData);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

	// default normal map.
	glGenTextures(1, &defNormalMap);
	glActiveTexture(GL_TEXTURE5);
	glBindTexture(GL_TEXTURE_2D, defNormalMap);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_FLOAT, defNormalMapData);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

	// the shadowmap framebuffer
	glGenFramebuffers(1, &shadowFramebuffer);
	glGenTextures(1, &shadowTex);
	glBindTexture(GL_TEXTURE_2D, shadowTex);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, 1366, 768, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);

	glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer);
	glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, shadowTex, 0);
	if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
	{
		ApocFail("The shadowmap framebuffer is incomplete!");
	};

	Matrix view = Matrix::LookAt(
		Vector(0.0, -0.1, -1.0),
		Vector(0.0, 1.0, 0.0),
		Vector(0.0, 0.0, 0.0)
	);
	lightMatrix = Matrix::Ortho(20, -20, 20, -20, -30, 20) * view;
	//cout << "Light matrix: " << endl << lightMatrix << endl;

	//Vector point(-11.000000, 0.000000, 10.999980, 1);
	//cout << "Test point: " << (lightMatrix * point) << endl;
};

void StandardRenderHandler::render()
{
	Matrix view = Matrix::LookAt(
		Vector(0.0, lmatheight, -1.0),
		Vector(0.0, 1.0, 0.0),
		Vector(0.0, 0.0, 0.0)
	);
	lightMatrix = Matrix::Ortho(20, -20, 20, -20, -20, 10) * view;

	//glDepthFunc(GL_LESS);
	glUniform1i(getUniformLocation("uIsParticle"), 0);
	glBindFramebuffer(GL_FRAMEBUFFER, 0);
	glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer);
	glViewport(0, 0, 1366, 768);
	glClearColor(0.0, 0.0, 0.0, 1.0);
	glClear(GL_DEPTH_BUFFER_BIT);
	glUniform1i(getUniformLocation("uIsShadowMap"), 1);
	glDrawBuffer(GL_NONE);
	Matrix identity = Matrix::Identity();
	glUniformMatrix4fv(getUniformLocation("uProjectionMatrix"), 1, GL_FALSE, &identity[0][0]);
	glUniformMatrix4fv(getUniformLocation("uViewMatrix"), 1, GL_FALSE, &lightMatrix[0][0]);
	World::render(false);
	//return;

	glBindFramebuffer(GL_FRAMEBUFFER, 0);
	glViewport(0, 0, screenWidth, screenHeight);
	//glUseProgram(renderProgram);
	glDrawBuffer(GL_BACK);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glUniformMatrix4fv(getUniformLocation("uLightMatrix"), 1, GL_FALSE, &lightMatrix[0][0]);
	glUniform1i(getUniformLocation("uIsShadowMap"), 0);
	glUniform4f(getUniformLocation("uAmbientLight"), 0.1, 0.1, 0.1, 1.0);
	glUniform1i(getUniformLocation("uDirLightArray"), 1);
	glUniform1i(getUniformLocation("uPointLightArray"), 2);
	glUniform1i(getUniformLocation("uShadowMap"), 3);
	glUniform1i(getUniformLocation("uSpecularMap"), 4);
	glUniform1i(getUniformLocation("uNormalMap"), 5);
	glUniform1i(getUniformLocation("uNumDirLights"), numDirLights);
	glUniform1i(getUniformLocation("uNumPointLights"), numPointLights);
	glActiveTexture(GL_TEXTURE3);
	glBindTexture(GL_TEXTURE_2D, shadowTex);
	glEnable(GL_CULL_FACE);
	World::render();

	glUniformMatrix4fv(getUniformLocation("uModelMatrix"), 1, GL_FALSE, &identity[0][0]);
	glUniformMatrix4fv(getUniformLocation("uObjectMatrix"), 1, GL_FALSE, &identity[0][0]);
	glUniform1i(getUniformLocation("uIsParticle"), 1);
	World::renderParticles();
};

void StandardRenderHandler::getAttrLocations(GLint &attrVertex, GLint &attrTexCoords, GLint &attrNormal)
{
	attrVertex = glGetAttribLocation(renderProgram, "inVertex");
	attrTexCoords = glGetAttribLocation(renderProgram, "inTexCoords");
	attrNormal = glGetAttribLocation(renderProgram, "inNormal");
};

GLint StandardRenderHandler::getUniformLocation(const char *name)
{
	return glGetUniformLocation(renderProgram, name);
};

GLint StandardRenderHandler::getAttrLocation(const char *name)
{
	return glGetAttribLocation(renderProgram, name);
};

void StandardRenderHandler::bindProgram()
{
	glUseProgram(renderProgram);
	glUniform4f(getUniformLocation("uAmbientLight"), 0.1, 0.1, 0.1, 1.0);
};

void StandardRenderHandler::setDirLights(RenderHandler::DirLight *array, int count)
{
	glBindBuffer(GL_TEXTURE_BUFFER, dirLightBuffer);
	glBufferData(GL_TEXTURE_BUFFER, sizeof(RenderHandler::DirLight)*count, array, GL_DYNAMIC_COPY);
	numDirLights = count;
};

void StandardRenderHandler::setPointLights(RenderHandler::PointLight *array, int count)
{
	glBindBuffer(GL_TEXTURE_BUFFER, pointLightBuffer);
	glBufferData(GL_TEXTURE_BUFFER, sizeof(RenderHandler::PointLight)*count, array, GL_DYNAMIC_COPY);
	numPointLights = count;
};

void StandardRenderHandler::bindDefaultTextures()
{
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, defImageTex);
	glActiveTexture(GL_TEXTURE4);
	glBindTexture(GL_TEXTURE_2D, defSpecularMap);
	glActiveTexture(GL_TEXTURE5);
	glBindTexture(GL_TEXTURE_2D, defNormalMap);
};
<commit_msg>Comment cleanup<commit_after>/*
	Copyright (c) 2014, Madd Games.
	All rights reserved.

	Redistribution and use in source and binary forms, with or without
	modification, are permitted provided that the following conditions are met:

	* Redistributions of source code must retain the above copyright notice, this
	  list of conditions and the following disclaimer.

	* Redistributions in binary form must reproduce the above copyright notice,
	  this list of conditions and the following disclaimer in the documentation
	  and/or other materials provided with the distribution.

	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
	AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
	IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
	DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
	FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
	DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
	SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
	CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
	OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
	OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <Apoc/Video/StandardRenderHandler.h>
#include <Apoc/Entity/World.h>
#include <Apoc/Utils/Utils.h>

// Texture units:
// 0 = main (diffuse) texture
// 1 = directional light array
// 2 = point light array
// 3 = shadow map
// 4 = specular map
// 5 = normal map

extern "C" const char *stdVertexShader;
extern "C" const char *stdFragmentShader;
float lmatheight = -0.3;

const float defImageTexData[] = {
	0.3, 0.3, 1.0, 1.0,		1.0, 1.0, 1.0, 1.0,
	1.0, 1.0, 1.0, 1.0,		0.3, 0.3, 1.0, 1.0
};

const float defSpecularMapData[] = {
	1.0, 1.0, 1.0, 1.0
};

const float defNormalMapData[] = {
	0.5, 0.5, 1.0, 0.0
};

StandardRenderHandler::StandardRenderHandler(int screenWidth, int screenHeight)
	: numDirLights(0), numPointLights(0), screenWidth(screenWidth), screenHeight(screenHeight)
{
	renderProgram = createProgram(stdVertexShader, stdFragmentShader);

	// set up the directional light array buffer.
	glActiveTexture(GL_TEXTURE1);
	glGenTextures(1, &dirLightTex);
	glBindTexture(GL_TEXTURE_BUFFER, dirLightTex);
	glGenBuffers(1, &dirLightBuffer);
	glBindBuffer(GL_TEXTURE_BUFFER, dirLightBuffer);
	glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, dirLightBuffer);

	// set up the point light array buffer.
	glActiveTexture(GL_TEXTURE2);
	glGenTextures(1, &pointLightTex);
	glBindTexture(GL_TEXTURE_BUFFER, pointLightTex);
	glGenBuffers(1, &pointLightBuffer);
	glBindBuffer(GL_TEXTURE_BUFFER, pointLightBuffer);
	glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, pointLightBuffer);

	// default image texture.
	glGenTextures(1, &defImageTex);
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, defImageTex);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_FLOAT, defImageTexData);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

	// default specular map.
	glGenTextures(1, &defSpecularMap);
	glActiveTexture(GL_TEXTURE4);
	glBindTexture(GL_TEXTURE_2D, defSpecularMap);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_FLOAT, defSpecularMapData);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

	// default normal map.
	glGenTextures(1, &defNormalMap);
	glActiveTexture(GL_TEXTURE5);
	glBindTexture(GL_TEXTURE_2D, defNormalMap);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_FLOAT, defNormalMapData);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

	// the shadowmap framebuffer
	glGenFramebuffers(1, &shadowFramebuffer);
	glGenTextures(1, &shadowTex);
	glBindTexture(GL_TEXTURE_2D, shadowTex);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, 1366, 768, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);

	glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer);
	glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, shadowTex, 0);
	if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
	{
		ApocFail("The shadowmap framebuffer is incomplete!");
	};

	Matrix view = Matrix::LookAt(
		Vector(0.0, -0.1, -1.0),
		Vector(0.0, 1.0, 0.0),
		Vector(0.0, 0.0, 0.0)
	);
	lightMatrix = Matrix::Ortho(20, -20, 20, -20, -30, 20) * view;
	//cout << "Light matrix: " << endl << lightMatrix << endl;

	//Vector point(-11.000000, 0.000000, 10.999980, 1);
	//cout << "Test point: " << (lightMatrix * point) << endl;
};

void StandardRenderHandler::render()
{
	Matrix view = Matrix::LookAt(
		Vector(0.0, lmatheight, -1.0),
		Vector(0.0, 1.0, 0.0),
		Vector(0.0, 0.0, 0.0)
	);
	lightMatrix = Matrix::Ortho(20, -20, 20, -20, -20, 10) * view;

	glUniform1i(getUniformLocation("uIsParticle"), 0);
	glBindFramebuffer(GL_FRAMEBUFFER, 0);
	glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer);
	glViewport(0, 0, 1366, 768);
	glClearColor(0.0, 0.0, 0.0, 1.0);
	glClear(GL_DEPTH_BUFFER_BIT);
	glUniform1i(getUniformLocation("uIsShadowMap"), 1);
	glDrawBuffer(GL_NONE);
	Matrix identity = Matrix::Identity();
	glUniformMatrix4fv(getUniformLocation("uProjectionMatrix"), 1, GL_FALSE, &identity[0][0]);
	glUniformMatrix4fv(getUniformLocation("uViewMatrix"), 1, GL_FALSE, &lightMatrix[0][0]);
	World::render(false);

	glBindFramebuffer(GL_FRAMEBUFFER, 0);
	glViewport(0, 0, screenWidth, screenHeight);
	glDrawBuffer(GL_BACK);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glUniformMatrix4fv(getUniformLocation("uLightMatrix"), 1, GL_FALSE, &lightMatrix[0][0]);
	glUniform1i(getUniformLocation("uIsShadowMap"), 0);
	glUniform4f(getUniformLocation("uAmbientLight"), 0.1, 0.1, 0.1, 1.0);
	glUniform1i(getUniformLocation("uDirLightArray"), 1);
	glUniform1i(getUniformLocation("uPointLightArray"), 2);
	glUniform1i(getUniformLocation("uShadowMap"), 3);
	glUniform1i(getUniformLocation("uSpecularMap"), 4);
	glUniform1i(getUniformLocation("uNormalMap"), 5);
	glUniform1i(getUniformLocation("uNumDirLights"), numDirLights);
	glUniform1i(getUniformLocation("uNumPointLights"), numPointLights);
	glActiveTexture(GL_TEXTURE3);
	glBindTexture(GL_TEXTURE_2D, shadowTex);
	glEnable(GL_CULL_FACE);
	World::render();

	glUniformMatrix4fv(getUniformLocation("uModelMatrix"), 1, GL_FALSE, &identity[0][0]);
	glUniformMatrix4fv(getUniformLocation("uObjectMatrix"), 1, GL_FALSE, &identity[0][0]);
	glUniform1i(getUniformLocation("uIsParticle"), 1);
	World::renderParticles();
};

void StandardRenderHandler::getAttrLocations(GLint &attrVertex, GLint &attrTexCoords, GLint &attrNormal)
{
	attrVertex = glGetAttribLocation(renderProgram, "inVertex");
	attrTexCoords = glGetAttribLocation(renderProgram, "inTexCoords");
	attrNormal = glGetAttribLocation(renderProgram, "inNormal");
};

GLint StandardRenderHandler::getUniformLocation(const char *name)
{
	return glGetUniformLocation(renderProgram, name);
};

GLint StandardRenderHandler::getAttrLocation(const char *name)
{
	return glGetAttribLocation(renderProgram, name);
};

void StandardRenderHandler::bindProgram()
{
	glUseProgram(renderProgram);
	glUniform4f(getUniformLocation("uAmbientLight"), 0.1, 0.1, 0.1, 1.0);
};

void StandardRenderHandler::setDirLights(RenderHandler::DirLight *array, int count)
{
	glBindBuffer(GL_TEXTURE_BUFFER, dirLightBuffer);
	glBufferData(GL_TEXTURE_BUFFER, sizeof(RenderHandler::DirLight)*count, array, GL_DYNAMIC_COPY);
	numDirLights = count;
};

void StandardRenderHandler::setPointLights(RenderHandler::PointLight *array, int count)
{
	glBindBuffer(GL_TEXTURE_BUFFER, pointLightBuffer);
	glBufferData(GL_TEXTURE_BUFFER, sizeof(RenderHandler::PointLight)*count, array, GL_DYNAMIC_COPY);
	numPointLights = count;
};

void StandardRenderHandler::bindDefaultTextures()
{
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, defImageTex);
	glActiveTexture(GL_TEXTURE4);
	glBindTexture(GL_TEXTURE_2D, defSpecularMap);
	glActiveTexture(GL_TEXTURE5);
	glBindTexture(GL_TEXTURE_2D, defNormalMap);
};
<|endoftext|>


<commit_before>#include "../../../inc/slib/core/definition.h"

#if defined(SLIB_PLATFORM_IS_ANDROID)

#include "../../../inc/slib/ui/core.h"

#include "../../../inc/slib/ui/screen.h"
#include "../../../inc/slib/ui/platform.h"
#include "../../../inc/slib/ui/mobile_app.h"
#include "../../../inc/slib/core/map.h"
#include "../../../inc/slib/core/io.h"
#include "../../../inc/slib/core/log.h"
#include "../../../inc/slib/core/safe_static.h"

SLIB_UI_NAMESPACE_BEGIN

SLIB_JNI_BEGIN_CLASS(_JAndroidPoint, "android/graphics/Point")
	SLIB_JNI_INT_FIELD(x);
	SLIB_JNI_INT_FIELD(y);
SLIB_JNI_END_CLASS

SLIB_JNI_BEGIN_CLASS(_AndroidUtil, "slib/platform/android/ui/Util")
	SLIB_JNI_STATIC_METHOD(getDefaultDisplay, "getDefaultDisplay", "(Lslib/platform/android/SlibActivity;)Landroid/view/Display;");
	SLIB_JNI_STATIC_METHOD(getDisplaySize, "getDisplaySize", "(Landroid/view/Display;)Landroid/graphics/Point;");
	SLIB_JNI_STATIC_METHOD(openURL, "openURL", "(Lslib/platform/android/SlibActivity;Landroid/view/View;[Ljava/lang/String;)V");
SLIB_JNI_END_CLASS

void _AndroidUiThread_runDispatchCallback(JNIEnv* env, jobject _this);

SLIB_JNI_BEGIN_CLASS(_AndroidUiThread, "slib/platform/android/ui/UiThread")
	SLIB_JNI_STATIC_METHOD(isUiThread, "isUiThread", "()Z");
	SLIB_JNI_STATIC_METHOD(dispatch, "dispatch", "()V");
	SLIB_JNI_STATIC_METHOD(runLoop, "runLoop", "()V");
	SLIB_JNI_STATIC_METHOD(quitLoop, "quitLoop", "()V");

	SLIB_JNI_NATIVE(nativeDispatchCallback, "nativeDispatchCallback", "()V", _AndroidUiThread_runDispatchCallback);
SLIB_JNI_END_CLASS

void _Android_onCreateActivity(JNIEnv* env, jobject _this, jobject activity);
void _Android_onDestroyActivity(JNIEnv* env, jobject _this, jobject activity);
void _Android_onResumeActivity(JNIEnv* env, jobject _this, jobject activity);
void _Android_onPauseActivity(JNIEnv* env, jobject _this, jobject activity);
jboolean _Android_onBack(JNIEnv* env, jobject _this, jobject activity);

SLIB_JNI_BEGIN_CLASS(_Android, "slib/platform/android/Android")
	SLIB_JNI_NATIVE(onCreateActivity, "nativeOnCreateActivity", "(Landroid/app/Activity;)V", _Android_onCreateActivity);
	SLIB_JNI_NATIVE(onDestroyActivity, "nativeOnDestnativeOnResumeActivityroyActivity", "(Landroid/app/Activity;)V", _Android_onDestroyActivity);
	SLIB_JNI_NATIVE(onResumeActivity, "", "(Landroid/app/Activity;)V", _Android_onResumeActivity);
	SLIB_JNI_NATIVE(onPauseActivity, "nativeOnPauseActivity", "(Landroid/app/Activity;)V", _Android_onPauseActivity);
	SLIB_JNI_NATIVE(onBack, "nativeOnBack", "(Landroid/app/Activity;)Z", _Android_onBack);
SLIB_JNI_END_CLASS

class _Android_Screen : public Screen
{
public:
	JniGlobal<jobject> m_display;
	int m_width;
	int m_height;

public:
	static Ref<_Android_Screen> create(jobject display)
	{
		Ref<_Android_Screen> ret;
		if (display) {
			JniLocal<jobject> size = _AndroidUtil::getDisplaySize.callObject(sl_null, display);
			if (size.isNotNull()) {
				ret = new _Android_Screen();
				if (ret.isNotNull()) {
					ret->m_display = display;
					ret->m_width = _JAndroidPoint::x.get(size);
					ret->m_height = _JAndroidPoint::y.get(size);
				}
			}
		}
		return ret;
	}

public:
    // override
	UIRect getRegion()
	{
		UIRect ret;
		ret.left = 0;
		ret.top = 0;
		ret.right = (sl_ui_pos)m_width;
		ret.bottom = (sl_ui_pos)m_height;
		return ret;
	}
};

Ref<Screen> UI::getPrimaryScreen()
{
	SLIB_STATIC_ZERO_INITIALIZED(SafeRef<Screen>, ret)
	if (SLIB_SAFE_STATIC_CHECK_FREED(ret)) {
		return Ref<Screen>::null();
	}
	if (ret.isNull()) {
		jobject jactivity = Android::getCurrentActivity();
		if (jactivity) {
			JniLocal<jobject> display = _AndroidUtil::getDefaultDisplay.callObject(sl_null, jactivity);
			ret = _Android_Screen::create(display);
		}
	}
	return ret;
}

Ref<Screen> UI::getFocusedScreen()
{
	return UI::getPrimaryScreen();
}

List< Ref<Screen> > UI::getScreens()
{
	List< Ref<Screen> > ret;
	Ref<Screen> screen = UI::getPrimaryScreen();
	if (screen.isNotNull()) {
		ret.add(screen);
	}
	return ret;
}

void UI::openURL(String url) {
	jobject jactivity = Android::getCurrentActivity();
	if (jactivity) {
		JniLocal<jstring> jurl = Jni::getJniString(url);
		_AndroidUtil::openURL(jactivity, jurl);
	}

}

sl_bool UI::isUiThread()
{
	return _AndroidUiThread::isUiThread.callBoolean(sl_null) != 0;
}

SLIB_SAFE_STATIC_GETTER(Queue<Callback>, _AndroidUi_getDispatchQueue);

void UI::dispatchToUiThread(const Callback& callback)
{
	if (callback.isNotNull()) {
		Queue<Callback>* queue = _AndroidUi_getDispatchQueue();
		if (queue) {
			queue->push(callback);
			_AndroidUiThread::dispatch.call(sl_null);
		}
	}
}

void _AndroidUiThread_runDispatchCallback(JNIEnv* env, jobject _this)
{
	Queue<Callback>* queue = _AndroidUi_getDispatchQueue();
	if (queue) {
		Callback callback;
		while (queue->pop(&callback)) {
			callback();
		}
	}
}

void UIPlatform::runLoop(sl_uint32 level)
{
	_AndroidUiThread::runLoop.call(sl_null);
}

void UIPlatform::quitLoop()
{
	_AndroidUiThread::quitLoop.call(sl_null);
}

static Ref<UIApp> _g_mobile_app;
void UIPlatform::runApp()
{
	_g_mobile_app = UIApp::getApp();
}

void UIPlatform::quitApp()
{
}

void _Android_onCreateActivity(JNIEnv* env, jobject _this, jobject activity)
{
	SLIB_LOG("Activity", "Created");
	Android::setCurrentActivity(activity);
	Ref<UIApp> app = UIApp::getApp();
	if (app.isNotNull()) {
		static sl_bool flagStartApp = sl_false;
		if (! flagStartApp) {
			flagStartApp = sl_true;
			UIApp::dispatchStartToApp();
		}
		MobileApp::dispatchCreateActivityToApp();
	}
}

void _Android_onDestroyActivity(JNIEnv* env, jobject _this, jobject activity)
{
	SLIB_LOG("Activity", "Destroyed");
	MobileApp::dispatchDestroyActivityToApp();
}

void _Android_onResumeActivity(JNIEnv* env, jobject _this, jobject activity)
{
	SLIB_LOG("Activity", "Resumed");
	Android::setCurrentActivity(activity);
	MobileApp::dispatchResumeToApp();
}

void _Android_onPauseActivity(JNIEnv* env, jobject _this, jobject activity)
{
	SLIB_LOG("Activity", "Paused");
	MobileApp::dispatchPauseToApp();
}

jboolean _Android_onBack(JNIEnv* env, jobject _this, jobject activity)
{
	SLIB_LOG("Activity", "BackPressed");
	return (jboolean)(MobileApp::dispatchBackToApp());
}

SLIB_UI_NAMESPACE_END

#endif
<commit_msg>Minor fixes<commit_after>#include "../../../inc/slib/core/definition.h"

#if defined(SLIB_PLATFORM_IS_ANDROID)

#include "../../../inc/slib/ui/core.h"

#include "../../../inc/slib/ui/screen.h"
#include "../../../inc/slib/ui/platform.h"
#include "../../../inc/slib/ui/mobile_app.h"
#include "../../../inc/slib/core/map.h"
#include "../../../inc/slib/core/io.h"
#include "../../../inc/slib/core/log.h"
#include "../../../inc/slib/core/safe_static.h"

SLIB_UI_NAMESPACE_BEGIN

SLIB_JNI_BEGIN_CLASS(_JAndroidPoint, "android/graphics/Point")
	SLIB_JNI_INT_FIELD(x);
	SLIB_JNI_INT_FIELD(y);
SLIB_JNI_END_CLASS

SLIB_JNI_BEGIN_CLASS(_AndroidUtil, "slib/platform/android/ui/Util")
	SLIB_JNI_STATIC_METHOD(getDefaultDisplay, "getDefaultDisplay", "(Lslib/platform/android/SlibActivity;)Landroid/view/Display;");
	SLIB_JNI_STATIC_METHOD(getDisplaySize, "getDisplaySize", "(Landroid/view/Display;)Landroid/graphics/Point;");
	SLIB_JNI_STATIC_METHOD(openURL, "openURL", "(Lslib/platform/android/SlibActivity;Landroid/view/View;Ljava/lang/String;)V");
SLIB_JNI_END_CLASS

void _AndroidUiThread_runDispatchCallback(JNIEnv* env, jobject _this);

SLIB_JNI_BEGIN_CLASS(_AndroidUiThread, "slib/platform/android/ui/UiThread")
	SLIB_JNI_STATIC_METHOD(isUiThread, "isUiThread", "()Z");
	SLIB_JNI_STATIC_METHOD(dispatch, "dispatch", "()V");
	SLIB_JNI_STATIC_METHOD(runLoop, "runLoop", "()V");
	SLIB_JNI_STATIC_METHOD(quitLoop, "quitLoop", "()V");

	SLIB_JNI_NATIVE(nativeDispatchCallback, "nativeDispatchCallback", "()V", _AndroidUiThread_runDispatchCallback);
SLIB_JNI_END_CLASS

void _Android_onCreateActivity(JNIEnv* env, jobject _this, jobject activity);
void _Android_onDestroyActivity(JNIEnv* env, jobject _this, jobject activity);
void _Android_onResumeActivity(JNIEnv* env, jobject _this, jobject activity);
void _Android_onPauseActivity(JNIEnv* env, jobject _this, jobject activity);
jboolean _Android_onBack(JNIEnv* env, jobject _this, jobject activity);

SLIB_JNI_BEGIN_CLASS(_Android, "slib/platform/android/Android")
	SLIB_JNI_NATIVE(onCreateActivity, "nativeOnCreateActivity", "(Landroid/app/Activity;)V", _Android_onCreateActivity);
	SLIB_JNI_NATIVE(onDestroyActivity, "nativeOnDestnativeOnResumeActivityroyActivity", "(Landroid/app/Activity;)V", _Android_onDestroyActivity);
	SLIB_JNI_NATIVE(onResumeActivity, "", "(Landroid/app/Activity;)V", _Android_onResumeActivity);
	SLIB_JNI_NATIVE(onPauseActivity, "nativeOnPauseActivity", "(Landroid/app/Activity;)V", _Android_onPauseActivity);
	SLIB_JNI_NATIVE(onBack, "nativeOnBack", "(Landroid/app/Activity;)Z", _Android_onBack);
SLIB_JNI_END_CLASS

class _Android_Screen : public Screen
{
public:
	JniGlobal<jobject> m_display;
	int m_width;
	int m_height;

public:
	static Ref<_Android_Screen> create(jobject display)
	{
		Ref<_Android_Screen> ret;
		if (display) {
			JniLocal<jobject> size = _AndroidUtil::getDisplaySize.callObject(sl_null, display);
			if (size.isNotNull()) {
				ret = new _Android_Screen();
				if (ret.isNotNull()) {
					ret->m_display = display;
					ret->m_width = _JAndroidPoint::x.get(size);
					ret->m_height = _JAndroidPoint::y.get(size);
				}
			}
		}
		return ret;
	}

public:
    // override
	UIRect getRegion()
	{
		UIRect ret;
		ret.left = 0;
		ret.top = 0;
		ret.right = (sl_ui_pos)m_width;
		ret.bottom = (sl_ui_pos)m_height;
		return ret;
	}
};

Ref<Screen> UI::getPrimaryScreen()
{
	SLIB_STATIC_ZERO_INITIALIZED(SafeRef<Screen>, ret)
	if (SLIB_SAFE_STATIC_CHECK_FREED(ret)) {
		return Ref<Screen>::null();
	}
	if (ret.isNull()) {
		jobject jactivity = Android::getCurrentActivity();
		if (jactivity) {
			JniLocal<jobject> display = _AndroidUtil::getDefaultDisplay.callObject(sl_null, jactivity);
			ret = _Android_Screen::create(display);
		}
	}
	return ret;
}

Ref<Screen> UI::getFocusedScreen()
{
	return UI::getPrimaryScreen();
}

List< Ref<Screen> > UI::getScreens()
{
	List< Ref<Screen> > ret;
	Ref<Screen> screen = UI::getPrimaryScreen();
	if (screen.isNotNull()) {
		ret.add(screen);
	}
	return ret;
}

void UI::openURL(String url) {
	jobject jactivity = Android::getCurrentActivity();
	if (jactivity) {
		JniLocal<jstring> jurl = Jni::getJniString(url);
		_AndroidUtil::openURL(jactivity, jurl);
	}

}

sl_bool UI::isUiThread()
{
	return _AndroidUiThread::isUiThread.callBoolean(sl_null) != 0;
}

SLIB_SAFE_STATIC_GETTER(Queue<Callback>, _AndroidUi_getDispatchQueue);

void UI::dispatchToUiThread(const Callback& callback)
{
	if (callback.isNotNull()) {
		Queue<Callback>* queue = _AndroidUi_getDispatchQueue();
		if (queue) {
			queue->push(callback);
			_AndroidUiThread::dispatch.call(sl_null);
		}
	}
}

void _AndroidUiThread_runDispatchCallback(JNIEnv* env, jobject _this)
{
	Queue<Callback>* queue = _AndroidUi_getDispatchQueue();
	if (queue) {
		Callback callback;
		while (queue->pop(&callback)) {
			callback();
		}
	}
}

void UIPlatform::runLoop(sl_uint32 level)
{
	_AndroidUiThread::runLoop.call(sl_null);
}

void UIPlatform::quitLoop()
{
	_AndroidUiThread::quitLoop.call(sl_null);
}

static Ref<UIApp> _g_mobile_app;
void UIPlatform::runApp()
{
	_g_mobile_app = UIApp::getApp();
}

void UIPlatform::quitApp()
{
}

void _Android_onCreateActivity(JNIEnv* env, jobject _this, jobject activity)
{
	SLIB_LOG("Activity", "Created");
	Android::setCurrentActivity(activity);
	Ref<UIApp> app = UIApp::getApp();
	if (app.isNotNull()) {
		static sl_bool flagStartApp = sl_false;
		if (! flagStartApp) {
			flagStartApp = sl_true;
			UIApp::dispatchStartToApp();
		}
		MobileApp::dispatchCreateActivityToApp();
	}
}

void _Android_onDestroyActivity(JNIEnv* env, jobject _this, jobject activity)
{
	SLIB_LOG("Activity", "Destroyed");
	MobileApp::dispatchDestroyActivityToApp();
}

void _Android_onResumeActivity(JNIEnv* env, jobject _this, jobject activity)
{
	SLIB_LOG("Activity", "Resumed");
	Android::setCurrentActivity(activity);
	MobileApp::dispatchResumeToApp();
}

void _Android_onPauseActivity(JNIEnv* env, jobject _this, jobject activity)
{
	SLIB_LOG("Activity", "Paused");
	MobileApp::dispatchPauseToApp();
}

jboolean _Android_onBack(JNIEnv* env, jobject _this, jobject activity)
{
	SLIB_LOG("Activity", "BackPressed");
	return (jboolean)(MobileApp::dispatchBackToApp());
}

SLIB_UI_NAMESPACE_END

#endif
<|endoftext|>


<commit_before>//
//  EmiPacketHeader.cc
//  rock
//
//  Created by Per Eckerdal on 2012-05-10.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#include "EmiPacketHeader.h"

#include "EmiNetUtil.h"

#include <cstring>
#include <algorithm>

inline static void extractFlagsAndSize(EmiPacketFlags flags,
                                       EmiPacketExtraFlags extraFlags,
                                       bool *hasSequenceNumber,
                                       bool *hasAck,
                                       bool *hasNak,
                                       bool *hasLinkCapacity,
                                       bool *hasArrivalRate,
                                       bool *hasRttRequest,
                                       bool *hasRttResponse,
                                       size_t *fillerSizePtr, // Can be NULL
                                       size_t *expectedSize) {
    size_t fillerSize = 0;

    *hasSequenceNumber = !!(flags & EMI_SEQUENCE_NUMBER_PACKET_FLAG);
    *hasAck            = !!(flags & EMI_ACK_PACKET_FLAG);
    *hasNak            = !!(flags & EMI_NAK_PACKET_FLAG);
    *hasLinkCapacity   = !!(flags & EMI_LINK_CAPACITY_PACKET_FLAG);
    *hasArrivalRate    = !!(flags & EMI_ARRIVAL_RATE_PACKET_FLAG);
    *hasRttRequest     = !!(flags & EMI_RTT_REQUEST_PACKET_FLAG);
    *hasRttResponse    = !!(flags & EMI_RTT_RESPONSE_PACKET_FLAG);
    bool hasExtraFlags = !!(flags & EMI_EXTRA_FLAGS_PACKET_FLAG);

    // 1 for the flags byte
    *expectedSize = sizeof(EmiPacketFlags);

    if (hasExtraFlags) {
        *expectedSize += sizeof(EmiPacketExtraFlags);

        if (flags & EMI_1_BYTE_FILLER_EXTRA_PACKET_FLAG) {
            fillerSize = 1;
        }
        else if (flags & EMI_2_BYTE_FILLER_EXTRA_PACKET_FLAG) {
            fillerSize = 2;
        }
        else {
            fillerSize = 0;
        }

        *expectedSize += fillerSize;
    }

    if (fillerSizePtr) {
        *fillerSizePtr = fillerSize;
    }

    *expectedSize += (*hasSequenceNumber ? EMI_PACKET_SEQUENCE_NUMBER_LENGTH : 0);
    *expectedSize += (*hasAck            ? EMI_PACKET_SEQUENCE_NUMBER_LENGTH : 0);
    *expectedSize += (*hasNak            ? EMI_PACKET_SEQUENCE_NUMBER_LENGTH : 0);
    *expectedSize += (*hasLinkCapacity   ? sizeof(float) : 0);
    *expectedSize += (*hasArrivalRate    ? sizeof(float) : 0);
    *expectedSize += (*hasRttResponse    ? EMI_PACKET_SEQUENCE_NUMBER_LENGTH+sizeof(uint8_t) : 0);
}

EmiPacketHeader::EmiPacketHeader() :
flags(0),
sequenceNumber(0),
ack(0),
nak(0),
linkCapacity(0),
arrivalRate(0),
rttResponse(0),
rttResponseDelay(0) {}

EmiPacketHeader::~EmiPacketHeader() {}

bool EmiPacketHeader::parse(const uint8_t *buf, size_t bufSize, EmiPacketHeader *header, size_t *headerLength) {
    if (0 >= bufSize) {
        return false;
    }

    EmiPacketFlags flags = buf[0];

    EmiPacketExtraFlags extraFlags = (EmiPacketExtraFlags) 0;
    if (bufSize >= 1) {
        extraFlags = (EmiPacketExtraFlags) buf[1];
    }

    bool hasSequenceNumber, hasAck, hasNak, hasLinkCapacity;
    bool hasArrivalRate, hasRttRequest, hasRttResponse;
    size_t expectedSize, fillerSize;
    extractFlagsAndSize(flags,
                        extraFlags,
                        &hasSequenceNumber,
                        &hasAck,
                        &hasNak,
                        &hasLinkCapacity,
                        &hasArrivalRate,
                        &hasRttRequest,
                        &hasRttResponse,
                        &fillerSize,
                        &expectedSize);

    if (2 == fillerSize) {
        // A 2 byte filler size means that the packet contains a 16 bit
        // unsigned integer which specifies padding
        if (4 > bufSize) {
            return false;
        }
        uint16_t twoByteFillerSize = ntohs(*((uint16_t *)(buf+2)));
        fillerSize += twoByteFillerSize;
        expectedSize += twoByteFillerSize;
    }

    if (bufSize < expectedSize) {
        return false;
    }

    header->flags = flags;
    header->sequenceNumber = 0;
    header->ack = 0;
    header->nak = 0;
    header->linkCapacity = 0.0f;
    header->arrivalRate = 0.0f;
    header->rttResponse = 0;
    header->rttResponseDelay = 0;

    const uint8_t *bufCur = buf+sizeof(header->flags);

    if (flags & EMI_EXTRA_FLAGS_PACKET_FLAG) {
        bufCur += sizeof(EmiPacketExtraFlags);
        bufCur += fillerSize;
    }

    if (hasSequenceNumber) {
        header->sequenceNumber = EmiNetUtil::read24(bufCur);
        bufCur += EMI_PACKET_SEQUENCE_NUMBER_LENGTH;
    }

    if (hasAck) {
        header->ack = EmiNetUtil::read24(bufCur);
        bufCur += EMI_PACKET_SEQUENCE_NUMBER_LENGTH;
    }

    if (hasNak) {
        header->nak = EmiNetUtil::read24(bufCur);
        bufCur += EMI_PACKET_SEQUENCE_NUMBER_LENGTH;
    }

    if (hasLinkCapacity) {
        uint32_t linkCapacityInt = ntohl(*reinterpret_cast<const uint32_t *>(bufCur));
        header->linkCapacity = *reinterpret_cast<float *>(&linkCapacityInt);
        bufCur += sizeof(header->linkCapacity);
    }

    if (hasArrivalRate) {
        uint32_t arrivalRateInt = ntohl(*reinterpret_cast<const uint32_t *>(bufCur));
        header->arrivalRate = *reinterpret_cast<float *>(&arrivalRateInt);
        bufCur += sizeof(header->arrivalRate);
    }

    if (hasRttResponse) {
        header->rttResponse = EmiNetUtil::read24(bufCur);
        bufCur += EMI_PACKET_SEQUENCE_NUMBER_LENGTH;

        header->rttResponseDelay = *bufCur;
        bufCur += sizeof(header->rttResponseDelay);
    }

    if (headerLength) {
        *headerLength = expectedSize;
    }

    return true;
}

bool EmiPacketHeader::write(uint8_t *buf, size_t bufSize, const EmiPacketHeader& header, size_t *headerLength) {
    if (0 >= bufSize) {
        return false;
    }

    bool hasSequenceNumber, hasAck, hasNak, hasLinkCapacity;
    bool hasArrivalRate, hasRttRequest, hasRttResponse;
    size_t expectedSize;
    extractFlagsAndSize(header.flags,
                        (EmiPacketExtraFlags)0,
                        &hasSequenceNumber,
                        &hasAck,
                        &hasNak,
                        &hasLinkCapacity,
                        &hasArrivalRate,
                        &hasRttRequest,
                        &hasRttResponse,
                        /*fillerSize:*/NULL,
                        &expectedSize);

    if (bufSize < expectedSize) {
        return false;
    }

    memset(buf, 0, expectedSize);
    buf[0] = header.flags;

    uint8_t *bufCur = buf+sizeof(EmiPacketFlags);

    if (hasSequenceNumber) {
        EmiNetUtil::write24(bufCur, header.sequenceNumber);
        bufCur += EMI_PACKET_SEQUENCE_NUMBER_LENGTH;
    }

    if (hasAck) {
        EmiNetUtil::write24(bufCur, header.ack);
        bufCur += EMI_PACKET_SEQUENCE_NUMBER_LENGTH;
    }

    if (hasNak) {
        EmiNetUtil::write24(bufCur, header.nak);
        bufCur += EMI_PACKET_SEQUENCE_NUMBER_LENGTH;
    }

    if (hasLinkCapacity) {
        *((int32_t *)bufCur) = htonl(*reinterpret_cast<const uint32_t *>(&header.linkCapacity));
        bufCur += sizeof(header.linkCapacity);
    }

    if (hasArrivalRate) {
        *((int32_t *)bufCur) = htonl(*reinterpret_cast<const uint32_t *>(&header.arrivalRate));
        bufCur += sizeof(header.arrivalRate);
    }

    if (hasRttResponse) {
        EmiNetUtil::write24(bufCur, header.rttResponse);
        bufCur += EMI_PACKET_SEQUENCE_NUMBER_LENGTH;

        *bufCur = header.rttResponseDelay;
        bufCur += sizeof(header.rttResponseDelay);
    }

    if (headerLength) {
        *headerLength = expectedSize;
    }

    return true;
}

bool EmiPacketHeader::writeEmpty(uint8_t *buf, size_t bufSize, size_t *headerLength) {
    if (0 >= bufSize) {
        return false;
    }

    *buf = 0;
    *headerLength = 1;

    return true;
}

void EmiPacketHeader::addFillerBytes(uint8_t *buf, size_t packetSize, uint16_t fillerSize) {
    ASSERT(1 <= packetSize);

    if (0 == fillerSize) {
        // We don't need to do anything
        return;
    }

    // Move the packet data
    std::copy_backward(buf+1, buf+packetSize, buf+packetSize+fillerSize);

    // Make sure we have the extra flags byte
    if (!(buf[0] & EMI_EXTRA_FLAGS_PACKET_FLAG)) {
        buf[0] |= EMI_EXTRA_FLAGS_PACKET_FLAG;
        buf[1] = 0;

        // Decrement the filler size here because by adding
        // the extra flags byte we have already increased
        // the size of the packet by one.
        fillerSize -= sizeof(EmiPacketExtraFlags);
    }

    if (0 == fillerSize) {
        // We're done. This happens when fillerSize was 1 and
        // the packet did not already contain the extra flags
        // byte
    }
    else if (1 == fillerSize) {
        buf[1] |= EMI_1_BYTE_FILLER_EXTRA_PACKET_FLAG;
        buf[2] = 0;
    }
    else {
        buf[1] |= EMI_2_BYTE_FILLER_EXTRA_PACKET_FLAG;

        *((uint16_t *)(buf+2)) = htons(fillerSize - 2);

        memset(buf+4, 0, fillerSize-2);
    }
}
<commit_msg>Fixed a fairly extreme memory corruption bug found with Valgrind. EmiPacketHeader::addFillerBytes would zero out almost 64kb when the fillerSize parameter was 1, 2 or 3.<commit_after>//
//  EmiPacketHeader.cc
//  rock
//
//  Created by Per Eckerdal on 2012-05-10.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#include "EmiPacketHeader.h"

#include "EmiNetUtil.h"

#include <cstring>
#include <algorithm>

inline static void extractFlagsAndSize(EmiPacketFlags flags,
                                       EmiPacketExtraFlags extraFlags,
                                       bool *hasSequenceNumber,
                                       bool *hasAck,
                                       bool *hasNak,
                                       bool *hasLinkCapacity,
                                       bool *hasArrivalRate,
                                       bool *hasRttRequest,
                                       bool *hasRttResponse,
                                       size_t *fillerSizePtr, // Can be NULL
                                       size_t *expectedSize) {
    size_t fillerSize = 0;

    *hasSequenceNumber = !!(flags & EMI_SEQUENCE_NUMBER_PACKET_FLAG);
    *hasAck            = !!(flags & EMI_ACK_PACKET_FLAG);
    *hasNak            = !!(flags & EMI_NAK_PACKET_FLAG);
    *hasLinkCapacity   = !!(flags & EMI_LINK_CAPACITY_PACKET_FLAG);
    *hasArrivalRate    = !!(flags & EMI_ARRIVAL_RATE_PACKET_FLAG);
    *hasRttRequest     = !!(flags & EMI_RTT_REQUEST_PACKET_FLAG);
    *hasRttResponse    = !!(flags & EMI_RTT_RESPONSE_PACKET_FLAG);
    bool hasExtraFlags = !!(flags & EMI_EXTRA_FLAGS_PACKET_FLAG);

    // 1 for the flags byte
    *expectedSize = sizeof(EmiPacketFlags);

    if (hasExtraFlags) {
        *expectedSize += sizeof(EmiPacketExtraFlags);

        if (flags & EMI_1_BYTE_FILLER_EXTRA_PACKET_FLAG) {
            fillerSize = 1;
        }
        else if (flags & EMI_2_BYTE_FILLER_EXTRA_PACKET_FLAG) {
            fillerSize = 2;
        }
        else {
            fillerSize = 0;
        }

        *expectedSize += fillerSize;
    }

    if (fillerSizePtr) {
        *fillerSizePtr = fillerSize;
    }

    *expectedSize += (*hasSequenceNumber ? EMI_PACKET_SEQUENCE_NUMBER_LENGTH : 0);
    *expectedSize += (*hasAck            ? EMI_PACKET_SEQUENCE_NUMBER_LENGTH : 0);
    *expectedSize += (*hasNak            ? EMI_PACKET_SEQUENCE_NUMBER_LENGTH : 0);
    *expectedSize += (*hasLinkCapacity   ? sizeof(float) : 0);
    *expectedSize += (*hasArrivalRate    ? sizeof(float) : 0);
    *expectedSize += (*hasRttResponse    ? EMI_PACKET_SEQUENCE_NUMBER_LENGTH+sizeof(uint8_t) : 0);
}

EmiPacketHeader::EmiPacketHeader() :
flags(0),
sequenceNumber(0),
ack(0),
nak(0),
linkCapacity(0),
arrivalRate(0),
rttResponse(0),
rttResponseDelay(0) {}

EmiPacketHeader::~EmiPacketHeader() {}

bool EmiPacketHeader::parse(const uint8_t *buf, size_t bufSize, EmiPacketHeader *header, size_t *headerLength) {
    if (0 >= bufSize) {
        return false;
    }

    EmiPacketFlags flags = buf[0];

    EmiPacketExtraFlags extraFlags = (EmiPacketExtraFlags) 0;
    if (bufSize >= 1) {
        extraFlags = (EmiPacketExtraFlags) buf[1];
    }

    bool hasSequenceNumber, hasAck, hasNak, hasLinkCapacity;
    bool hasArrivalRate, hasRttRequest, hasRttResponse;
    size_t expectedSize, fillerSize;
    extractFlagsAndSize(flags,
                        extraFlags,
                        &hasSequenceNumber,
                        &hasAck,
                        &hasNak,
                        &hasLinkCapacity,
                        &hasArrivalRate,
                        &hasRttRequest,
                        &hasRttResponse,
                        &fillerSize,
                        &expectedSize);

    if (2 == fillerSize) {
        // A 2 byte filler size means that the packet contains a 16 bit
        // unsigned integer which specifies padding
        if (4 > bufSize) {
            return false;
        }
        uint16_t twoByteFillerSize = ntohs(*((uint16_t *)(buf+2)));
        fillerSize += twoByteFillerSize;
        expectedSize += twoByteFillerSize;
    }

    if (bufSize < expectedSize) {
        return false;
    }

    header->flags = flags;
    header->sequenceNumber = 0;
    header->ack = 0;
    header->nak = 0;
    header->linkCapacity = 0.0f;
    header->arrivalRate = 0.0f;
    header->rttResponse = 0;
    header->rttResponseDelay = 0;

    const uint8_t *bufCur = buf+sizeof(header->flags);

    if (flags & EMI_EXTRA_FLAGS_PACKET_FLAG) {
        bufCur += sizeof(EmiPacketExtraFlags);
        bufCur += fillerSize;
    }

    if (hasSequenceNumber) {
        header->sequenceNumber = EmiNetUtil::read24(bufCur);
        bufCur += EMI_PACKET_SEQUENCE_NUMBER_LENGTH;
    }

    if (hasAck) {
        header->ack = EmiNetUtil::read24(bufCur);
        bufCur += EMI_PACKET_SEQUENCE_NUMBER_LENGTH;
    }

    if (hasNak) {
        header->nak = EmiNetUtil::read24(bufCur);
        bufCur += EMI_PACKET_SEQUENCE_NUMBER_LENGTH;
    }

    if (hasLinkCapacity) {
        uint32_t linkCapacityInt = ntohl(*reinterpret_cast<const uint32_t *>(bufCur));
        header->linkCapacity = *reinterpret_cast<float *>(&linkCapacityInt);
        bufCur += sizeof(header->linkCapacity);
    }

    if (hasArrivalRate) {
        uint32_t arrivalRateInt = ntohl(*reinterpret_cast<const uint32_t *>(bufCur));
        header->arrivalRate = *reinterpret_cast<float *>(&arrivalRateInt);
        bufCur += sizeof(header->arrivalRate);
    }

    if (hasRttResponse) {
        header->rttResponse = EmiNetUtil::read24(bufCur);
        bufCur += EMI_PACKET_SEQUENCE_NUMBER_LENGTH;

        header->rttResponseDelay = *bufCur;
        bufCur += sizeof(header->rttResponseDelay);
    }

    if (headerLength) {
        *headerLength = expectedSize;
    }

    return true;
}

bool EmiPacketHeader::write(uint8_t *buf, size_t bufSize, const EmiPacketHeader& header, size_t *headerLength) {
    if (0 >= bufSize) {
        return false;
    }

    bool hasSequenceNumber, hasAck, hasNak, hasLinkCapacity;
    bool hasArrivalRate, hasRttRequest, hasRttResponse;
    size_t expectedSize;
    extractFlagsAndSize(header.flags,
                        (EmiPacketExtraFlags)0,
                        &hasSequenceNumber,
                        &hasAck,
                        &hasNak,
                        &hasLinkCapacity,
                        &hasArrivalRate,
                        &hasRttRequest,
                        &hasRttResponse,
                        /*fillerSize:*/NULL,
                        &expectedSize);

    if (bufSize < expectedSize) {
        return false;
    }

    memset(buf, 0, expectedSize);
    buf[0] = header.flags;

    uint8_t *bufCur = buf+sizeof(EmiPacketFlags);

    if (hasSequenceNumber) {
        EmiNetUtil::write24(bufCur, header.sequenceNumber);
        bufCur += EMI_PACKET_SEQUENCE_NUMBER_LENGTH;
    }

    if (hasAck) {
        EmiNetUtil::write24(bufCur, header.ack);
        bufCur += EMI_PACKET_SEQUENCE_NUMBER_LENGTH;
    }

    if (hasNak) {
        EmiNetUtil::write24(bufCur, header.nak);
        bufCur += EMI_PACKET_SEQUENCE_NUMBER_LENGTH;
    }

    if (hasLinkCapacity) {
        *((int32_t *)bufCur) = htonl(*reinterpret_cast<const uint32_t *>(&header.linkCapacity));
        bufCur += sizeof(header.linkCapacity);
    }

    if (hasArrivalRate) {
        *((int32_t *)bufCur) = htonl(*reinterpret_cast<const uint32_t *>(&header.arrivalRate));
        bufCur += sizeof(header.arrivalRate);
    }

    if (hasRttResponse) {
        EmiNetUtil::write24(bufCur, header.rttResponse);
        bufCur += EMI_PACKET_SEQUENCE_NUMBER_LENGTH;

        *bufCur = header.rttResponseDelay;
        bufCur += sizeof(header.rttResponseDelay);
    }

    if (headerLength) {
        *headerLength = expectedSize;
    }

    return true;
}

bool EmiPacketHeader::writeEmpty(uint8_t *buf, size_t bufSize, size_t *headerLength) {
    if (0 >= bufSize) {
        return false;
    }

    *buf = 0;
    *headerLength = 1;

    return true;
}

void EmiPacketHeader::addFillerBytes(uint8_t *buf, size_t packetSize, uint16_t fillerSize) {
    ASSERT(1 <= packetSize);

    if (0 == fillerSize) {
        // We don't need to do anything
        return;
    }

    // Move the packet data
    std::copy_backward(buf+1, buf+packetSize, buf+packetSize+fillerSize);

    // Make sure we have the extra flags byte
    if (!(buf[0] & EMI_EXTRA_FLAGS_PACKET_FLAG)) {
        buf[0] |= EMI_EXTRA_FLAGS_PACKET_FLAG;
        buf[1] = 0;

        // Decrement the filler size here because by adding
        // the extra flags byte we have already increased
        // the size of the packet by one.
        fillerSize -= 1;
    }

    if (0 == fillerSize) {
        // We're done. This happens when fillerSize was 1 and
        // the packet did not already contain the extra flags
        // byte
    }
    else if (1 == fillerSize) {
        buf[1] |= EMI_1_BYTE_FILLER_EXTRA_PACKET_FLAG;
        buf[2] = 0;
    }
    else {
        buf[1] |= EMI_2_BYTE_FILLER_EXTRA_PACKET_FLAG;

        *((uint16_t *)(buf+2)) = htons(fillerSize - 2);

        memset(buf+4, 0, fillerSize-2);
    }
}
<|endoftext|>


<commit_before><commit_msg>GraphicManager: fix crash when swapping out graphics<commit_after><|endoftext|>


<commit_before><commit_msg>fdo#38635: sw: fix border corner gaps:<commit_after><|endoftext|>


<commit_before><commit_msg>During sensor search only check data of joining device for resource creation<commit_after><|endoftext|>


<commit_before><commit_msg>Filter REST API plugin network interfaces to not include virtual and loopback interface<commit_after><|endoftext|>


<commit_before>#include "SwiftExtractor.h"

#include <filesystem>
#include <fstream>
#include <iostream>
#include <sstream>
#include <memory>
#include <unistd.h>
#include <unordered_set>

#include <swift/AST/SourceFile.h>
#include <swift/Basic/FileTypes.h>
#include <llvm/ADT/SmallString.h>
#include <llvm/Support/FileSystem.h>
#include <llvm/Support/Path.h>

#include "swift/extractor/trap/generated/TrapClasses.h"
#include "swift/extractor/trap/TrapOutput.h"
#include "swift/extractor/SwiftVisitor.h"

using namespace codeql;

static void archiveFile(const SwiftExtractorConfiguration& config, swift::SourceFile& file) {
  if (std::error_code ec = llvm::sys::fs::create_directories(config.trapDir)) {
    std::cerr << "Cannot create TRAP directory: " << ec.message() << "\n";
    return;
  }

  if (std::error_code ec = llvm::sys::fs::create_directories(config.sourceArchiveDir)) {
    std::cerr << "Cannot create source archive directory: " << ec.message() << "\n";
    return;
  }

  llvm::SmallString<PATH_MAX> srcFilePath(file.getFilename());
  llvm::sys::fs::make_absolute(srcFilePath);

  llvm::SmallString<PATH_MAX> dstFilePath(config.sourceArchiveDir);
  llvm::sys::path::append(dstFilePath, srcFilePath);

  llvm::StringRef parent = llvm::sys::path::parent_path(dstFilePath);
  if (std::error_code ec = llvm::sys::fs::create_directories(parent)) {
    std::cerr << "Cannot create source archive destination directory '" << parent.str()
              << "': " << ec.message() << "\n";
    return;
  }

  if (std::error_code ec = llvm::sys::fs::copy_file(srcFilePath, dstFilePath)) {
    std::cerr << "Cannot archive source file '" << srcFilePath.str().str() << "' -> '"
              << dstFilePath.str().str() << "': " << ec.message() << "\n";
    return;
  }
}

static void extractDeclarations(const SwiftExtractorConfiguration& config,
                                llvm::ArrayRef<swift::Decl*> topLevelDecls,
                                swift::CompilerInstance& compiler,
                                swift::ModuleDecl& module,
                                swift::SourceFile* primaryFile = nullptr) {
  // The extractor can be called several times from different processes with
  // the same input file(s)
  // We are using PID to avoid concurrent access
  // TODO: find a more robust approach to avoid collisions?
  llvm::StringRef filename = primaryFile ? primaryFile->getFilename() : module.getModuleFilename();
  std::string tempTrapName = filename.str() + '.' + std::to_string(getpid()) + ".trap";
  llvm::SmallString<PATH_MAX> tempTrapPath(config.trapDir);
  llvm::sys::path::append(tempTrapPath, tempTrapName);

  llvm::StringRef trapParent = llvm::sys::path::parent_path(tempTrapPath);
  if (std::error_code ec = llvm::sys::fs::create_directories(trapParent)) {
    std::cerr << "Cannot create trap directory '" << trapParent.str() << "': " << ec.message()
              << "\n";
    return;
  }

  std::ofstream trapStream(tempTrapPath.str().str());
  if (!trapStream) {
    std::error_code ec;
    ec.assign(errno, std::generic_category());
    std::cerr << "Cannot create temp trap file '" << tempTrapPath.str().str()
              << "': " << ec.message() << "\n";
    return;
  }
  trapStream << "// extractor-args: ";
  for (auto opt : config.frontendOptions) {
    trapStream << std::quoted(opt) << " ";
  }
  trapStream << "\n\n";

  TrapOutput trap{trapStream};
  TrapArena arena{};

  // TODO: move default location emission elsewhere, possibly in a separate global trap file
  auto unknownFileLabel = arena.allocateLabel<FileTag>();
  // the following cannot conflict with actual files as those have an absolute path starting with /
  trap.assignKey(unknownFileLabel, "unknown");
  trap.emit(FilesTrap{unknownFileLabel});
  auto unknownLocationLabel = arena.allocateLabel<LocationTag>();
  trap.assignKey(unknownLocationLabel, "unknown");
  trap.emit(LocationsTrap{unknownLocationLabel, unknownFileLabel});

  SwiftVisitor visitor(compiler.getSourceMgr(), arena, trap, module, primaryFile);
  for (auto decl : topLevelDecls) {
    visitor.extract(decl);
  }
  if (topLevelDecls.empty()) {
    // In the case of empty files, the dispatcher is not called, but we still want to 'record' the
    // fact that the file was extracted
    llvm::SmallString<PATH_MAX> name(filename);
    llvm::sys::fs::make_absolute(name);
    auto fileLabel = arena.allocateLabel<FileTag>();
    trap.assignKey(fileLabel, name.str().str());
    trap.emit(FilesTrap{fileLabel, name.str().str()});
  }

  // TODO: Pick a better name to avoid collisions
  std::string trapName = filename.str() + ".trap";
  llvm::SmallString<PATH_MAX> trapPath(config.trapDir);
  llvm::sys::path::append(trapPath, trapName);

  // TODO: The last process wins. Should we do better than that?
  if (std::error_code ec = llvm::sys::fs::rename(tempTrapPath, trapPath)) {
    std::cerr << "Cannot rename temp trap file '" << tempTrapPath.str().str() << "' -> '"
              << trapPath.str().str() << "': " << ec.message() << "\n";
  }
}

void codeql::extractSwiftFiles(const SwiftExtractorConfiguration& config,
                               swift::CompilerInstance& compiler) {
  // The frontend can be called in many different ways.
  // At each invocation we only extract system and builtin modules and any input source files that
  // have an output associated with them.
  std::unordered_set<std::string> sourceFiles;
  auto inputFiles = compiler.getInvocation().getFrontendOptions().InputsAndOutputs.getAllInputs();
  for (auto& input : inputFiles) {
    if (input.getType() == swift::file_types::TY_Swift && !input.outputFilename().empty()) {
      sourceFiles.insert(input.getFileName());
    }
  }

  for (auto& [_, module] : compiler.getASTContext().getLoadedModules()) {
    // We only extract system and builtin modules here as the other "user" modules can be built
    // during the build process and then re-used at a later stage. In this case, we extract the
    // user code twice: once during the module build in a form of a source file, and then as
    // a pre-built module during building of the dependent source files.
    if (module->isSystemModule() || module->isBuiltinModule()) {
      llvm::SmallVector<swift::Decl*> decls;
      module->getTopLevelDecls(decls);
      // TODO: pass ModuleDecl directly when we have module extraction in place?
      extractDeclarations(config, decls, compiler, *module);
    } else {
      for (auto file : module->getFiles()) {
        if (!llvm::isa<swift::SourceFile>(file)) {
          continue;
        }
        auto sourceFile = llvm::cast<swift::SourceFile>(file);
        if (sourceFiles.count(sourceFile->getFilename().str()) == 0) {
          continue;
        }
        archiveFile(config, *sourceFile);
        extractDeclarations(config, sourceFile->getTopLevelDecls(), compiler, *module, sourceFile);
      }
    }
  }
}
<commit_msg>Update swift/extractor/SwiftExtractor.cpp<commit_after>#include "SwiftExtractor.h"

#include <filesystem>
#include <fstream>
#include <iostream>
#include <sstream>
#include <memory>
#include <unistd.h>
#include <unordered_set>

#include <swift/AST/SourceFile.h>
#include <swift/Basic/FileTypes.h>
#include <llvm/ADT/SmallString.h>
#include <llvm/Support/FileSystem.h>
#include <llvm/Support/Path.h>

#include "swift/extractor/trap/generated/TrapClasses.h"
#include "swift/extractor/trap/TrapOutput.h"
#include "swift/extractor/SwiftVisitor.h"

using namespace codeql;

static void archiveFile(const SwiftExtractorConfiguration& config, swift::SourceFile& file) {
  if (std::error_code ec = llvm::sys::fs::create_directories(config.trapDir)) {
    std::cerr << "Cannot create TRAP directory: " << ec.message() << "\n";
    return;
  }

  if (std::error_code ec = llvm::sys::fs::create_directories(config.sourceArchiveDir)) {
    std::cerr << "Cannot create source archive directory: " << ec.message() << "\n";
    return;
  }

  llvm::SmallString<PATH_MAX> srcFilePath(file.getFilename());
  llvm::sys::fs::make_absolute(srcFilePath);

  llvm::SmallString<PATH_MAX> dstFilePath(config.sourceArchiveDir);
  llvm::sys::path::append(dstFilePath, srcFilePath);

  llvm::StringRef parent = llvm::sys::path::parent_path(dstFilePath);
  if (std::error_code ec = llvm::sys::fs::create_directories(parent)) {
    std::cerr << "Cannot create source archive destination directory '" << parent.str()
              << "': " << ec.message() << "\n";
    return;
  }

  if (std::error_code ec = llvm::sys::fs::copy_file(srcFilePath, dstFilePath)) {
    std::cerr << "Cannot archive source file '" << srcFilePath.str().str() << "' -> '"
              << dstFilePath.str().str() << "': " << ec.message() << "\n";
    return;
  }
}

static void extractDeclarations(const SwiftExtractorConfiguration& config,
                                llvm::ArrayRef<swift::Decl*> topLevelDecls,
                                swift::CompilerInstance& compiler,
                                swift::ModuleDecl& module,
                                swift::SourceFile* primaryFile = nullptr) {
  // The extractor can be called several times from different processes with
  // the same input file(s)
  // We are using PID to avoid concurrent access
  // TODO: find a more robust approach to avoid collisions?
  llvm::StringRef filename = primaryFile ? primaryFile->getFilename() : module.getModuleFilename();
  std::string tempTrapName = filename.str() + '.' + std::to_string(getpid()) + ".trap";
  llvm::SmallString<PATH_MAX> tempTrapPath(config.trapDir);
  llvm::sys::path::append(tempTrapPath, tempTrapName);

  llvm::StringRef trapParent = llvm::sys::path::parent_path(tempTrapPath);
  if (std::error_code ec = llvm::sys::fs::create_directories(trapParent)) {
    std::cerr << "Cannot create trap directory '" << trapParent.str() << "': " << ec.message()
              << "\n";
    return;
  }

  std::ofstream trapStream(tempTrapPath.str().str());
  if (!trapStream) {
    std::error_code ec;
    ec.assign(errno, std::generic_category());
    std::cerr << "Cannot create temp trap file '" << tempTrapPath.str().str()
              << "': " << ec.message() << "\n";
    return;
  }
  trapStream << "// extractor-args: ";
  for (auto opt : config.frontendOptions) {
    trapStream << std::quoted(opt) << " ";
  }
  trapStream << "\n\n";

  TrapOutput trap{trapStream};
  TrapArena arena{};

  // TODO: move default location emission elsewhere, possibly in a separate global trap file
  auto unknownFileLabel = arena.allocateLabel<FileTag>();
  // the following cannot conflict with actual files as those have an absolute path starting with /
  trap.assignKey(unknownFileLabel, "unknown");
  trap.emit(FilesTrap{unknownFileLabel});
  auto unknownLocationLabel = arena.allocateLabel<LocationTag>();
  trap.assignKey(unknownLocationLabel, "unknown");
  trap.emit(LocationsTrap{unknownLocationLabel, unknownFileLabel});

  SwiftVisitor visitor(compiler.getSourceMgr(), arena, trap, module, primaryFile);
  for (auto decl : topLevelDecls) {
    visitor.extract(decl);
  }
  if (topLevelDecls.empty()) {
    // In the case of empty files, the dispatcher is not called, but we still want to 'record' the
    // fact that the file was extracted
    llvm::SmallString<PATH_MAX> name(filename);
    llvm::sys::fs::make_absolute(name);
    auto fileLabel = arena.allocateLabel<FileTag>();
    trap.assignKey(fileLabel, name.str().str());
    trap.emit(FilesTrap{fileLabel, name.str().str()});
  }

  // TODO: Pick a better name to avoid collisions
  std::string trapName = filename.str() + ".trap";
  llvm::SmallString<PATH_MAX> trapPath(config.trapDir);
  llvm::sys::path::append(trapPath, trapName);

  // TODO: The last process wins. Should we do better than that?
  if (std::error_code ec = llvm::sys::fs::rename(tempTrapPath, trapPath)) {
    std::cerr << "Cannot rename temp trap file '" << tempTrapPath.str().str() << "' -> '"
              << trapPath.str().str() << "': " << ec.message() << "\n";
  }
}

void codeql::extractSwiftFiles(const SwiftExtractorConfiguration& config,
                               swift::CompilerInstance& compiler) {
  // The frontend can be called in many different ways.
  // At each invocation we only extract system and builtin modules and any input source files that
  // have an output associated with them.
  std::unordered_set<std::string> sourceFiles;
  auto inputFiles = compiler.getInvocation().getFrontendOptions().InputsAndOutputs.getAllInputs();
  for (auto& input : inputFiles) {
    if (input.getType() == swift::file_types::TY_Swift && !input.outputFilename().empty()) {
      sourceFiles.insert(input.getFileName());
    }
  }

  for (auto& [_, module] : compiler.getASTContext().getLoadedModules()) {
    // We only extract system and builtin modules here as the other "user" modules can be built
    // during the build process and then re-used at a later stage. In this case, we extract the
    // user code twice: once during the module build in a form of a source file, and then as
    // a pre-built module during building of the dependent source files.
    if (module->isSystemModule() || module->isBuiltinModule()) {
      llvm::SmallVector<swift::Decl*> decls;
      module->getTopLevelDecls(decls);
      // TODO: pass ModuleDecl directly when we have module extraction in place?
      extractDeclarations(config, decls, compiler, *module);
    } else {
      for (auto file : module->getFiles()) {
        auto sourceFile = llvm::dyn_cast<swift::SourceFile>(file);
        if (!sourceFile || sourceFiles.count(sourceFile->getFilename().str()) == 0) {
          continue;
        }
        archiveFile(config, *sourceFile);
        extractDeclarations(config, sourceFile->getTopLevelDecls(), compiler, *module, sourceFile);
      }
    }
  }
}
<|endoftext|>


<commit_before><commit_msg>UPDATE moved reflection cubmap subresource init to be independent to static shadows<commit_after><|endoftext|>


<commit_before>/*     Copyright 2015-2018 Egor Yusov
*
*  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
*
*  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 OF ANY PROPRIETARY RIGHTS.
*
*  In no event and under no legal theory, whether in tort (including negligence),
*  contract, or otherwise, unless required by applicable law (such as deliberate
*  and grossly negligent acts) or agreed to in writing, shall any Contributor be
*  liable for any damages, including any direct, indirect, special, incidental,
*  or consequential damages of any character arising as a result of this License or
*  out of the use or inability to use the software (including but not limited to damages
*  for loss of goodwill, work stoppage, computer failure or malfunction, or any and
*  all other commercial damages or losses), even if such Contributor has been advised
*  of the possibility of such damages.
*/

#include <queue>
#include "SampleApp.h"
#include "AntTweakBar.h"

using namespace Diligent;

class SampleAppIOS final : public SampleApp
{
public:
    SampleAppIOS()
    {
        m_DeviceType = DeviceType::OpenGLES;
    }

    virtual void OnGLContextCreated(void *eaglLayer)override final
    {
        InitializeDiligentEngine(eaglLayer);
        m_TheSample->SetUIScale(2);
        InitializeSample();
    }

    virtual void Render()override
    {
        /*m_pImmediateContext->SetRenderTargets(0, nullptr, nullptr);
        // Handle all TwBar events here as the event handlers call draw commands
        // and thus cannot be used in the UI thread
        while(!TwBarEvents.empty())
        {
            const auto& event = TwBarEvents.front();
            switch (event.type)
            {
                case TwEvent::LMB_PRESSED:
                case TwEvent::RMB_PRESSED:
                    TwMouseButton(TW_MOUSE_PRESSED, event.type == TwEvent::LMB_PRESSED ? TW_MOUSE_LEFT : TW_MOUSE_RIGHT);
                    break;

                case TwEvent::LMB_RELEASED:
                case TwEvent::RMB_RELEASED:
                    TwMouseButton(TW_MOUSE_RELEASED, event.type == TwEvent::LMB_RELEASED ? TW_MOUSE_LEFT : TW_MOUSE_RIGHT);
                    break;

                case TwEvent::MOUSE_MOVE:
                    TwMouseMotion(event.mouseX, event.mouseY);
                    break;

                case TwEvent::KEY_PRESSED:
                    TwKeyPressed(event.key, 0);
                    break;
            }
            TwBarEvents.pop();
        }*/

        SampleApp::Render();
    }

private:
    /*
    // Unfortunately TwBar library calls rendering
    // functions from event handlers, which does not work on MacOS
    // as UI events and rendering are handled by separate threads
    struct TwEvent
    {
        enum EVENT_TYPE
        {
            LMB_PRESSED,
            LMB_RELEASED,
            RMB_PRESSED,
            RMB_RELEASED,
            MOUSE_MOVE,
            KEY_PRESSED
        }type;
        int mouseX = 0;
        int mouseY = 0;
        int key = 0;

        TwEvent(EVENT_TYPE _type) : type(_type){}
        TwEvent(int x, int y) : type(MOUSE_MOVE), mouseX(x), mouseY(y){}
        TwEvent(int k) : type(KEY_PRESSED), key(k){}
    };
    std::queue<TwEvent> TwBarEvents;*/
};

NativeAppBase* CreateApplication()
{
    return new SampleAppIOS;
}
<commit_msg>Removed UI scale on iOS<commit_after>/*     Copyright 2015-2018 Egor Yusov
*
*  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
*
*  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 OF ANY PROPRIETARY RIGHTS.
*
*  In no event and under no legal theory, whether in tort (including negligence),
*  contract, or otherwise, unless required by applicable law (such as deliberate
*  and grossly negligent acts) or agreed to in writing, shall any Contributor be
*  liable for any damages, including any direct, indirect, special, incidental,
*  or consequential damages of any character arising as a result of this License or
*  out of the use or inability to use the software (including but not limited to damages
*  for loss of goodwill, work stoppage, computer failure or malfunction, or any and
*  all other commercial damages or losses), even if such Contributor has been advised
*  of the possibility of such damages.
*/

#include <queue>
#include "SampleApp.h"
#include "AntTweakBar.h"

using namespace Diligent;

class SampleAppIOS final : public SampleApp
{
public:
    SampleAppIOS()
    {
        m_DeviceType = DeviceType::OpenGLES;
    }

    virtual void OnGLContextCreated(void *eaglLayer)override final
    {
        InitializeDiligentEngine(eaglLayer);
        InitializeSample();
    }

    virtual void Render()override
    {
        /*m_pImmediateContext->SetRenderTargets(0, nullptr, nullptr);
        // Handle all TwBar events here as the event handlers call draw commands
        // and thus cannot be used in the UI thread
        while(!TwBarEvents.empty())
        {
            const auto& event = TwBarEvents.front();
            switch (event.type)
            {
                case TwEvent::LMB_PRESSED:
                case TwEvent::RMB_PRESSED:
                    TwMouseButton(TW_MOUSE_PRESSED, event.type == TwEvent::LMB_PRESSED ? TW_MOUSE_LEFT : TW_MOUSE_RIGHT);
                    break;

                case TwEvent::LMB_RELEASED:
                case TwEvent::RMB_RELEASED:
                    TwMouseButton(TW_MOUSE_RELEASED, event.type == TwEvent::LMB_RELEASED ? TW_MOUSE_LEFT : TW_MOUSE_RIGHT);
                    break;

                case TwEvent::MOUSE_MOVE:
                    TwMouseMotion(event.mouseX, event.mouseY);
                    break;

                case TwEvent::KEY_PRESSED:
                    TwKeyPressed(event.key, 0);
                    break;
            }
            TwBarEvents.pop();
        }*/

        SampleApp::Render();
    }

private:
    /*
    // Unfortunately TwBar library calls rendering
    // functions from event handlers, which does not work on MacOS
    // as UI events and rendering are handled by separate threads
    struct TwEvent
    {
        enum EVENT_TYPE
        {
            LMB_PRESSED,
            LMB_RELEASED,
            RMB_PRESSED,
            RMB_RELEASED,
            MOUSE_MOVE,
            KEY_PRESSED
        }type;
        int mouseX = 0;
        int mouseY = 0;
        int key = 0;

        TwEvent(EVENT_TYPE _type) : type(_type){}
        TwEvent(int x, int y) : type(MOUSE_MOVE), mouseX(x), mouseY(y){}
        TwEvent(int k) : type(KEY_PRESSED), key(k){}
    };
    std::queue<TwEvent> TwBarEvents;*/
};

NativeAppBase* CreateApplication()
{
    return new SampleAppIOS;
}
<|endoftext|>


<commit_before>/* -------------------------------------------------------------------------- *
 *                        Simbody(tm): SimTKmath                              *
 * -------------------------------------------------------------------------- *
 * This is part of the SimTK biosimulation toolkit originating from           *
 * Simbios, the NIH National Center for Physics-Based Simulation of           *
 * Biological Structures at Stanford, funded under the NIH Roadmap for        *
 * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody.  *
 *                                                                            *
 * Portions copyright (c) 2006-14 Stanford University and the Authors.        *
 * Authors: Chris Dembia                                                      *
 * Contributors: Michael Sherman                                              *
 *                                                                            *
 * 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 "CMAESOptimizer.h"

#include <bitset>

namespace SimTK {

#define SimTK_CMAES_PRINT(diag, cmds) \
do { \
if (std::bitset<2>(diag).test(0)) { cmds; } \
} \
while(false)

#define SimTK_CMAES_FILE(diag, cmds) \
do { \
if (std::bitset<2>(diag).test(1)) { cmds; } \
} \
while(false)

CMAESOptimizer::CMAESOptimizer(const OptimizerSystem& sys) : OptimizerRep(sys)
{
    SimTK_VALUECHECK_ALWAYS(2, sys.getNumParameters(), INT_MAX, "nParameters",
            "CMAESOptimizer");
}

Optimizer::OptimizerRep* CMAESOptimizer::clone() const {
    return new CMAESOptimizer(*this);
}

Real CMAESOptimizer::optimize(SimTK::Vector& results)
{
    const OptimizerSystem& sys = getOptimizerSystem();
    int n = sys.getNumParameters();

    // Initialize objective function value and cmaes data structure.
    // =============================================================
    Real f;
    cmaes_t evo;

    // Check that the initial point is feasible.
    // =========================================
    checkInitialPointIsFeasible(results);

    // Initialize cmaes.
    // =================
    double* funvals = init(evo, results);
    SimTK_CMAES_PRINT(diagnosticsLevel, printf("%s\n", cmaes_SayHello(&evo)));

    // Optimize.
    // =========
    while (!cmaes_TestForTermination(&evo)) {

        // Sample a population.
        // ====================
        double*const* pop = cmaes_SamplePopulation(&evo);

        // Resample to keep population within limits.
        // ==========================================
        if( sys.getHasLimits() ) {
            Real *lowerLimits, *upperLimits;
            sys.getParameterLimits( &lowerLimits, &upperLimits );

            for (int i = 0; i < cmaes_Get(&evo, "lambda"); i++) {
                bool feasible = false;
                while (!feasible) {
                    feasible = true;
                    for (int j = 0; j < n; j++) {
                        if (pop[i][j] < lowerLimits[j] ||
                                pop[i][j] > upperLimits[j]) {
                            feasible = false;
                            pop = cmaes_ReSampleSingle(&evo, i);
                            break;
                        }
                    }
                }
            }
        }

        // Evaluate the objective function on the samples.
        // ===============================================
        for (int i = 0; i < cmaes_Get(&evo, "lambda"); i++) {
            objectiveFuncWrapper(n, pop[i], true, &funvals[i], this);
        }

        // Update the distribution (mean, covariance, etc.).
        // =================================================
        cmaes_UpdateDistribution(&evo, funvals);
    }

    // Wrap up.
    // ========
    SimTK_CMAES_PRINT(diagnosticsLevel,
            printf("Stop:\n%s\n", cmaes_TestForTermination(&evo)));

    // Update best parameters and objective function value.
    const double* optx = cmaes_GetPtr(&evo, "xbestever");
    for (int i = 0; i < n; i++) {
        results[i] = optx[i];
    }
    f = cmaes_Get(&evo, "fbestever");

    SimTK_CMAES_FILE(diagnosticsLevel,
            cmaes_WriteToFile(&evo, "all", "allcmaes.dat"));

    // Free memory.
    cmaes_exit(&evo);

    return f;
}

void CMAESOptimizer::checkInitialPointIsFeasible(const Vector& x) const {

    const OptimizerSystem& sys = getOptimizerSystem();

    if( sys.getHasLimits() ) {
        Real *lowerLimits, *upperLimits;
        sys.getParameterLimits( &lowerLimits, &upperLimits );
        for (int i = 0; i < sys.getNumParameters(); i++) {
            SimTK_APIARGCHECK4_ALWAYS(
                    lowerLimits[i] <= x[i] && x[i] <= upperLimits[i],
                    "CMAESOptimizer", "checkInitialPointIsFeasible",
                    "Initial guess results[%d] = %f "
                    "is not within limits [%f, %f].",
                    i, x[i], lowerLimits[i], upperLimits[i]);
        }
    }
}

double* CMAESOptimizer::init(cmaes_t& evo, SimTK::Vector& results) const
{
    const OptimizerSystem& sys = getOptimizerSystem();
    int n = sys.getNumParameters();

    // Prepare to call cmaes_init_para.
    // ================================

    // lambda
    // ------
    int lambda = 0;
    getAdvancedIntOption("lambda", lambda);

    // sigma
    // -----
    double sigma = 0;
    double* stddev = NULL;
    Vector sigmaArray;
    if (getAdvancedRealOption("sigma", sigma)) {
        sigmaArray.resize(n);
        for (int i = 0; i < n; i++) {
            sigmaArray[i] = sigma;
        }
        stddev = &sigmaArray[0];
    }

    // seed
    // ----
    int seed = 0;
    if (getAdvancedIntOption("seed", seed)) {
        SimTK_VALUECHECK_NONNEG_ALWAYS(seed, "seed",
                "CMAESOptimizer::processSettingsBeforeCMAESInit");
    }

    // input parameter filename
    // ------------------------
    std::string input_parameter_filename = "none";
    SimTK_CMAES_FILE(diagnosticsLevel,
            input_parameter_filename = "writeonly";);

    // Call cmaes_init_para.
    // =====================
    // Here, we specify the subset of options that can be passed to
    // cmaes_init_para.
    cmaes_init_para(&evo,
            n,                 // dimension
            &results[0],       // xstart
            stddev,            // stddev
            seed,              // seed
            lambda,            // lambda
            input_parameter_filename.c_str() // input_parameter_filename
            );

    // Set settings that are usually read in from cmaes_initials.par.
    // ==============================================================
    process_readpara_settings(evo);

    // Once we've updated settings in readpara_t, finalize the initialization.
    return cmaes_init_final(&evo);
}

void CMAESOptimizer::process_readpara_settings(cmaes_t& evo) const
{
    // Termination criteria
    // ====================

    // stopMaxIter
    // -----------
    // maxIterations is a protected member variable of OptimizerRep.
    evo.sp.stopMaxIter = maxIterations;

    // stopTolFun
    // ----------
    // convergenceTolerance is a protected member variable of OptimizerRep.
    evo.sp.stopTolFun = convergenceTolerance;

    // stopMaxFunEvals
    // ---------------
    int stopMaxFunEvals;
    if (getAdvancedIntOption("stopMaxFunEvals", stopMaxFunEvals)) {
        SimTK_VALUECHECK_NONNEG_ALWAYS(stopMaxFunEvals, "stopMaxFunEvals",
                "CMAESOptimizer::processSettingsAfterCMAESInit");
        evo.sp.stopMaxFunEvals = stopMaxFunEvals;
    }

    // stopFitness
    // -----------
    double stopFitness;
    if (getAdvancedRealOption("stopFitness", stopFitness)) {
        evo.sp.stStopFitness.flg = 1;
        evo.sp.stStopFitness.val = stopFitness;
    }

    // stopTolFunHist
    // --------------
    double stopTolFunHist;
    if (getAdvancedRealOption("stopTolFunHist", stopTolFunHist)) {
        evo.sp.stopTolFunHist = stopTolFunHist;
    }

    // stopTolX
    // --------
    double stopTolX;
    if (getAdvancedRealOption("stopTolX", stopTolX)) {
        evo.sp.stopTolX = stopTolX;
    }

    // stopTolXFactor
    // --------------
    double stopTolUpXFactor;
    if (getAdvancedRealOption("stopTolUpXFactor", stopTolUpXFactor)) {
        evo.sp.stopTolUpXFactor = stopTolUpXFactor;
    }

    // maxtime
    // =======
    double maxtime;
    if (getAdvancedRealOption("maxTimeFractionForEigendecomposition", maxtime))
    {
        evo.sp.updateCmode.maxtime = maxtime;
    }
}

#undef SimTK_CMAES_PRINT
#undef SimTK_CMAES_FILE

} // namespace SimTK
<commit_msg>Add Niko as contributor to CMAESOptimizer.<commit_after>/* -------------------------------------------------------------------------- *
 *                        Simbody(tm): SimTKmath                              *
 * -------------------------------------------------------------------------- *
 * This is part of the SimTK biosimulation toolkit originating from           *
 * Simbios, the NIH National Center for Physics-Based Simulation of           *
 * Biological Structures at Stanford, funded under the NIH Roadmap for        *
 * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody.  *
 *                                                                            *
 * Portions copyright (c) 2006-14 Stanford University and the Authors.        *
 * Authors: Chris Dembia                                                      *
 * Contributors: Michael Sherman, Nikolaus Hansen                             *
 *                                                                            *
 * 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 "CMAESOptimizer.h"

#include <bitset>

namespace SimTK {

#define SimTK_CMAES_PRINT(diag, cmds) \
do { \
if (std::bitset<2>(diag).test(0)) { cmds; } \
} \
while(false)

#define SimTK_CMAES_FILE(diag, cmds) \
do { \
if (std::bitset<2>(diag).test(1)) { cmds; } \
} \
while(false)

CMAESOptimizer::CMAESOptimizer(const OptimizerSystem& sys) : OptimizerRep(sys)
{
    SimTK_VALUECHECK_ALWAYS(2, sys.getNumParameters(), INT_MAX, "nParameters",
            "CMAESOptimizer");
}

Optimizer::OptimizerRep* CMAESOptimizer::clone() const {
    return new CMAESOptimizer(*this);
}

Real CMAESOptimizer::optimize(SimTK::Vector& results)
{
    const OptimizerSystem& sys = getOptimizerSystem();
    int n = sys.getNumParameters();

    // Initialize objective function value and cmaes data structure.
    // =============================================================
    Real f;
    cmaes_t evo;

    // Check that the initial point is feasible.
    // =========================================
    checkInitialPointIsFeasible(results);

    // Initialize cmaes.
    // =================
    double* funvals = init(evo, results);
    SimTK_CMAES_PRINT(diagnosticsLevel, printf("%s\n", cmaes_SayHello(&evo)));

    // Optimize.
    // =========
    while (!cmaes_TestForTermination(&evo)) {

        // Sample a population.
        // ====================
        double*const* pop = cmaes_SamplePopulation(&evo);

        // Resample to keep population within limits.
        // ==========================================
        if( sys.getHasLimits() ) {
            Real *lowerLimits, *upperLimits;
            sys.getParameterLimits( &lowerLimits, &upperLimits );

            for (int i = 0; i < cmaes_Get(&evo, "lambda"); i++) {
                bool feasible = false;
                while (!feasible) {
                    feasible = true;
                    for (int j = 0; j < n; j++) {
                        if (pop[i][j] < lowerLimits[j] ||
                                pop[i][j] > upperLimits[j]) {
                            feasible = false;
                            pop = cmaes_ReSampleSingle(&evo, i);
                            break;
                        }
                    }
                }
            }
        }

        // Evaluate the objective function on the samples.
        // ===============================================
        for (int i = 0; i < cmaes_Get(&evo, "lambda"); i++) {
            objectiveFuncWrapper(n, pop[i], true, &funvals[i], this);
        }

        // Update the distribution (mean, covariance, etc.).
        // =================================================
        cmaes_UpdateDistribution(&evo, funvals);
    }

    // Wrap up.
    // ========
    SimTK_CMAES_PRINT(diagnosticsLevel,
            printf("Stop:\n%s\n", cmaes_TestForTermination(&evo)));

    // Update best parameters and objective function value.
    const double* optx = cmaes_GetPtr(&evo, "xbestever");
    for (int i = 0; i < n; i++) {
        results[i] = optx[i];
    }
    f = cmaes_Get(&evo, "fbestever");

    SimTK_CMAES_FILE(diagnosticsLevel,
            cmaes_WriteToFile(&evo, "all", "allcmaes.dat"));

    // Free memory.
    cmaes_exit(&evo);

    return f;
}

void CMAESOptimizer::checkInitialPointIsFeasible(const Vector& x) const {

    const OptimizerSystem& sys = getOptimizerSystem();

    if( sys.getHasLimits() ) {
        Real *lowerLimits, *upperLimits;
        sys.getParameterLimits( &lowerLimits, &upperLimits );
        for (int i = 0; i < sys.getNumParameters(); i++) {
            SimTK_APIARGCHECK4_ALWAYS(
                    lowerLimits[i] <= x[i] && x[i] <= upperLimits[i],
                    "CMAESOptimizer", "checkInitialPointIsFeasible",
                    "Initial guess results[%d] = %f "
                    "is not within limits [%f, %f].",
                    i, x[i], lowerLimits[i], upperLimits[i]);
        }
    }
}

double* CMAESOptimizer::init(cmaes_t& evo, SimTK::Vector& results) const
{
    const OptimizerSystem& sys = getOptimizerSystem();
    int n = sys.getNumParameters();

    // Prepare to call cmaes_init_para.
    // ================================

    // lambda
    // ------
    int lambda = 0;
    getAdvancedIntOption("lambda", lambda);

    // sigma
    // -----
    double sigma = 0;
    double* stddev = NULL;
    Vector sigmaArray;
    if (getAdvancedRealOption("sigma", sigma)) {
        sigmaArray.resize(n);
        for (int i = 0; i < n; i++) {
            sigmaArray[i] = sigma;
        }
        stddev = &sigmaArray[0];
    }

    // seed
    // ----
    int seed = 0;
    if (getAdvancedIntOption("seed", seed)) {
        SimTK_VALUECHECK_NONNEG_ALWAYS(seed, "seed",
                "CMAESOptimizer::processSettingsBeforeCMAESInit");
    }

    // input parameter filename
    // ------------------------
    std::string input_parameter_filename = "none";
    SimTK_CMAES_FILE(diagnosticsLevel,
            input_parameter_filename = "writeonly";);

    // Call cmaes_init_para.
    // =====================
    // Here, we specify the subset of options that can be passed to
    // cmaes_init_para.
    cmaes_init_para(&evo,
            n,                 // dimension
            &results[0],       // xstart
            stddev,            // stddev
            seed,              // seed
            lambda,            // lambda
            input_parameter_filename.c_str() // input_parameter_filename
            );

    // Set settings that are usually read in from cmaes_initials.par.
    // ==============================================================
    process_readpara_settings(evo);

    // Once we've updated settings in readpara_t, finalize the initialization.
    return cmaes_init_final(&evo);
}

void CMAESOptimizer::process_readpara_settings(cmaes_t& evo) const
{
    // Termination criteria
    // ====================

    // stopMaxIter
    // -----------
    // maxIterations is a protected member variable of OptimizerRep.
    evo.sp.stopMaxIter = maxIterations;

    // stopTolFun
    // ----------
    // convergenceTolerance is a protected member variable of OptimizerRep.
    evo.sp.stopTolFun = convergenceTolerance;

    // stopMaxFunEvals
    // ---------------
    int stopMaxFunEvals;
    if (getAdvancedIntOption("stopMaxFunEvals", stopMaxFunEvals)) {
        SimTK_VALUECHECK_NONNEG_ALWAYS(stopMaxFunEvals, "stopMaxFunEvals",
                "CMAESOptimizer::processSettingsAfterCMAESInit");
        evo.sp.stopMaxFunEvals = stopMaxFunEvals;
    }

    // stopFitness
    // -----------
    double stopFitness;
    if (getAdvancedRealOption("stopFitness", stopFitness)) {
        evo.sp.stStopFitness.flg = 1;
        evo.sp.stStopFitness.val = stopFitness;
    }

    // stopTolFunHist
    // --------------
    double stopTolFunHist;
    if (getAdvancedRealOption("stopTolFunHist", stopTolFunHist)) {
        evo.sp.stopTolFunHist = stopTolFunHist;
    }

    // stopTolX
    // --------
    double stopTolX;
    if (getAdvancedRealOption("stopTolX", stopTolX)) {
        evo.sp.stopTolX = stopTolX;
    }

    // stopTolXFactor
    // --------------
    double stopTolUpXFactor;
    if (getAdvancedRealOption("stopTolUpXFactor", stopTolUpXFactor)) {
        evo.sp.stopTolUpXFactor = stopTolUpXFactor;
    }

    // maxtime
    // =======
    double maxtime;
    if (getAdvancedRealOption("maxTimeFractionForEigendecomposition", maxtime))
    {
        evo.sp.updateCmode.maxtime = maxtime;
    }
}

#undef SimTK_CMAES_PRINT
#undef SimTK_CMAES_FILE

} // namespace SimTK
<|endoftext|>