<commit_before>/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES 3.1 Module
 * -------------------------------------------------
 *
 * Copyright 2016 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.
 *
 *//*!
 * \file
 * \brief Negative Advanced Blend Equation Tests
 *//*--------------------------------------------------------------------*/

#include "es31fNegativeAdvancedBlendEquationTests.hpp"

#include "gluShaderProgram.hpp"
#include "glwEnums.hpp"

namespace deqp
{
namespace gles31
{
namespace Functional
{
namespace NegativeTestShared
{
namespace
{

enum BlendEquation
{
	BLEND_EQUATION_MULTIPLY = 0,
	BLEND_EQUATION_SCREEN,
	BLEND_EQUATION_OVERLAY,
	BLEND_EQUATION_DARKEN,
	BLEND_EQUATION_LIGHTEN,
	BLEND_EQUATION_COLORDODGE,
	BLEND_EQUATION_COLORBURN,
	BLEND_EQUATION_HARDLIGHT,
	BLEND_EQUATION_SOFTLIGHT,
	BLEND_EQUATION_DIFFERENCE,
	BLEND_EQUATION_EXCLUSION,
	BLEND_EQUATION_HSL_HUE,
	BLEND_EQUATION_HSL_SATURATION,
	BLEND_EQUATION_HSL_COLOR,
	BLEND_EQUATION_HSL_LUMINOSITY,
	BLEND_EQUATION_ALL_EQUATIONS,

	BLEND_EQUATION_LAST
};

static const BlendEquation s_equations[] =
{
	BLEND_EQUATION_MULTIPLY,
	BLEND_EQUATION_SCREEN,
	BLEND_EQUATION_OVERLAY,
	BLEND_EQUATION_DARKEN,
	BLEND_EQUATION_LIGHTEN,
	BLEND_EQUATION_COLORDODGE,
	BLEND_EQUATION_COLORBURN,
	BLEND_EQUATION_HARDLIGHT,
	BLEND_EQUATION_SOFTLIGHT,
	BLEND_EQUATION_DIFFERENCE,
	BLEND_EQUATION_EXCLUSION,
	BLEND_EQUATION_HSL_HUE,
	BLEND_EQUATION_HSL_SATURATION,
	BLEND_EQUATION_HSL_COLOR,
	BLEND_EQUATION_HSL_LUMINOSITY
};

std::string getShaderLayoutEquation (BlendEquation equation)
{
	switch (equation)
	{
		case BLEND_EQUATION_MULTIPLY:          return "blend_support_multiply";
		case BLEND_EQUATION_SCREEN:            return "blend_support_screen";
		case BLEND_EQUATION_OVERLAY:           return "blend_support_overlay";
		case BLEND_EQUATION_DARKEN:            return "blend_support_darken";
		case BLEND_EQUATION_LIGHTEN:           return "blend_support_lighten";
		case BLEND_EQUATION_COLORDODGE:        return "blend_support_colordodge";
		case BLEND_EQUATION_COLORBURN:         return "blend_support_colorburn";
		case BLEND_EQUATION_HARDLIGHT:         return "blend_support_hardlight";
		case BLEND_EQUATION_SOFTLIGHT:         return "blend_support_softlight";
		case BLEND_EQUATION_DIFFERENCE:        return "blend_support_difference";
		case BLEND_EQUATION_EXCLUSION:         return "blend_support_exclusion";
		case BLEND_EQUATION_HSL_HUE:           return "blend_support_hsl_hue";
		case BLEND_EQUATION_HSL_SATURATION:    return "blend_support_hsl_saturation";
		case BLEND_EQUATION_HSL_COLOR:         return "blend_support_hsl_color";
		case BLEND_EQUATION_HSL_LUMINOSITY:    return "blend_support_hsl_luminosity";
		case BLEND_EQUATION_ALL_EQUATIONS:     return "blend_support_all_equations";
		default:
			DE_FATAL("Equation not supported.");
	}
	return DE_NULL;
}

glw::GLenum getEquation (BlendEquation equation)
{
	switch (equation)
	{
		case BLEND_EQUATION_MULTIPLY:          return GL_MULTIPLY;
		case BLEND_EQUATION_SCREEN:            return GL_SCREEN;
		case BLEND_EQUATION_OVERLAY:           return GL_OVERLAY;
		case BLEND_EQUATION_DARKEN:            return GL_DARKEN;
		case BLEND_EQUATION_LIGHTEN:           return GL_LIGHTEN;
		case BLEND_EQUATION_COLORDODGE:        return GL_COLORDODGE;
		case BLEND_EQUATION_COLORBURN:         return GL_COLORBURN;
		case BLEND_EQUATION_HARDLIGHT:         return GL_HARDLIGHT;
		case BLEND_EQUATION_SOFTLIGHT:         return GL_SOFTLIGHT;
		case BLEND_EQUATION_DIFFERENCE:        return GL_DIFFERENCE;
		case BLEND_EQUATION_EXCLUSION:         return GL_EXCLUSION;
		case BLEND_EQUATION_HSL_HUE:           return GL_HSL_HUE;
		case BLEND_EQUATION_HSL_SATURATION:    return GL_HSL_SATURATION;
		case BLEND_EQUATION_HSL_COLOR:         return GL_HSL_COLOR;
		case BLEND_EQUATION_HSL_LUMINOSITY:    return GL_HSL_LUMINOSITY;
		default:
			DE_FATAL("Equation not supported.");
	}
	return DE_NULL;
}

std::string generateVertexShaderSource (NegativeTestContext& ctx)
{
	const bool				isES32	= contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
	const glu::GLSLVersion	version	= isES32 ? glu::GLSL_VERSION_320_ES : glu::GLSL_VERSION_310_ES;
	std::ostringstream		source;

	source	<< glu::getGLSLVersionDeclaration(version) << "\n"
			<< "void main ()\n"
			<< "{\n"
			<< "	gl_Position = vec4(0.0);\n"
			<< "}\n";

	return source.str();
}

std::string generateFragmentShaderSource (NegativeTestContext& ctx, BlendEquation equation)
{
	const bool				isES32	= contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
	const glu::GLSLVersion	version	= isES32 ? glu::GLSL_VERSION_320_ES : glu::GLSL_VERSION_310_ES;
	std::ostringstream		source;

	source	<< glu::getGLSLVersionDeclaration(version) << "\n"
			<< (isES32 ? "" : "#extension GL_KHR_blend_equation_advanced : enable\n")
			<< "layout(" << getShaderLayoutEquation(equation) << ") out;\n"
			<< "layout(location=0) out mediump vec4 o_color;\n"
			<< "void main ()\n"
			<< "{\n"
			<< "	o_color = vec4(0);\n"
			<< "}\n";

	return source.str();
}

glu::ProgramSources generateProgramSources (NegativeTestContext& ctx, BlendEquation equation)
{
	return glu::ProgramSources()
		<< glu::VertexSource(generateVertexShaderSource(ctx))
		<< glu::FragmentSource(generateFragmentShaderSource(ctx, equation));
}

void blend_qualifier_mismatch (NegativeTestContext& ctx)
{
	TCU_CHECK_AND_THROW(NotSupportedError,
		ctx.isExtensionSupported("GL_KHR_blend_equation_advanced") || contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)),
		"This test requires support for the extension GL_KHR_blend_equation_advanced or context version 3.2 or higher.");

	ctx.beginSection("GL_INVALID_OPERATION is generated if blending is enabled, and the blend qualifier is different from blend_support_all_equations and does not match the blend equation.");
	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_equations); ++ndx)
	{
		glu::ShaderProgram program(ctx.getRenderContext(), generateProgramSources(ctx, s_equations[ndx]));

		ctx.getLog() << program;
		TCU_CHECK(program.isOk());

		ctx.glUseProgram(program.getProgram());
		ctx.expectError(GL_NO_ERROR);

		for (int ndx2 = 0; ndx2 < DE_LENGTH_OF_ARRAY(s_equations); ++ndx2)
		{
			if (s_equations[ndx] == s_equations[ndx2])
				continue;

			ctx.glEnable(GL_BLEND);
			ctx.glBlendEquation(getEquation(s_equations[ndx2]));
			ctx.expectError(GL_NO_ERROR);
			ctx.glDrawElements(GL_TRIANGLES, 0, GL_UNSIGNED_INT, 0);
			ctx.expectError(GL_INVALID_OPERATION);

			ctx.glDisable(GL_BLEND);
			ctx.glDrawElements(GL_TRIANGLES, 0, GL_UNSIGNED_INT, 0);
			ctx.expectError(GL_NO_ERROR);
		}
	}
	ctx.endSection();
}

void attachment_advanced_equation (NegativeTestContext& ctx)
{
	TCU_CHECK_AND_THROW(NotSupportedError,
		ctx.isExtensionSupported("GL_KHR_blend_equation_advanced") || contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)),
		"This test requires support for the extension GL_KHR_blend_equation_advanced or context version 3.2 or higher.");

	glw::GLuint			fbo				= 0x1234;
	glw::GLuint			texture			= 0x1234;
	const glw::GLenum	attachments[]	= { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };

	ctx.glGenTextures(1, &texture);
	ctx.glBindTexture(GL_TEXTURE_2D, texture);
	ctx.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
	ctx.glGenFramebuffers(1, &fbo);
	ctx.glBindFramebuffer(GL_FRAMEBUFFER, fbo);
	ctx.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
	ctx.expectError(GL_NO_ERROR);
	ctx.glCheckFramebufferStatus(GL_FRAMEBUFFER);

	ctx.beginSection("GL_INVALID_OPERATION is generated if blending is enabled, advanced equations are used, and the draw buffer for other color outputs is not NONE.");
	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_equations); ++ndx)
	{
		glu::ShaderProgram	program(ctx.getRenderContext(), generateProgramSources(ctx, s_equations[ndx]));
		ctx.getLog() << program;
		TCU_CHECK(program.isOk());

		ctx.glUseProgram(program.getProgram());
		ctx.glEnable(GL_BLEND);
		ctx.glDrawBuffers(2, attachments);
		ctx.expectError(GL_NO_ERROR);
		ctx.glBlendEquation(getEquation(s_equations[ndx]));
		ctx.glDrawElements(GL_TRIANGLES, 0, GL_UNSIGNED_INT, 0);
		ctx.expectError(GL_INVALID_OPERATION);
	}
	ctx.endSection();

	ctx.beginSection("GL_NO_ERROR is generated if no advanced blend equations are used.");
	ctx.glBlendEquation(GL_FUNC_ADD);
	ctx.glDrawElements(GL_TRIANGLES, 0, GL_UNSIGNED_INT, 0);
	ctx.expectError(GL_NO_ERROR);
	ctx.endSection();

	ctx.beginSection("GL_NO_ERROR is generated if blending is disabled.");
	ctx.glDisable(GL_BLEND);
	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_equations); ++ndx)
	{
		ctx.glBlendEquation(getEquation(s_equations[ndx]));
		ctx.glDrawElements(GL_TRIANGLES, 0, GL_UNSIGNED_INT, 0);
		ctx.expectError(GL_NO_ERROR);
	}
	ctx.endSection();

	ctx.glDeleteFramebuffers(1, &fbo);
	ctx.glDeleteTextures(1, &texture);
}

} // anonymous

std::vector<FunctionContainer> getNegativeAdvancedBlendEquationTestFunctions (void)
{
	const FunctionContainer funcs[] =
	{
		{blend_qualifier_mismatch,			"blend_qualifier_mismatch",			"Test blend qualifier mismatch."			},
		{attachment_advanced_equation,		"attachment_advanced_equation",		"Test draw buffer for other color outputs." },
	};

	return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
}

} // NegativeTestShared
} // Functional
} // gles31
} // deqp
<commit_msg>Multiple draw buffers in blend_equation_advanced am: 123de4f307<commit_after>/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES 3.1 Module
 * -------------------------------------------------
 *
 * Copyright 2016 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.
 *
 *//*!
 * \file
 * \brief Negative Advanced Blend Equation Tests
 *//*--------------------------------------------------------------------*/

#include "es31fNegativeAdvancedBlendEquationTests.hpp"

#include "gluShaderProgram.hpp"
#include "glwEnums.hpp"

namespace deqp
{
namespace gles31
{
namespace Functional
{
namespace NegativeTestShared
{
namespace
{

enum BlendEquation
{
	BLEND_EQUATION_MULTIPLY = 0,
	BLEND_EQUATION_SCREEN,
	BLEND_EQUATION_OVERLAY,
	BLEND_EQUATION_DARKEN,
	BLEND_EQUATION_LIGHTEN,
	BLEND_EQUATION_COLORDODGE,
	BLEND_EQUATION_COLORBURN,
	BLEND_EQUATION_HARDLIGHT,
	BLEND_EQUATION_SOFTLIGHT,
	BLEND_EQUATION_DIFFERENCE,
	BLEND_EQUATION_EXCLUSION,
	BLEND_EQUATION_HSL_HUE,
	BLEND_EQUATION_HSL_SATURATION,
	BLEND_EQUATION_HSL_COLOR,
	BLEND_EQUATION_HSL_LUMINOSITY,
	BLEND_EQUATION_ALL_EQUATIONS,

	BLEND_EQUATION_LAST
};

static const BlendEquation s_equations[] =
{
	BLEND_EQUATION_MULTIPLY,
	BLEND_EQUATION_SCREEN,
	BLEND_EQUATION_OVERLAY,
	BLEND_EQUATION_DARKEN,
	BLEND_EQUATION_LIGHTEN,
	BLEND_EQUATION_COLORDODGE,
	BLEND_EQUATION_COLORBURN,
	BLEND_EQUATION_HARDLIGHT,
	BLEND_EQUATION_SOFTLIGHT,
	BLEND_EQUATION_DIFFERENCE,
	BLEND_EQUATION_EXCLUSION,
	BLEND_EQUATION_HSL_HUE,
	BLEND_EQUATION_HSL_SATURATION,
	BLEND_EQUATION_HSL_COLOR,
	BLEND_EQUATION_HSL_LUMINOSITY
};

std::string getShaderLayoutEquation (BlendEquation equation)
{
	switch (equation)
	{
		case BLEND_EQUATION_MULTIPLY:          return "blend_support_multiply";
		case BLEND_EQUATION_SCREEN:            return "blend_support_screen";
		case BLEND_EQUATION_OVERLAY:           return "blend_support_overlay";
		case BLEND_EQUATION_DARKEN:            return "blend_support_darken";
		case BLEND_EQUATION_LIGHTEN:           return "blend_support_lighten";
		case BLEND_EQUATION_COLORDODGE:        return "blend_support_colordodge";
		case BLEND_EQUATION_COLORBURN:         return "blend_support_colorburn";
		case BLEND_EQUATION_HARDLIGHT:         return "blend_support_hardlight";
		case BLEND_EQUATION_SOFTLIGHT:         return "blend_support_softlight";
		case BLEND_EQUATION_DIFFERENCE:        return "blend_support_difference";
		case BLEND_EQUATION_EXCLUSION:         return "blend_support_exclusion";
		case BLEND_EQUATION_HSL_HUE:           return "blend_support_hsl_hue";
		case BLEND_EQUATION_HSL_SATURATION:    return "blend_support_hsl_saturation";
		case BLEND_EQUATION_HSL_COLOR:         return "blend_support_hsl_color";
		case BLEND_EQUATION_HSL_LUMINOSITY:    return "blend_support_hsl_luminosity";
		case BLEND_EQUATION_ALL_EQUATIONS:     return "blend_support_all_equations";
		default:
			DE_FATAL("Equation not supported.");
	}
	return DE_NULL;
}

glw::GLenum getEquation (BlendEquation equation)
{
	switch (equation)
	{
		case BLEND_EQUATION_MULTIPLY:          return GL_MULTIPLY;
		case BLEND_EQUATION_SCREEN:            return GL_SCREEN;
		case BLEND_EQUATION_OVERLAY:           return GL_OVERLAY;
		case BLEND_EQUATION_DARKEN:            return GL_DARKEN;
		case BLEND_EQUATION_LIGHTEN:           return GL_LIGHTEN;
		case BLEND_EQUATION_COLORDODGE:        return GL_COLORDODGE;
		case BLEND_EQUATION_COLORBURN:         return GL_COLORBURN;
		case BLEND_EQUATION_HARDLIGHT:         return GL_HARDLIGHT;
		case BLEND_EQUATION_SOFTLIGHT:         return GL_SOFTLIGHT;
		case BLEND_EQUATION_DIFFERENCE:        return GL_DIFFERENCE;
		case BLEND_EQUATION_EXCLUSION:         return GL_EXCLUSION;
		case BLEND_EQUATION_HSL_HUE:           return GL_HSL_HUE;
		case BLEND_EQUATION_HSL_SATURATION:    return GL_HSL_SATURATION;
		case BLEND_EQUATION_HSL_COLOR:         return GL_HSL_COLOR;
		case BLEND_EQUATION_HSL_LUMINOSITY:    return GL_HSL_LUMINOSITY;
		default:
			DE_FATAL("Equation not supported.");
	}
	return DE_NULL;
}

std::string generateVertexShaderSource (NegativeTestContext& ctx)
{
	const bool				isES32	= contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
	const glu::GLSLVersion	version	= isES32 ? glu::GLSL_VERSION_320_ES : glu::GLSL_VERSION_310_ES;
	std::ostringstream		source;

	source	<< glu::getGLSLVersionDeclaration(version) << "\n"
			<< "void main ()\n"
			<< "{\n"
			<< "	gl_Position = vec4(0.0);\n"
			<< "}\n";

	return source.str();
}

std::string generateFragmentShaderSource (NegativeTestContext& ctx, BlendEquation equation)
{
	const bool				isES32	= contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
	const glu::GLSLVersion	version	= isES32 ? glu::GLSL_VERSION_320_ES : glu::GLSL_VERSION_310_ES;
	std::ostringstream		source;

	source	<< glu::getGLSLVersionDeclaration(version) << "\n"
			<< (isES32 ? "" : "#extension GL_KHR_blend_equation_advanced : enable\n")
			<< "layout(" << getShaderLayoutEquation(equation) << ") out;\n"
			<< "layout(location=0) out mediump vec4 o_color;\n"
			<< "void main ()\n"
			<< "{\n"
			<< "	o_color = vec4(0);\n"
			<< "}\n";

	return source.str();
}

glu::ProgramSources generateProgramSources (NegativeTestContext& ctx, BlendEquation equation)
{
	return glu::ProgramSources()
		<< glu::VertexSource(generateVertexShaderSource(ctx))
		<< glu::FragmentSource(generateFragmentShaderSource(ctx, equation));
}

void blend_qualifier_mismatch (NegativeTestContext& ctx)
{
	TCU_CHECK_AND_THROW(NotSupportedError,
		ctx.isExtensionSupported("GL_KHR_blend_equation_advanced") || contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)),
		"This test requires support for the extension GL_KHR_blend_equation_advanced or context version 3.2 or higher.");

	ctx.beginSection("GL_INVALID_OPERATION is generated if blending is enabled, and the blend qualifier is different from blend_support_all_equations and does not match the blend equation.");
	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_equations); ++ndx)
	{
		glu::ShaderProgram program(ctx.getRenderContext(), generateProgramSources(ctx, s_equations[ndx]));

		ctx.getLog() << program;
		TCU_CHECK(program.isOk());

		ctx.glUseProgram(program.getProgram());
		ctx.expectError(GL_NO_ERROR);

		for (int ndx2 = 0; ndx2 < DE_LENGTH_OF_ARRAY(s_equations); ++ndx2)
		{
			if (s_equations[ndx] == s_equations[ndx2])
				continue;

			ctx.glEnable(GL_BLEND);
			ctx.glBlendEquation(getEquation(s_equations[ndx2]));
			ctx.expectError(GL_NO_ERROR);
			ctx.glDrawElements(GL_TRIANGLES, 0, GL_UNSIGNED_INT, 0);
			ctx.expectError(GL_INVALID_OPERATION);

			ctx.glDisable(GL_BLEND);
			ctx.glDrawElements(GL_TRIANGLES, 0, GL_UNSIGNED_INT, 0);
			ctx.expectError(GL_NO_ERROR);
		}
	}
	ctx.endSection();
}

void attachment_advanced_equation (NegativeTestContext& ctx)
{
	TCU_CHECK_AND_THROW(NotSupportedError,
		ctx.isExtensionSupported("GL_KHR_blend_equation_advanced") || contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)),
		"This test requires support for the extension GL_KHR_blend_equation_advanced or context version 3.2 or higher.");

	glw::GLuint			fbo				= 0x1234;
	glw::GLuint			texture			= 0x1234;
	const glw::GLenum	attachments[]	= { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };

	ctx.glGenTextures(1, &texture);
	ctx.glBindTexture(GL_TEXTURE_2D, texture);
	ctx.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
	ctx.glGenFramebuffers(1, &fbo);
	ctx.glBindFramebuffer(GL_FRAMEBUFFER, fbo);
	ctx.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
	ctx.expectError(GL_NO_ERROR);
	ctx.glCheckFramebufferStatus(GL_FRAMEBUFFER);

	ctx.beginSection("GL_INVALID_OPERATION is generated if blending is enabled, advanced equations are used, and the draw buffer for other color outputs is not NONE unless NVX_blend_equation_advanced_multi_draw_buffers is supported.");
	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_equations); ++ndx)
	{
		glu::ShaderProgram	program(ctx.getRenderContext(), generateProgramSources(ctx, s_equations[ndx]));
		ctx.getLog() << program;
		TCU_CHECK(program.isOk());

		ctx.glUseProgram(program.getProgram());
		ctx.glEnable(GL_BLEND);
		ctx.glDrawBuffers(2, attachments);
		ctx.expectError(GL_NO_ERROR);
		ctx.glBlendEquation(getEquation(s_equations[ndx]));
		ctx.glDrawElements(GL_TRIANGLES, 0, GL_UNSIGNED_INT, 0);
		if (ctx.isExtensionSupported("GL_NVX_blend_equation_advanced_multi_draw_buffers"))
			ctx.expectError(GL_NO_ERROR);
		else
			ctx.expectError(GL_INVALID_OPERATION);
	}
	ctx.endSection();

	ctx.beginSection("GL_NO_ERROR is generated if no advanced blend equations are used.");
	ctx.glBlendEquation(GL_FUNC_ADD);
	ctx.glDrawElements(GL_TRIANGLES, 0, GL_UNSIGNED_INT, 0);
	ctx.expectError(GL_NO_ERROR);
	ctx.endSection();

	ctx.beginSection("GL_NO_ERROR is generated if blending is disabled.");
	ctx.glDisable(GL_BLEND);
	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_equations); ++ndx)
	{
		ctx.glBlendEquation(getEquation(s_equations[ndx]));
		ctx.glDrawElements(GL_TRIANGLES, 0, GL_UNSIGNED_INT, 0);
		ctx.expectError(GL_NO_ERROR);
	}
	ctx.endSection();

	ctx.glDeleteFramebuffers(1, &fbo);
	ctx.glDeleteTextures(1, &texture);
}

} // anonymous

std::vector<FunctionContainer> getNegativeAdvancedBlendEquationTestFunctions (void)
{
	const FunctionContainer funcs[] =
	{
		{blend_qualifier_mismatch,			"blend_qualifier_mismatch",			"Test blend qualifier mismatch."			},
		{attachment_advanced_equation,		"attachment_advanced_equation",		"Test draw buffer for other color outputs." },
	};

	return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
}

} // NegativeTestShared
} // Functional
} // gles31
} // deqp
<|endoftext|>


<commit_before>// $Id: AliHLTCaloClusterAnalyser.cxx 35107 2009-09-30 01:45:06Z phille $

/**************************************************************************
 * This file is property of and copyright by the ALICE HLT Project        *
 * All rights reserved.                                                   *
 *                                                                        *
 * Primary Authors: Oystein Djuvsland                                     *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/**
 * @file   AliHLTCaloClusterAnalyser.cxx
 * @author Oystein Djuvsland
 * @date
 * @brief  Cluster analyser for Calo HLT
 */

// see header file for class documentation
// or
// refer to README to build package
// or
// visit http://web.ift.uib.no/~kjeks/doc/alice-hlt

#include "AliHLTCaloClusterAnalyser.h"
#include "AliHLTCaloRecPointHeaderStruct.h"
#include "AliHLTCaloRecPointDataStruct.h"
#include "AliHLTCaloClusterDataStruct.h"
//#include "AliHLTCaloPhysicsAnalyzer.h"
#include "AliHLTCaloGeometry.h"
#include "AliESDCaloCluster.h"
#include "TMath.h"
#include "TVector3.h"
#include "TH1F.h"
#include "TFile.h"
#include "AliHLTCaloRecoParamHandler.h"

ClassImp(AliHLTCaloClusterAnalyser);

AliHLTCaloClusterAnalyser::AliHLTCaloClusterAnalyser() :
  //  AliHLTCaloBase(),
  fLogWeight(4.5),
  fRecPointArray(0),
  fDigitDataArray(0),
  fNRecPoints(0),
  fCaloClusterDataPtr(0),
  fCaloClusterHeaderPtr(0),
  //fAnalyzerPtr(0),
  fDoClusterFit(false),
  fHaveCPVInfo(false),
  fDoPID(false),
  fHaveDistanceToBadChannel(false),
  fGeometry(0),
  fClusterType(AliESDCaloCluster::kPHOSCluster),
  fRecoParamsPtr(0),
  fCutOnSingleCellClusters(false),
  fSingleCellEnergyCut(0.5)
{
  //See header file for documentation
}

AliHLTCaloClusterAnalyser::~AliHLTCaloClusterAnalyser()
{
  // See header file for class documentation
}

void
AliHLTCaloClusterAnalyser::SetCaloClusterData(AliHLTCaloClusterDataStruct *caloClusterDataPtr)
{
  //see header file for documentation
  fCaloClusterDataPtr = caloClusterDataPtr;
}

void
AliHLTCaloClusterAnalyser::SetRecPointArray(AliHLTCaloRecPointDataStruct **recPointDataPtr, Int_t nRecPoints)
{
  fRecPointArray = recPointDataPtr;
  fNRecPoints = nRecPoints;
}

void
AliHLTCaloClusterAnalyser::SetDigitDataArray(AliHLTCaloDigitDataStruct **digits)
{
//   AliHLTCaloClusterizer cl("PHOS");
  // cl.CheckDigits(fRecPointArray, digits, fNRecPoints);
   fDigitDataArray = digits;
   //cl.CheckDigits(fRecPointArray, fDigitDataArray, fNRecPoints);
}

Int_t
AliHLTCaloClusterAnalyser::CalculateCenterOfGravity()
{
  //see header file for documentation
  Float_t wtot = 0.;
  Float_t x = 0.;
  Float_t z = 0.;
  Float_t xi = 0.;
  Float_t zi = 0.;

  AliHLTCaloDigitDataStruct *digit = 0;

  UInt_t iDigit = 0;

  for(Int_t iRecPoint=0; iRecPoint < fNRecPoints; iRecPoint++)
    {
      AliHLTCaloRecPointDataStruct *recPoint = fRecPointArray[iRecPoint];
      //      digit = &(recPoint->fDigits);

      Int_t *digitIndexPtr = &(recPoint->fDigits);
       wtot = 0;
       x = 0;
       z = 0;

/*       Float_t maxAmp = 0;
       Int_t maxX = 0;
       Int_t maxZ = 0;*/
      for(iDigit = 0; iDigit < recPoint->fMultiplicity; iDigit++)
	{

	  digit = fDigitDataArray[*digitIndexPtr];

	  xi = digit->fX+0.5;
	  zi = digit->fZ+0.5;

	  if (recPoint->fAmp > 0 && digit->fEnergy > 0)
	    {
	      Float_t w = TMath::Max( 0., fLogWeight + TMath::Log( digit->fEnergy / recPoint->fAmp ) ) ;
	      x    += xi * w ;
	      z    += zi * w ;
	      wtot += w ;
/*	      if(digit->fEnergy > maxAmp)
	      {
		 maxAmp = digit->fEnergy;
		 maxX = digit->fX;// + 0.5;
		 maxZ = digit->fZ;// + 0.5;
	      }*/
	    }
	  digitIndexPtr++;
	}

      if (wtot>0)
	{
	  recPoint->fX = x/wtot ;
	  recPoint->fZ = z/wtot ;
	}
      else
	{
	  recPoint->fAmp = 0;
	}
//	printf("Max digit: E = %f, x = %d, z= %d, cluster: E = %f, x = %f, z = %f\n" , maxAmp, maxX, maxZ, recPoint->fAmp, recPoint->fX, recPoint->fZ);
    }
  return 0;
}

Int_t
AliHLTCaloClusterAnalyser::CalculateRecPointMoments()
{
  //See header file for documentation
  return 0;
}

Int_t
AliHLTCaloClusterAnalyser::CalculateClusterMoments(AliHLTCaloRecPointDataStruct */*recPointPtr*/, AliHLTCaloClusterDataStruct* /*clusterPtr*/)
{
  //See header file for documentation
  return 0;
}

Int_t
AliHLTCaloClusterAnalyser::DeconvoluteClusters()
{
  //See header file for documentation
  return 0;
}

Int_t
AliHLTCaloClusterAnalyser::CreateClusters(Int_t nRecPoints, UInt_t availableSize, UInt_t& totSize)
{
  //See header file for documentation

   if(fRecoParamsPtr)
   {
      fLogWeight = fRecoParamsPtr->GetLogWeight();
   }

  fNRecPoints = nRecPoints;

  if(fGeometry == 0)
  {
     HLTError("No geometry object is initialised, creation of clusters stopped");
     return  -1;
  }

  CalculateCenterOfGravity();

  //  AliHLTCaloDigitDataStruct* digitPtr = &(recPointPtr->fDigits);
  AliHLTCaloDigitDataStruct* digitPtr = 0;

  AliHLTCaloClusterDataStruct* caloClusterPtr = 0;

  //  Int_t id = -1;
  TVector3 globalPos;

  for(Int_t i = 0; i < fNRecPoints; i++) //TODO needs fix when we start unfolding (number of clusters not necessarily same as number of recpoints gotten from the clusterizer
    {
      if((availableSize - totSize)  < sizeof(AliHLTCaloClusterDataStruct))
      {
	 HLTError("Out of buffer: available size is: %d, total size used: %d", availableSize, totSize);
	 return -ENOBUFS;
      }

      AliHLTCaloRecPointDataStruct *recPointPtr = fRecPointArray[i];

      if(fCutOnSingleCellClusters && recPointPtr->fAmp > fSingleCellEnergyCut && recPointPtr->fMultiplicity == 1) continue;

      totSize += sizeof(AliHLTCaloClusterDataStruct);

      caloClusterPtr = fCaloClusterDataPtr;
      caloClusterPtr->fChi2 = 0;
      caloClusterPtr->fClusterType = kUndef;
      caloClusterPtr->fDispersion = 0;
      caloClusterPtr->fDistanceToBadChannel = 0;
      caloClusterPtr->fDistToBadChannel = 0;
      caloClusterPtr->fEmcCpvDistance = 0;
      caloClusterPtr->fEnergy = 0;
      caloClusterPtr->fFitQuality = 0;
      caloClusterPtr->fID = 0;
      caloClusterPtr->fM02 = 0;
      caloClusterPtr->fM20 = 0;
      caloClusterPtr->fNCells = 0;
      caloClusterPtr->fNExMax = 0;
      caloClusterPtr->fTOF = 0;
      caloClusterPtr->fTrackDx = -999;
      caloClusterPtr->fTrackDz = -999;

      AliHLTCaloGlobalCoordinate globalCoord;
      fGeometry->GetGlobalCoordinates(*recPointPtr, globalCoord);

      caloClusterPtr->fModule = recPointPtr->fModule;
      caloClusterPtr->fGlobalPos[0] =  globalCoord.fX;
      caloClusterPtr->fGlobalPos[1] =  globalCoord.fY;
      caloClusterPtr->fGlobalPos[2] =  globalCoord.fZ;

      HLTError("Cluster local position: x = %f, z = %f, module = %d", recPointPtr->fX, recPointPtr->fZ, recPointPtr->fModule);
      HLTError("Cluster global position: x = %f, y = %f, z = %f", globalCoord.fX, globalCoord.fY, globalCoord.fZ);

      //caloClusterPtr->fNCells = 0;//recPointPtr->fMultiplicity;
      caloClusterPtr->fNCells = recPointPtr->fMultiplicity;

      caloClusterPtr->fClusterType = fClusterType;
//      Int_t tmpSize = 0;//totSize + (caloClusterPtr->fNCells-1)*(sizeof(Short_t) + sizeof(Float_t));

      //TODO remove hardcoded 10;
      memset(caloClusterPtr->fTracksMatched, 0xff, sizeof(Int_t)*10);

      //Int_t tmpSize = totSize + (caloClusterPtr->fNCells-1)*(sizeof(Short_t) + sizeof(Float_t));
      UInt_t tmpSize = (caloClusterPtr->fNCells-1)*sizeof(AliHLTCaloCellDataStruct);

      if((availableSize - totSize)  < tmpSize)
      {
	 HLTError("Out of buffer, available size is: %d, total size used: %d, extra size needed: %d", availableSize, totSize, tmpSize);
	 return -ENOBUFS;
      }

      Int_t *digitIndexPtr = &(recPointPtr->fDigits);
      Int_t id = 0;

       AliHLTCaloCellDataStruct *cellPtr = &(caloClusterPtr->fCaloCells);

      for(UInt_t j = 0; j < caloClusterPtr->fNCells; j++)
	{
 	   digitPtr = fDigitDataArray[*digitIndexPtr];
	   fGeometry->GetCellAbsId(recPointPtr->fModule, digitPtr->fX, digitPtr->fZ, id);

	  cellPtr->fCellsAbsId= id;
 	  cellPtr->fCellsAmpFraction = digitPtr->fEnergy/recPointPtr->fAmp;
	  //printf("Cell ID pointer: %x\n", cellIDPtr);
 	 //printf("Cell Amp Pointer: %x\n", cellAmpFracPtr);
	 //printf("Cell pos: x = %d, z = %d\n", digitPtr->fX, digitPtr->fZ);
//	 printf("Cell ID: %d\n", cellPtr->fCellsAbsId);
 	 //printf("Cell Amp: %f, pointer: %x\n", *cellAmpFracPtr, cellAmpFracPtr);
	  cellPtr++;
	  digitIndexPtr++;

	}

      totSize += tmpSize;

      if(fRecoParamsPtr)
      {
	 caloClusterPtr->fEnergy = fRecoParamsPtr->GetCorrectedEnergy(recPointPtr->fAmp);
      }
      else
      {
	 caloClusterPtr->fEnergy = recPointPtr->fAmp;
      }

      HLTDebug("Cluster global position: x = %f, y = %f, z = %f, energy: %f, number of cells: %d, cluster pointer: %x", globalCoord.fX, globalCoord.fY, globalCoord.fZ, caloClusterPtr->fEnergy, caloClusterPtr->fNCells,  caloClusterPtr);

      if(fDoClusterFit)
	{
	  FitCluster(recPointPtr);
	}
      else
	{
	  caloClusterPtr->fDispersion = 0;
	  caloClusterPtr->fFitQuality = 0;
	  caloClusterPtr->fM20 = 0;
	  caloClusterPtr->fM02 = 0;

	}
      if(fHaveCPVInfo)
	{
	  caloClusterPtr->fEmcCpvDistance = GetCPVDistance(recPointPtr);
	}
      else
	{
	  caloClusterPtr->fEmcCpvDistance = -1;
	}
      if(fDoPID)
	{
	  DoParticleIdentification(caloClusterPtr);
	}
      else
	{
	  for(Int_t k = 0; k < AliPID::kSPECIESN; k++)
	    {
	      caloClusterPtr->fPID[k] = 0;
	    }
	}
      if(fHaveDistanceToBadChannel)
	{
	  caloClusterPtr->fDistanceToBadChannel = GetDistanceToBadChannel(caloClusterPtr);
	}
      else
	{
	  caloClusterPtr->fDistanceToBadChannel = -1;
	}

      caloClusterPtr->fClusterType = fClusterType;
	  //totSize += sizeof(AliHLTCaloClusterDataStruct) + (caloClusterPtr->fNCells)*(sizeof(Short_t) +sizeof(Float_t)-1);
      //totSize += sizeof(AliHLTCaloClusterDataStruct) + (caloClusterPtr->fNCells-1)*(sizeof(Short_t) + sizeof(Float_t));
      //printf("CaloClusterPtr: %x, energy: %f\n", caloClusterPtr, caloClusterPtr->fEnergy);

      //      caloClusterPtr = reinterpret_cast<AliHLTCaloClusterDataStruct*>(cellAmpFracPtr);
      //caloClusterPtr = reinterpret_cast<AliHLTCaloClusterDataStruct*>(cellIDPtr);
      fCaloClusterDataPtr = reinterpret_cast<AliHLTCaloClusterDataStruct*>(cellPtr);
      recPointPtr = reinterpret_cast<AliHLTCaloRecPointDataStruct*>(digitPtr);
      //digitPtr = &(recPointPtr->fDigits);
    }

return fNRecPoints;

}

<commit_msg>- removing debug outout<commit_after>// $Id: AliHLTCaloClusterAnalyser.cxx 35107 2009-09-30 01:45:06Z phille $

/**************************************************************************
 * This file is property of and copyright by the ALICE HLT Project        *
 * All rights reserved.                                                   *
 *                                                                        *
 * Primary Authors: Oystein Djuvsland                                     *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/**
 * @file   AliHLTCaloClusterAnalyser.cxx
 * @author Oystein Djuvsland
 * @date
 * @brief  Cluster analyser for Calo HLT
 */

// see header file for class documentation
// or
// refer to README to build package
// or
// visit http://web.ift.uib.no/~kjeks/doc/alice-hlt

#include "AliHLTCaloClusterAnalyser.h"
#include "AliHLTCaloRecPointHeaderStruct.h"
#include "AliHLTCaloRecPointDataStruct.h"
#include "AliHLTCaloClusterDataStruct.h"
//#include "AliHLTCaloPhysicsAnalyzer.h"
#include "AliHLTCaloGeometry.h"
#include "AliESDCaloCluster.h"
#include "TMath.h"
#include "TVector3.h"
#include "TH1F.h"
#include "TFile.h"
#include "AliHLTCaloRecoParamHandler.h"

ClassImp(AliHLTCaloClusterAnalyser);

AliHLTCaloClusterAnalyser::AliHLTCaloClusterAnalyser() :
  //  AliHLTCaloBase(),
  fLogWeight(4.5),
  fRecPointArray(0),
  fDigitDataArray(0),
  fNRecPoints(0),
  fCaloClusterDataPtr(0),
  fCaloClusterHeaderPtr(0),
  //fAnalyzerPtr(0),
  fDoClusterFit(false),
  fHaveCPVInfo(false),
  fDoPID(false),
  fHaveDistanceToBadChannel(false),
  fGeometry(0),
  fClusterType(AliESDCaloCluster::kPHOSCluster),
  fRecoParamsPtr(0),
  fCutOnSingleCellClusters(false),
  fSingleCellEnergyCut(0.5)
{
  //See header file for documentation
}

AliHLTCaloClusterAnalyser::~AliHLTCaloClusterAnalyser()
{
  // See header file for class documentation
}

void
AliHLTCaloClusterAnalyser::SetCaloClusterData(AliHLTCaloClusterDataStruct *caloClusterDataPtr)
{
  //see header file for documentation
  fCaloClusterDataPtr = caloClusterDataPtr;
}

void
AliHLTCaloClusterAnalyser::SetRecPointArray(AliHLTCaloRecPointDataStruct **recPointDataPtr, Int_t nRecPoints)
{
  fRecPointArray = recPointDataPtr;
  fNRecPoints = nRecPoints;
}

void
AliHLTCaloClusterAnalyser::SetDigitDataArray(AliHLTCaloDigitDataStruct **digits)
{
//   AliHLTCaloClusterizer cl("PHOS");
  // cl.CheckDigits(fRecPointArray, digits, fNRecPoints);
   fDigitDataArray = digits;
   //cl.CheckDigits(fRecPointArray, fDigitDataArray, fNRecPoints);
}

Int_t
AliHLTCaloClusterAnalyser::CalculateCenterOfGravity()
{
  //see header file for documentation
  Float_t wtot = 0.;
  Float_t x = 0.;
  Float_t z = 0.;
  Float_t xi = 0.;
  Float_t zi = 0.;

  AliHLTCaloDigitDataStruct *digit = 0;

  UInt_t iDigit = 0;

  for(Int_t iRecPoint=0; iRecPoint < fNRecPoints; iRecPoint++)
    {
      AliHLTCaloRecPointDataStruct *recPoint = fRecPointArray[iRecPoint];
      //      digit = &(recPoint->fDigits);

      Int_t *digitIndexPtr = &(recPoint->fDigits);
       wtot = 0;
       x = 0;
       z = 0;

/*       Float_t maxAmp = 0;
       Int_t maxX = 0;
       Int_t maxZ = 0;*/
      for(iDigit = 0; iDigit < recPoint->fMultiplicity; iDigit++)
	{

	  digit = fDigitDataArray[*digitIndexPtr];

	  xi = digit->fX+0.5;
	  zi = digit->fZ+0.5;

	  if (recPoint->fAmp > 0 && digit->fEnergy > 0)
	    {
	      Float_t w = TMath::Max( 0., fLogWeight + TMath::Log( digit->fEnergy / recPoint->fAmp ) ) ;
	      x    += xi * w ;
	      z    += zi * w ;
	      wtot += w ;
/*	      if(digit->fEnergy > maxAmp)
	      {
		 maxAmp = digit->fEnergy;
		 maxX = digit->fX;// + 0.5;
		 maxZ = digit->fZ;// + 0.5;
	      }*/
	    }
	  digitIndexPtr++;
	}

      if (wtot>0)
	{
	  recPoint->fX = x/wtot ;
	  recPoint->fZ = z/wtot ;
	}
      else
	{
	  recPoint->fAmp = 0;
	}
//	printf("Max digit: E = %f, x = %d, z= %d, cluster: E = %f, x = %f, z = %f\n" , maxAmp, maxX, maxZ, recPoint->fAmp, recPoint->fX, recPoint->fZ);
    }
  return 0;
}

Int_t
AliHLTCaloClusterAnalyser::CalculateRecPointMoments()
{
  //See header file for documentation
  return 0;
}

Int_t
AliHLTCaloClusterAnalyser::CalculateClusterMoments(AliHLTCaloRecPointDataStruct */*recPointPtr*/, AliHLTCaloClusterDataStruct* /*clusterPtr*/)
{
  //See header file for documentation
  return 0;
}

Int_t
AliHLTCaloClusterAnalyser::DeconvoluteClusters()
{
  //See header file for documentation
  return 0;
}

Int_t
AliHLTCaloClusterAnalyser::CreateClusters(Int_t nRecPoints, UInt_t availableSize, UInt_t& totSize)
{
  //See header file for documentation

   if(fRecoParamsPtr)
   {
      fLogWeight = fRecoParamsPtr->GetLogWeight();
   }

  fNRecPoints = nRecPoints;

  if(fGeometry == 0)
  {
     HLTError("No geometry object is initialised, creation of clusters stopped");
     return  -1;
  }

  CalculateCenterOfGravity();

  //  AliHLTCaloDigitDataStruct* digitPtr = &(recPointPtr->fDigits);
  AliHLTCaloDigitDataStruct* digitPtr = 0;

  AliHLTCaloClusterDataStruct* caloClusterPtr = 0;

  //  Int_t id = -1;
  TVector3 globalPos;

  for(Int_t i = 0; i < fNRecPoints; i++) //TODO needs fix when we start unfolding (number of clusters not necessarily same as number of recpoints gotten from the clusterizer
    {
      if((availableSize - totSize)  < sizeof(AliHLTCaloClusterDataStruct))
      {
	 HLTError("Out of buffer: available size is: %d, total size used: %d", availableSize, totSize);
	 return -ENOBUFS;
      }

      AliHLTCaloRecPointDataStruct *recPointPtr = fRecPointArray[i];

      if(fCutOnSingleCellClusters && recPointPtr->fAmp > fSingleCellEnergyCut && recPointPtr->fMultiplicity == 1) continue;

      totSize += sizeof(AliHLTCaloClusterDataStruct);

      caloClusterPtr = fCaloClusterDataPtr;
      caloClusterPtr->fChi2 = 0;
      caloClusterPtr->fClusterType = kUndef;
      caloClusterPtr->fDispersion = 0;
      caloClusterPtr->fDistanceToBadChannel = 0;
      caloClusterPtr->fDistToBadChannel = 0;
      caloClusterPtr->fEmcCpvDistance = 0;
      caloClusterPtr->fEnergy = 0;
      caloClusterPtr->fFitQuality = 0;
      caloClusterPtr->fID = 0;
      caloClusterPtr->fM02 = 0;
      caloClusterPtr->fM20 = 0;
      caloClusterPtr->fNCells = 0;
      caloClusterPtr->fNExMax = 0;
      caloClusterPtr->fTOF = 0;
      caloClusterPtr->fTrackDx = -999;
      caloClusterPtr->fTrackDz = -999;

      AliHLTCaloGlobalCoordinate globalCoord;
      fGeometry->GetGlobalCoordinates(*recPointPtr, globalCoord);

      caloClusterPtr->fModule = recPointPtr->fModule;
      caloClusterPtr->fGlobalPos[0] =  globalCoord.fX;
      caloClusterPtr->fGlobalPos[1] =  globalCoord.fY;
      caloClusterPtr->fGlobalPos[2] =  globalCoord.fZ;

      HLTDebug("Cluster local position: x = %f, z = %f, module = %d", recPointPtr->fX, recPointPtr->fZ, recPointPtr->fModule);
      HLTDebug("Cluster global position: x = %f, y = %f, z = %f", globalCoord.fX, globalCoord.fY, globalCoord.fZ);

      //caloClusterPtr->fNCells = 0;//recPointPtr->fMultiplicity;
      caloClusterPtr->fNCells = recPointPtr->fMultiplicity;

      caloClusterPtr->fClusterType = fClusterType;
//      Int_t tmpSize = 0;//totSize + (caloClusterPtr->fNCells-1)*(sizeof(Short_t) + sizeof(Float_t));

      //TODO remove hardcoded 10;
      memset(caloClusterPtr->fTracksMatched, 0xff, sizeof(Int_t)*10);

      //Int_t tmpSize = totSize + (caloClusterPtr->fNCells-1)*(sizeof(Short_t) + sizeof(Float_t));
      UInt_t tmpSize = (caloClusterPtr->fNCells-1)*sizeof(AliHLTCaloCellDataStruct);

      if((availableSize - totSize)  < tmpSize)
      {
	 HLTError("Out of buffer, available size is: %d, total size used: %d, extra size needed: %d", availableSize, totSize, tmpSize);
	 return -ENOBUFS;
      }

      Int_t *digitIndexPtr = &(recPointPtr->fDigits);
      Int_t id = 0;

       AliHLTCaloCellDataStruct *cellPtr = &(caloClusterPtr->fCaloCells);

      for(UInt_t j = 0; j < caloClusterPtr->fNCells; j++)
	{
 	   digitPtr = fDigitDataArray[*digitIndexPtr];
	   fGeometry->GetCellAbsId(recPointPtr->fModule, digitPtr->fX, digitPtr->fZ, id);

	  cellPtr->fCellsAbsId= id;
 	  cellPtr->fCellsAmpFraction = digitPtr->fEnergy/recPointPtr->fAmp;
	  //printf("Cell ID pointer: %x\n", cellIDPtr);
 	 //printf("Cell Amp Pointer: %x\n", cellAmpFracPtr);
	 //printf("Cell pos: x = %d, z = %d\n", digitPtr->fX, digitPtr->fZ);
//	 printf("Cell ID: %d\n", cellPtr->fCellsAbsId);
 	 //printf("Cell Amp: %f, pointer: %x\n", *cellAmpFracPtr, cellAmpFracPtr);
	  cellPtr++;
	  digitIndexPtr++;

	}

      totSize += tmpSize;

      if(fRecoParamsPtr)
      {
	 caloClusterPtr->fEnergy = fRecoParamsPtr->GetCorrectedEnergy(recPointPtr->fAmp);
      }
      else
      {
	 caloClusterPtr->fEnergy = recPointPtr->fAmp;
      }

      HLTDebug("Cluster global position: x = %f, y = %f, z = %f, energy: %f, number of cells: %d, cluster pointer: %x", globalCoord.fX, globalCoord.fY, globalCoord.fZ, caloClusterPtr->fEnergy, caloClusterPtr->fNCells,  caloClusterPtr);

      if(fDoClusterFit)
	{
	  FitCluster(recPointPtr);
	}
      else
	{
	  caloClusterPtr->fDispersion = 0;
	  caloClusterPtr->fFitQuality = 0;
	  caloClusterPtr->fM20 = 0;
	  caloClusterPtr->fM02 = 0;

	}
      if(fHaveCPVInfo)
	{
	  caloClusterPtr->fEmcCpvDistance = GetCPVDistance(recPointPtr);
	}
      else
	{
	  caloClusterPtr->fEmcCpvDistance = -1;
	}
      if(fDoPID)
	{
	  DoParticleIdentification(caloClusterPtr);
	}
      else
	{
	  for(Int_t k = 0; k < AliPID::kSPECIESN; k++)
	    {
	      caloClusterPtr->fPID[k] = 0;
	    }
	}
      if(fHaveDistanceToBadChannel)
	{
	  caloClusterPtr->fDistanceToBadChannel = GetDistanceToBadChannel(caloClusterPtr);
	}
      else
	{
	  caloClusterPtr->fDistanceToBadChannel = -1;
	}

      caloClusterPtr->fClusterType = fClusterType;
	  //totSize += sizeof(AliHLTCaloClusterDataStruct) + (caloClusterPtr->fNCells)*(sizeof(Short_t) +sizeof(Float_t)-1);
      //totSize += sizeof(AliHLTCaloClusterDataStruct) + (caloClusterPtr->fNCells-1)*(sizeof(Short_t) + sizeof(Float_t));
      //printf("CaloClusterPtr: %x, energy: %f\n", caloClusterPtr, caloClusterPtr->fEnergy);

      //      caloClusterPtr = reinterpret_cast<AliHLTCaloClusterDataStruct*>(cellAmpFracPtr);
      //caloClusterPtr = reinterpret_cast<AliHLTCaloClusterDataStruct*>(cellIDPtr);
      fCaloClusterDataPtr = reinterpret_cast<AliHLTCaloClusterDataStruct*>(cellPtr);
      recPointPtr = reinterpret_cast<AliHLTCaloRecPointDataStruct*>(digitPtr);
      //digitPtr = &(recPointPtr->fDigits);
    }

return fNRecPoints;

}

<|endoftext|>


<commit_before>/*
   Copyright 2013 Jun Funada

   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 "FullScreen.h"
#include <Qt>
#include <QApplication>
#include <QPixmap>

Screen::Screen(QWidget* parent, Qt::WindowFlags f)
: QLabel(parent, f) {}

Screen::Screen(const QString& text, QWidget* parent, Qt::WindowFlags f)
: QLabel(text, parent, f) {}

void Screen::keyPressEvent(QKeyEvent* ev) {
	QLabel::keyPressEvent(ev);
	if (ev->key() == Qt::Key_Escape) {
		if (isFullScreen()) {
			showNormal();
			showMaximized();
		} else {
			showFullScreen();
		}
	}
}

int main(int argc, char** argv) {
  QApplication app(argc, argv);
	QPixmap pixmap("hoge.jpg");
  Screen screen;
  screen.setPixmap(pixmap);
  screen.showFullScreen();

	return app.exec();
}
<commit_msg>Fix Indentation Again<commit_after>/*
   Copyright 2013 Jun Funada

   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 "FullScreen.h"
#include <Qt>
#include <QApplication>
#include <QPixmap>

Screen::Screen(QWidget* parent, Qt::WindowFlags f)
: QLabel(parent, f) {}

Screen::Screen(const QString& text, QWidget* parent, Qt::WindowFlags f)
: QLabel(text, parent, f) {}

void Screen::keyPressEvent(QKeyEvent* ev) {
  QLabel::keyPressEvent(ev);
  if (ev->key() == Qt::Key_Escape) {
    if (isFullScreen()) {
      showNormal();
      showMaximized();
    } else {
      showFullScreen();
    }
  }
}

int main(int argc, char** argv) {
  QApplication app(argc, argv);
  QPixmap pixmap("hoge.jpg");
  Screen screen;
  screen.setPixmap(pixmap);
  screen.showFullScreen();

  return app.exec();
}
<|endoftext|>


<commit_before><commit_msg>ironed that shuffle bug<commit_after><|endoftext|>


<commit_before><commit_msg>Removed old includes.<commit_after><|endoftext|>


<commit_before>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#define EIGEN_USE_THREADS

#include "main.h"
#include <iostream>
#include <Eigen/CXX11/Tensor>

using Eigen::Tensor;

void test_multithread_elementwise()
{
  Tensor<float, 3> in1(2,3,7);
  Tensor<float, 3> in2(2,3,7);
  Tensor<float, 3> out(2,3,7);

  in1.setRandom();
  in2.setRandom();

  Eigen::ThreadPool tp(internal::random<int>(3, 11));
  Eigen::ThreadPoolDevice thread_pool_device(&tp, internal::random<int>(3, 11));
  out.device(thread_pool_device) = in1 + in2 * 3.14f;

  for (int i = 0; i < 2; ++i) {
    for (int j = 0; j < 3; ++j) {
      for (int k = 0; k < 7; ++k) {
        VERIFY_IS_APPROX(out(i,j,k), in1(i,j,k) + in2(i,j,k) * 3.14f);
      }
    }
  }
}

void test_multithread_compound_assignment()
{
  Tensor<float, 3> in1(2,3,7);
  Tensor<float, 3> in2(2,3,7);
  Tensor<float, 3> out(2,3,7);

  in1.setRandom();
  in2.setRandom();

  Eigen::ThreadPool tp(internal::random<int>(3, 11));
  Eigen::ThreadPoolDevice thread_pool_device(&tp, internal::random<int>(3, 11));
  out.device(thread_pool_device) = in1;
  out.device(thread_pool_device) += in2 * 3.14f;

  for (int i = 0; i < 2; ++i) {
    for (int j = 0; j < 3; ++j) {
      for (int k = 0; k < 7; ++k) {
        VERIFY_IS_APPROX(out(i,j,k), in1(i,j,k) + in2(i,j,k) * 3.14f);
      }
    }
  }
}

template<int DataLayout>
void test_multithread_contraction()
{
  Tensor<float, 4, DataLayout> t_left(30, 50, 37, 31);
  Tensor<float, 5, DataLayout> t_right(37, 31, 70, 2, 10);
  Tensor<float, 5, DataLayout> t_result(30, 50, 70, 2, 10);

  t_left.setRandom();
  t_right.setRandom();

  // this contraction should be equivalent to a single matrix multiplication
  typedef Tensor<float, 1>::DimensionPair DimPair;
  Eigen::array<DimPair, 2> dims({{DimPair(2, 0), DimPair(3, 1)}});

  typedef Map<Matrix<float, Dynamic, Dynamic, DataLayout>> MapXf;
  MapXf m_left(t_left.data(), 1500, 1147);
  MapXf m_right(t_right.data(), 1147, 1400);
  Matrix<float, Dynamic, Dynamic, DataLayout> m_result(1500, 1400);

  Eigen::ThreadPool tp(4);
  Eigen::ThreadPoolDevice thread_pool_device(&tp, 4);

  // compute results by separate methods
  t_result.device(thread_pool_device) = t_left.contract(t_right, dims);
  m_result = m_left * m_right;

 for (ptrdiff_t i = 0; i < t_result.size(); i++) {
    VERIFY(&t_result.data()[i] != &m_result.data()[i]);
    if (fabs(t_result.data()[i] - m_result.data()[i]) >= 1e-4) {
      std::cout << "mismatch detected: " << t_result.data()[i] << " vs " <<  m_result.data()[i] << std::endl;
      assert(false);
    }
  }
}

template<int DataLayout>
void test_contraction_corner_cases()
{
  Tensor<float, 2, DataLayout> t_left(32, 500);
  Tensor<float, 2, DataLayout> t_right(32, 28*28);
  Tensor<float, 2, DataLayout> t_result(500, 28*28);

  t_left = (t_left.constant(-0.5f) + t_left.random()) * 2.0f;
  t_right = (t_right.constant(-0.6f) + t_right.random()) * 2.0f;
  t_result = t_result.constant(NAN);

  // this contraction should be equivalent to a single matrix multiplication
  typedef Tensor<float, 1>::DimensionPair DimPair;
  Eigen::array<DimPair, 1> dims{{DimPair(0, 0)}};

  typedef Map<Matrix<float, Dynamic, Dynamic, DataLayout>> MapXf;
  MapXf m_left(t_left.data(), 32, 500);
  MapXf m_right(t_right.data(), 32, 28*28);
  Matrix<float, Dynamic, Dynamic, DataLayout> m_result(500, 28*28);

  Eigen::ThreadPool tp(12);
  Eigen::ThreadPoolDevice thread_pool_device(&tp, 12);

  // compute results by separate methods
  t_result.device(thread_pool_device) = t_left.contract(t_right, dims);
  m_result = m_left.transpose() * m_right;

  for (ptrdiff_t i = 0; i < t_result.size(); i++) {
    assert(!(numext::isnan)(t_result.data()[i]));
    if (fabs(t_result.data()[i] - m_result.data()[i]) >= 1e-4) {
      std::cout << "mismatch detected at index " << i << " : " << t_result.data()[i] << " vs " <<  m_result.data()[i] << std::endl;
      assert(false);
    }
  }

  t_left.resize(32, 1);
  t_left = (t_left.constant(-0.5f) + t_left.random()) * 2.0f;
  t_result.resize (1, 28*28);
  t_result = t_result.constant(NAN);
  t_result.device(thread_pool_device) = t_left.contract(t_right, dims);
  new(&m_left) MapXf(t_left.data(), 32, 1);
  m_result = m_left.transpose() * m_right;
  for (ptrdiff_t i = 0; i < t_result.size(); i++) {
    assert(!(numext::isnan)(t_result.data()[i]));
    if (fabs(t_result.data()[i] - m_result.data()[i]) >= 1e-4) {
      std::cout << "mismatch detected: " << t_result.data()[i] << " vs " <<  m_result.data()[i] << std::endl;
      assert(false);
    }
  }

  t_left.resize(32, 500);
  t_right.resize(32, 4);
  t_left = (t_left.constant(-0.5f) + t_left.random()) * 2.0f;
  t_right = (t_right.constant(-0.6f) + t_right.random()) * 2.0f;
  t_result.resize (500, 4);
  t_result = t_result.constant(NAN);
  t_result.device(thread_pool_device) = t_left.contract(t_right, dims);
  new(&m_left) MapXf(t_left.data(), 32, 500);
  new(&m_right) MapXf(t_right.data(), 32, 4);
  m_result = m_left.transpose() * m_right;
  for (ptrdiff_t i = 0; i < t_result.size(); i++) {
    assert(!(numext::isnan)(t_result.data()[i]));
    if (fabs(t_result.data()[i] - m_result.data()[i]) >= 1e-4) {
      std::cout << "mismatch detected: " << t_result.data()[i] << " vs " <<  m_result.data()[i] << std::endl;
      assert(false);
    }
  }

  t_left.resize(32, 1);
  t_right.resize(32, 4);
  t_left = (t_left.constant(-0.5f) + t_left.random()) * 2.0f;
  t_right = (t_right.constant(-0.6f) + t_right.random()) * 2.0f;
  t_result.resize (1, 4);
  t_result = t_result.constant(NAN);
  t_result.device(thread_pool_device) = t_left.contract(t_right, dims);
  new(&m_left) MapXf(t_left.data(), 32, 1);
  new(&m_right) MapXf(t_right.data(), 32, 4);
  m_result = m_left.transpose() * m_right;
  for (ptrdiff_t i = 0; i < t_result.size(); i++) {
    assert(!(numext::isnan)(t_result.data()[i]));
    if (fabs(t_result.data()[i] - m_result.data()[i]) >= 1e-4) {
      std::cout << "mismatch detected: " << t_result.data()[i] << " vs " <<  m_result.data()[i] << std::endl;
      assert(false);
    }
  }
}

template<int DataLayout>
void test_multithread_contraction_agrees_with_singlethread() {
  int contract_size = internal::random<int>(1, 5000);

  Tensor<float, 3, DataLayout> left(internal::random<int>(1, 80),
                                    contract_size,
                                    internal::random<int>(1, 100));

  Tensor<float, 4, DataLayout> right(internal::random<int>(1, 25),
                                     internal::random<int>(1, 37),
                                     contract_size,
                                     internal::random<int>(1, 51));

  left.setRandom();
  right.setRandom();

  // add constants to shift values away from 0 for more precision
  left += left.constant(1.5f);
  right += right.constant(1.5f);

  typedef Tensor<float, 1>::DimensionPair DimPair;
  Eigen::array<DimPair, 1> dims({{DimPair(1, 2)}});

  Eigen::ThreadPool tp(internal::random<int>(2, 11));
  Eigen::ThreadPoolDevice thread_pool_device(&tp, internal::random<int>(2, 11));

  Tensor<float, 5, DataLayout> st_result;
  st_result = left.contract(right, dims);

  Tensor<float, 5, DataLayout> tp_result(st_result.dimensions());
  tp_result.device(thread_pool_device) = left.contract(right, dims);

  VERIFY(dimensions_match(st_result.dimensions(), tp_result.dimensions()));
  for (ptrdiff_t i = 0; i < st_result.size(); i++) {
    // if both of the values are very small, then do nothing (because the test will fail
    // due to numerical precision issues when values are small)
    if (fabs(st_result.data()[i] - tp_result.data()[i]) >= 1e-4) {
      VERIFY_IS_APPROX(st_result.data()[i], tp_result.data()[i]);
    }
  }
}

template<int DataLayout>
void test_multithreaded_reductions() {
  const int num_threads = internal::random<int>(3, 11);
  ThreadPool thread_pool(num_threads);
  Eigen::ThreadPoolDevice thread_pool_device(&thread_pool, num_threads);

  const int num_rows = internal::random<int>(13, 732);
  const int num_cols = internal::random<int>(13, 732);
  Tensor<float, 2, DataLayout> t1(num_rows, num_cols);
  t1.setRandom();

  Tensor<float, 0, DataLayout> full_redux;
  full_redux = t1.sum();

  Tensor<float, 0, DataLayout> full_redux_tp;
  full_redux_tp.device(thread_pool_device) = t1.sum();

  // Check that the single threaded and the multi threaded reductions return
  // the same result.
  VERIFY_IS_APPROX(full_redux(), full_redux_tp());
}

void test_memcpy() {

  for (int i = 0; i < 5; ++i) {
    const int num_threads = internal::random<int>(3, 11);
    Eigen::ThreadPool tp(num_threads);
    Eigen::ThreadPoolDevice thread_pool_device(&tp, num_threads);

    const int size = internal::random<int>(13, 7632);
    Tensor<float, 1> t1(size);
    t1.setRandom();
    std::vector<float> result(size);
    thread_pool_device.memcpy(&result[0], t1.data(), size*sizeof(float));
    for (int j = 0; j < size; j++) {
      VERIFY_IS_EQUAL(t1(j), result[j]);
    }
  }
}

void test_multithread_random()
{
  Eigen::ThreadPool tp(2);
  Eigen::ThreadPoolDevice device(&tp, 2);
  Tensor<float, 1> t(1 << 20);
  t.device(device) = t.random<Eigen::internal::NormalRandomGenerator<float>>();
}

void test_cxx11_tensor_thread_pool()
{
  CALL_SUBTEST_1(test_multithread_elementwise());
  CALL_SUBTEST_1(test_multithread_compound_assignment());

  CALL_SUBTEST_2(test_multithread_contraction<ColMajor>());
  CALL_SUBTEST_2(test_multithread_contraction<RowMajor>());

  CALL_SUBTEST_3(test_multithread_contraction_agrees_with_singlethread<ColMajor>());
  CALL_SUBTEST_3(test_multithread_contraction_agrees_with_singlethread<RowMajor>());

  // Exercise various cases that have been problematic in the past.
  CALL_SUBTEST_4(test_contraction_corner_cases<ColMajor>());
  CALL_SUBTEST_4(test_contraction_corner_cases<RowMajor>());

  CALL_SUBTEST_5(test_multithreaded_reductions<ColMajor>());
  CALL_SUBTEST_5(test_multithreaded_reductions<RowMajor>());

  CALL_SUBTEST_6(test_memcpy());
  CALL_SUBTEST_6(test_multithread_random());
}
<commit_msg>Made the comparison between single and multithreaded contraction results more resistant to numerical noise to prevent spurious test failures.<commit_after>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#define EIGEN_USE_THREADS

#include "main.h"
#include <iostream>
#include <Eigen/CXX11/Tensor>

using Eigen::Tensor;

void test_multithread_elementwise()
{
  Tensor<float, 3> in1(2,3,7);
  Tensor<float, 3> in2(2,3,7);
  Tensor<float, 3> out(2,3,7);

  in1.setRandom();
  in2.setRandom();

  Eigen::ThreadPool tp(internal::random<int>(3, 11));
  Eigen::ThreadPoolDevice thread_pool_device(&tp, internal::random<int>(3, 11));
  out.device(thread_pool_device) = in1 + in2 * 3.14f;

  for (int i = 0; i < 2; ++i) {
    for (int j = 0; j < 3; ++j) {
      for (int k = 0; k < 7; ++k) {
        VERIFY_IS_APPROX(out(i,j,k), in1(i,j,k) + in2(i,j,k) * 3.14f);
      }
    }
  }
}

void test_multithread_compound_assignment()
{
  Tensor<float, 3> in1(2,3,7);
  Tensor<float, 3> in2(2,3,7);
  Tensor<float, 3> out(2,3,7);

  in1.setRandom();
  in2.setRandom();

  Eigen::ThreadPool tp(internal::random<int>(3, 11));
  Eigen::ThreadPoolDevice thread_pool_device(&tp, internal::random<int>(3, 11));
  out.device(thread_pool_device) = in1;
  out.device(thread_pool_device) += in2 * 3.14f;

  for (int i = 0; i < 2; ++i) {
    for (int j = 0; j < 3; ++j) {
      for (int k = 0; k < 7; ++k) {
        VERIFY_IS_APPROX(out(i,j,k), in1(i,j,k) + in2(i,j,k) * 3.14f);
      }
    }
  }
}

template<int DataLayout>
void test_multithread_contraction()
{
  Tensor<float, 4, DataLayout> t_left(30, 50, 37, 31);
  Tensor<float, 5, DataLayout> t_right(37, 31, 70, 2, 10);
  Tensor<float, 5, DataLayout> t_result(30, 50, 70, 2, 10);

  t_left.setRandom();
  t_right.setRandom();

  // this contraction should be equivalent to a single matrix multiplication
  typedef Tensor<float, 1>::DimensionPair DimPair;
  Eigen::array<DimPair, 2> dims({{DimPair(2, 0), DimPair(3, 1)}});

  typedef Map<Matrix<float, Dynamic, Dynamic, DataLayout>> MapXf;
  MapXf m_left(t_left.data(), 1500, 1147);
  MapXf m_right(t_right.data(), 1147, 1400);
  Matrix<float, Dynamic, Dynamic, DataLayout> m_result(1500, 1400);

  Eigen::ThreadPool tp(4);
  Eigen::ThreadPoolDevice thread_pool_device(&tp, 4);

  // compute results by separate methods
  t_result.device(thread_pool_device) = t_left.contract(t_right, dims);
  m_result = m_left * m_right;

 for (ptrdiff_t i = 0; i < t_result.size(); i++) {
    VERIFY(&t_result.data()[i] != &m_result.data()[i]);
    if (fabs(t_result(i) - m_result(i)) < 1e-4) {
      continue;
    }
    if (Eigen::internal::isApprox(t_result(i), m_result(i), 1e-4f)) {
      continue;
    }
    std::cout << "mismatch detected at index " << i << ": " << t_result(i)
              << " vs " <<  m_result(i) << std::endl;
    assert(false);
  }
}

template<int DataLayout>
void test_contraction_corner_cases()
{
  Tensor<float, 2, DataLayout> t_left(32, 500);
  Tensor<float, 2, DataLayout> t_right(32, 28*28);
  Tensor<float, 2, DataLayout> t_result(500, 28*28);

  t_left = (t_left.constant(-0.5f) + t_left.random()) * 2.0f;
  t_right = (t_right.constant(-0.6f) + t_right.random()) * 2.0f;
  t_result = t_result.constant(NAN);

  // this contraction should be equivalent to a single matrix multiplication
  typedef Tensor<float, 1>::DimensionPair DimPair;
  Eigen::array<DimPair, 1> dims{{DimPair(0, 0)}};

  typedef Map<Matrix<float, Dynamic, Dynamic, DataLayout>> MapXf;
  MapXf m_left(t_left.data(), 32, 500);
  MapXf m_right(t_right.data(), 32, 28*28);
  Matrix<float, Dynamic, Dynamic, DataLayout> m_result(500, 28*28);

  Eigen::ThreadPool tp(12);
  Eigen::ThreadPoolDevice thread_pool_device(&tp, 12);

  // compute results by separate methods
  t_result.device(thread_pool_device) = t_left.contract(t_right, dims);
  m_result = m_left.transpose() * m_right;

  for (ptrdiff_t i = 0; i < t_result.size(); i++) {
    assert(!(numext::isnan)(t_result.data()[i]));
    if (fabs(t_result.data()[i] - m_result.data()[i]) >= 1e-4) {
      std::cout << "mismatch detected at index " << i << " : " << t_result.data()[i] << " vs " <<  m_result.data()[i] << std::endl;
      assert(false);
    }
  }

  t_left.resize(32, 1);
  t_left = (t_left.constant(-0.5f) + t_left.random()) * 2.0f;
  t_result.resize (1, 28*28);
  t_result = t_result.constant(NAN);
  t_result.device(thread_pool_device) = t_left.contract(t_right, dims);
  new(&m_left) MapXf(t_left.data(), 32, 1);
  m_result = m_left.transpose() * m_right;
  for (ptrdiff_t i = 0; i < t_result.size(); i++) {
    assert(!(numext::isnan)(t_result.data()[i]));
    if (fabs(t_result.data()[i] - m_result.data()[i]) >= 1e-4) {
      std::cout << "mismatch detected: " << t_result.data()[i] << " vs " <<  m_result.data()[i] << std::endl;
      assert(false);
    }
  }

  t_left.resize(32, 500);
  t_right.resize(32, 4);
  t_left = (t_left.constant(-0.5f) + t_left.random()) * 2.0f;
  t_right = (t_right.constant(-0.6f) + t_right.random()) * 2.0f;
  t_result.resize (500, 4);
  t_result = t_result.constant(NAN);
  t_result.device(thread_pool_device) = t_left.contract(t_right, dims);
  new(&m_left) MapXf(t_left.data(), 32, 500);
  new(&m_right) MapXf(t_right.data(), 32, 4);
  m_result = m_left.transpose() * m_right;
  for (ptrdiff_t i = 0; i < t_result.size(); i++) {
    assert(!(numext::isnan)(t_result.data()[i]));
    if (fabs(t_result.data()[i] - m_result.data()[i]) >= 1e-4) {
      std::cout << "mismatch detected: " << t_result.data()[i] << " vs " <<  m_result.data()[i] << std::endl;
      assert(false);
    }
  }

  t_left.resize(32, 1);
  t_right.resize(32, 4);
  t_left = (t_left.constant(-0.5f) + t_left.random()) * 2.0f;
  t_right = (t_right.constant(-0.6f) + t_right.random()) * 2.0f;
  t_result.resize (1, 4);
  t_result = t_result.constant(NAN);
  t_result.device(thread_pool_device) = t_left.contract(t_right, dims);
  new(&m_left) MapXf(t_left.data(), 32, 1);
  new(&m_right) MapXf(t_right.data(), 32, 4);
  m_result = m_left.transpose() * m_right;
  for (ptrdiff_t i = 0; i < t_result.size(); i++) {
    assert(!(numext::isnan)(t_result.data()[i]));
    if (fabs(t_result.data()[i] - m_result.data()[i]) >= 1e-4) {
      std::cout << "mismatch detected: " << t_result.data()[i] << " vs " <<  m_result.data()[i] << std::endl;
      assert(false);
    }
  }
}

template<int DataLayout>
void test_multithread_contraction_agrees_with_singlethread() {
  int contract_size = internal::random<int>(1, 5000);

  Tensor<float, 3, DataLayout> left(internal::random<int>(1, 80),
                                    contract_size,
                                    internal::random<int>(1, 100));

  Tensor<float, 4, DataLayout> right(internal::random<int>(1, 25),
                                     internal::random<int>(1, 37),
                                     contract_size,
                                     internal::random<int>(1, 51));

  left.setRandom();
  right.setRandom();

  // add constants to shift values away from 0 for more precision
  left += left.constant(1.5f);
  right += right.constant(1.5f);

  typedef Tensor<float, 1>::DimensionPair DimPair;
  Eigen::array<DimPair, 1> dims({{DimPair(1, 2)}});

  Eigen::ThreadPool tp(internal::random<int>(2, 11));
  Eigen::ThreadPoolDevice thread_pool_device(&tp, internal::random<int>(2, 11));

  Tensor<float, 5, DataLayout> st_result;
  st_result = left.contract(right, dims);

  Tensor<float, 5, DataLayout> tp_result(st_result.dimensions());
  tp_result.device(thread_pool_device) = left.contract(right, dims);

  VERIFY(dimensions_match(st_result.dimensions(), tp_result.dimensions()));
  for (ptrdiff_t i = 0; i < st_result.size(); i++) {
    // if both of the values are very small, then do nothing (because the test will fail
    // due to numerical precision issues when values are small)
    if (fabs(st_result.data()[i] - tp_result.data()[i]) >= 1e-4) {
      VERIFY_IS_APPROX(st_result.data()[i], tp_result.data()[i]);
    }
  }
}

template<int DataLayout>
void test_multithreaded_reductions() {
  const int num_threads = internal::random<int>(3, 11);
  ThreadPool thread_pool(num_threads);
  Eigen::ThreadPoolDevice thread_pool_device(&thread_pool, num_threads);

  const int num_rows = internal::random<int>(13, 732);
  const int num_cols = internal::random<int>(13, 732);
  Tensor<float, 2, DataLayout> t1(num_rows, num_cols);
  t1.setRandom();

  Tensor<float, 0, DataLayout> full_redux;
  full_redux = t1.sum();

  Tensor<float, 0, DataLayout> full_redux_tp;
  full_redux_tp.device(thread_pool_device) = t1.sum();

  // Check that the single threaded and the multi threaded reductions return
  // the same result.
  VERIFY_IS_APPROX(full_redux(), full_redux_tp());
}

void test_memcpy() {

  for (int i = 0; i < 5; ++i) {
    const int num_threads = internal::random<int>(3, 11);
    Eigen::ThreadPool tp(num_threads);
    Eigen::ThreadPoolDevice thread_pool_device(&tp, num_threads);

    const int size = internal::random<int>(13, 7632);
    Tensor<float, 1> t1(size);
    t1.setRandom();
    std::vector<float> result(size);
    thread_pool_device.memcpy(&result[0], t1.data(), size*sizeof(float));
    for (int j = 0; j < size; j++) {
      VERIFY_IS_EQUAL(t1(j), result[j]);
    }
  }
}

void test_multithread_random()
{
  Eigen::ThreadPool tp(2);
  Eigen::ThreadPoolDevice device(&tp, 2);
  Tensor<float, 1> t(1 << 20);
  t.device(device) = t.random<Eigen::internal::NormalRandomGenerator<float>>();
}

void test_cxx11_tensor_thread_pool()
{
  CALL_SUBTEST_1(test_multithread_elementwise());
  CALL_SUBTEST_1(test_multithread_compound_assignment());

  CALL_SUBTEST_2(test_multithread_contraction<ColMajor>());
  CALL_SUBTEST_2(test_multithread_contraction<RowMajor>());

  CALL_SUBTEST_3(test_multithread_contraction_agrees_with_singlethread<ColMajor>());
  CALL_SUBTEST_3(test_multithread_contraction_agrees_with_singlethread<RowMajor>());

  // Exercise various cases that have been problematic in the past.
  CALL_SUBTEST_4(test_contraction_corner_cases<ColMajor>());
  CALL_SUBTEST_4(test_contraction_corner_cases<RowMajor>());

  CALL_SUBTEST_5(test_multithreaded_reductions<ColMajor>());
  CALL_SUBTEST_5(test_multithreaded_reductions<RowMajor>());

  CALL_SUBTEST_6(test_memcpy());
  CALL_SUBTEST_6(test_multithread_random());
}
<|endoftext|>


<commit_before>/**
*  Copyright (C) 2017 3D Repo Ltd
*
*  This program is free software: you can redistribute it and/or modify
*  it under the terms of the GNU Affero General Public License as
*  published by the Free Software Foundation, either version 3 of the
*  License, or (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU Affero General Public License for more details.
*
*  You should have received a copy of the GNU Affero General Public License
*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "c_sharp_wrapper.h"
#include <repo/core/model/bson/repo_node_material.h>
#include <repo/core/model/bson/repo_node_texture.h>
#include <repo/lib/repo_exception.h>
#include <boost/filesystem.hpp>
#include <fstream>

using namespace repo::lib;

CSharpWrapper* CSharpWrapper::wrapper = nullptr;

CSharpWrapper::CSharpWrapper()
	: controller(new repo::RepoController()),
	token(nullptr),
	scene(nullptr),
	vrEnabled(false)
{
}

CSharpWrapper::~CSharpWrapper()
{
	if (controller)
	{
		repoInfo << "Deconstructing the controller.";
		if (token)
			controller->destroyToken(token);
		if (scene)
			delete scene;
		delete controller;

	}

}

bool CSharpWrapper::connect(
	const std::string &config
)
{
	std::string msg;
	try {
		token = controller->init(msg, repo::lib::RepoConfig::fromFile(config));
		return token;
	} catch(const repo::lib::RepoException &exception) {
		return false;
	}
}

void CSharpWrapper::freeSuperMesh(
		const int &index)
{

	if (superMeshes.size() > index && superMeshes[index] != nullptr)
	{
		superMeshes[index] = nullptr;
	}
}

void CSharpWrapper::getIdMapBuffer(
	const int &index,
	const int &smIndex,
	float* &idMap) const
{
	if (idMapBuf.size() > index && idMapBuf[index].size() > smIndex)
	{
		memcpy(idMap, idMapBuf[index][smIndex].data(), sizeof(*idMap) * idMapBuf[index][smIndex].size());
	}
}

CSharpWrapper* CSharpWrapper::getInstance()
{
	if (!wrapper) {
		wrapper = new CSharpWrapper();
	}
	return wrapper;
}

void CSharpWrapper::destroyInstance() {
	if(wrapper) {
		delete wrapper;
	}
}

void CSharpWrapper::getMaterialInfo(
	const std::string &materialID,
	float* &diffuse,
	float* &specular,
	float* &shininess,
	float* &shininessStrength) const
{
	auto it = matNodes.find(materialID);
	if (it != matNodes.end())
	{
		*shininess = 0;
		*shininessStrength = 1;
		if (it->second.shininess == it->second.shininess)
			*shininess = it->second.shininess;
		if (it->second.shininessStrength == it->second.shininessStrength)
			*shininessStrength = it->second.shininessStrength;

		for (size_t i = 0; i < 3; i++)
		{
			diffuse[i] = 0.5;
			specular[i] = 0;
		}

		for (size_t i = 0; i < it->second.diffuse.size(); i++)
		{
			diffuse[i] = it->second.diffuse[i];
		}

		for (size_t i = 0; i < it->second.specular.size(); i++)
		{
			specular[i] = it->second.specular[i];
		}

		diffuse[3] = it->second.opacity;
	}
}

std::string CSharpWrapper::getOrgMeshInfoFromSubMesh(
	const int &index,
	const int &smIndex,
	const int &orgMeshIdx,
	int* &smFFrom,
	int* &smFTo) const
{
	std::string matID;
	if (meshMappings.size() > index &&
		meshMappings[index].size() > smIndex &&
		meshMappings[index][smIndex].size() > orgMeshIdx)
	{
		*smFFrom = meshMappings[index][smIndex][orgMeshIdx].triFrom;
		*smFTo = meshMappings[index][smIndex][orgMeshIdx].triTo;
		matID = meshMappings[index][smIndex][orgMeshIdx].material_id.toString();
	}

	return matID;
}

int CSharpWrapper::getNumSuperMeshes() const
{
	return superMeshes.size();
}

std::string CSharpWrapper::getRevisionList(
	const std::string &database,
	const std::string &project)
{
	auto revs = controller->getAllFromCollectionContinuous(token, database, project + ".history");
	repoTrace << "Trying to find revisions for " << database << "." << project;
	std::stringstream ss;
	bool first = true;
	for(const auto rev : revs)
	{
		auto id = repo::core::model::RepoNode(rev).getUniqueID().toString();
		if(first)
		{
			ss << id ;
			first = false;
		}
		else
		{
			ss << "," << id;
		}
	}

	return ss.str();
}

void CSharpWrapper::getSuperMeshBuffers(
	const int &index,
	float* &vertices,
	float* &normals,
	uint16_t* &faces,
	float* &uvs,
	int* &numOrgMeshes) const
{
	if (superMeshes.size() > index)
	{
		auto vBuf = superMeshes[index]->getVertices();
		size_t vByteSize = sizeof(*vBuf.data()) * vBuf.size();
		memcpy(vertices, vBuf.data(), vByteSize);
		auto normalsBuf = superMeshes[index]->getNormals();
		if(normalsBuf.size())
			memcpy(normals, normalsBuf.data(), vByteSize);
		memcpy(faces, serialisedFaceBuf[index].data(), sizeof(*serialisedFaceBuf[index].data()) * serialisedFaceBuf[index].size());

		auto uvs_in = superMeshes[index]->getUVChannelsSeparated();
		if (uvs_in.size())
		{
			memcpy(uvs, uvs_in[0].data(), sizeof(*uvs_in[0].data()) * uvs_in[0].size());
		}

		for (int i = 0; i < meshMappings[index].size(); ++i)
		{
			numOrgMeshes[i] = meshMappings[index][i].size();
		}

	}
}

void CSharpWrapper::getSubMeshInfo(const int &index,
	const int &subIdx,
	int32_t* &vFrom,
	int32_t* &vTo,
	int32_t* &fFrom,
	int32_t* &fTo) const
{
	if (superMeshes.size() > index)
	{
		auto smMapping = superMeshes[index]->getMeshMapping();
		if (smMapping.size() > subIdx)
		{
			auto mapping = smMapping[subIdx];
			*vFrom = mapping.vertFrom;
			*vTo = mapping.vertTo;
			*fFrom = mapping.triFrom;
			*fTo = mapping.triTo;
		}
	}
}

std::string CSharpWrapper::getSuperMeshInfo(
	const int &index,
	long* &subMeshes,
	long* &numVertices,
	long* &numFaces,
	bool* &hasNormals,
	bool* &hasUV,
	int* &primitiveType,
	int* &numMappings) const
{
	std::string res;
	if (superMeshes.size() > index)
	{
		*subMeshes = superMeshes[index]->getMeshMapping().size();
		*numVertices = superMeshes[index]->getVertices().size();
		*numFaces = superMeshes[index]->getFaces().size();
		*hasUV = superMeshes[index]->getUVChannels().size();
		*hasNormals = superMeshes[index]->getNormals().size();
		*primitiveType = static_cast<int>(superMeshes[index]->getPrimitive());
		*numMappings = numIdMappings[index];
		res = superMeshes[index]->getUniqueID().toString();
	}

	return res;
}

void CSharpWrapper::getTexture(
	char* materialID,
	char* texBuf) const
{
	auto it = matToTexture.find(materialID);
	if (it != matToTexture.end())
	{
		memcpy(texBuf, it->second.data(), sizeof(*texBuf) * it->second.size());
	}
}

std::string CSharpWrapper::getVersion() const
{
	std::stringstream ss;
	ss << "3D Repo Bouncer Version: " + controller->getVersion();
	return ss.str();
}

int CSharpWrapper::hasTexture(
	const std::string &materialID) const
{
	int res = -1;
	auto it = matToTexture.find(materialID);
	if (it != matToTexture.end())
	{
		res = it->second.size();
	}
	return res;
}

bool CSharpWrapper::initialiseSceneForAssetBundle(
	const std::string &database,
	const std::string &project,
	const std::string &revisionID)
{
	//clean up last job's data if available
	superMeshes.clear();
	jsonFiles.clear();
	serialisedFaceBuf.clear();
	idMapBuf.clear();
	meshMappings.clear();
	matNodes.clear();
	matToTexture.clear();
	numIdMappings.clear();

	if(scene)
		delete scene;

	if(revisionID.empty())
		scene = controller->fetchScene(token, database, project, REPO_HISTORY_MASTER_BRANCH, true,
				true, false, false, { repo::core::model::RevisionNode::UploadStatus::MISSING_BUNDLES });
	else
		scene = controller->fetchScene(token, database, project, revisionID, false,
				true, false, false, { repo::core::model::RevisionNode::UploadStatus::MISSING_BUNDLES });
	bool success  = false;
	if (scene)
	{
		projectName = project;
		databaseName = database;
		vrEnabled = controller->isVREnabled(token, scene);
		superMeshes = controller->initialiseAssetBuffer(token, scene, jsonFiles, unityAssets, serialisedFaceBuf, idMapBuf, meshMappings);
		success = superMeshes.size();

		// Get the total number of mappings contained in this supermesh. This is needed ahead of time to build things like textures.
		// We could consider passing this from the AssetModelExport in the future.

		for (auto splitMeshIdMap : idMapBuf) {
			numIdMappings.push_back(splitMeshIdMap.back().back() + 1);
		}

		//We dont' need the scene anymore
		for (auto mat : scene->getAllMaterials(repo::core::model::RepoScene::GraphType::OPTIMIZED))
		{
			auto matNode = dynamic_cast<repo::core::model::MaterialNode*>(mat);
			matNodes[mat->getUniqueID().toString()] = matNode->getMaterialStruct();
			auto textureChildren = scene->getChildrenNodesFiltered(
				repo::core::model::RepoScene::GraphType::OPTIMIZED,
				mat->getSharedID(),
				repo::core::model::NodeType::TEXTURE
				);
			if (textureChildren.size())
			{
				//There can only be 1 texture per material
				auto textNode = dynamic_cast<repo::core::model::TextureNode*>(textureChildren[0]);
				matToTexture[mat->getUniqueID().toString()] = textNode->getRawData();
			}
		}
		scene->clearStash();
	}

	return success;
}

bool CSharpWrapper::isVREnabled()
{
	return vrEnabled;
}

bool CSharpWrapper::isFederation(
				const std::string &database,
				const std::string &project) const
{
	auto tempScene = controller->fetchScene(token, database, project, REPO_HISTORY_MASTER_BRANCH, true, true);
	return tempScene && tempScene->getAllReferences(repo::core::model::RepoScene::GraphType::DEFAULT).size() > 0;
}

bool CSharpWrapper::saveAssetBundles(
	char** assetFiles,
	int      length
	)
{
	repo_web_buffers_t webBuffers;
	webBuffers.jsonFiles = jsonFiles;
	webBuffers.unityAssets = unityAssets;
	for (int i = 0; i < length; ++i)
	{
		std::ifstream inputStream;

		inputStream.open(assetFiles[i], std::ios::in | std::ios::binary);

		if (inputStream.is_open())
		{
			std::ostringstream ss;
			ss << inputStream.rdbuf();
			auto s = ss.str();
			boost::filesystem::path path(assetFiles[i]);
			std::string fileName = path.filename().string();
			fileName = "/" + databaseName + "/" + projectName + "/" + fileName;
			webBuffers.geoFiles[fileName] = std::vector<uint8_t>(s.begin(), s.end());
		}
		else
		{
			repoError << "Failed to find asset bundle";
			return false;
		}
	}

	return controller->commitAssetBundleBuffers(token, scene, webBuffers);
}
<commit_msg>Revert "ISSUE #531 debug message"<commit_after>/**
*  Copyright (C) 2017 3D Repo Ltd
*
*  This program is free software: you can redistribute it and/or modify
*  it under the terms of the GNU Affero General Public License as
*  published by the Free Software Foundation, either version 3 of the
*  License, or (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU Affero General Public License for more details.
*
*  You should have received a copy of the GNU Affero General Public License
*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "c_sharp_wrapper.h"
#include <repo/core/model/bson/repo_node_material.h>
#include <repo/core/model/bson/repo_node_texture.h>
#include <repo/lib/repo_exception.h>
#include <boost/filesystem.hpp>
#include <fstream>

using namespace repo::lib;

CSharpWrapper* CSharpWrapper::wrapper = nullptr;

CSharpWrapper::CSharpWrapper()
	: controller(new repo::RepoController()),
	token(nullptr),
	scene(nullptr),
	vrEnabled(false)
{
}

CSharpWrapper::~CSharpWrapper()
{
	if (controller)
	{
		if (token)
			controller->destroyToken(token);
		if (scene)
			delete scene;
		delete controller;

	}

}

bool CSharpWrapper::connect(
	const std::string &config
)
{
	std::string msg;
	try {
		token = controller->init(msg, repo::lib::RepoConfig::fromFile(config));
		return token;
	} catch(const repo::lib::RepoException &exception) {
		return false;
	}
}

void CSharpWrapper::freeSuperMesh(
		const int &index)
{

	if (superMeshes.size() > index && superMeshes[index] != nullptr)
	{
		superMeshes[index] = nullptr;
	}
}

void CSharpWrapper::getIdMapBuffer(
	const int &index,
	const int &smIndex,
	float* &idMap) const
{
	if (idMapBuf.size() > index && idMapBuf[index].size() > smIndex)
	{
		memcpy(idMap, idMapBuf[index][smIndex].data(), sizeof(*idMap) * idMapBuf[index][smIndex].size());
	}
}

CSharpWrapper* CSharpWrapper::getInstance()
{
	if (!wrapper) {
		wrapper = new CSharpWrapper();
	}
	return wrapper;
}

void CSharpWrapper::destroyInstance() {
	if(wrapper) {
		delete wrapper;
	}
}

void CSharpWrapper::getMaterialInfo(
	const std::string &materialID,
	float* &diffuse,
	float* &specular,
	float* &shininess,
	float* &shininessStrength) const
{
	auto it = matNodes.find(materialID);
	if (it != matNodes.end())
	{
		*shininess = 0;
		*shininessStrength = 1;
		if (it->second.shininess == it->second.shininess)
			*shininess = it->second.shininess;
		if (it->second.shininessStrength == it->second.shininessStrength)
			*shininessStrength = it->second.shininessStrength;

		for (size_t i = 0; i < 3; i++)
		{
			diffuse[i] = 0.5;
			specular[i] = 0;
		}

		for (size_t i = 0; i < it->second.diffuse.size(); i++)
		{
			diffuse[i] = it->second.diffuse[i];
		}

		for (size_t i = 0; i < it->second.specular.size(); i++)
		{
			specular[i] = it->second.specular[i];
		}

		diffuse[3] = it->second.opacity;
	}
}

std::string CSharpWrapper::getOrgMeshInfoFromSubMesh(
	const int &index,
	const int &smIndex,
	const int &orgMeshIdx,
	int* &smFFrom,
	int* &smFTo) const
{
	std::string matID;
	if (meshMappings.size() > index &&
		meshMappings[index].size() > smIndex &&
		meshMappings[index][smIndex].size() > orgMeshIdx)
	{
		*smFFrom = meshMappings[index][smIndex][orgMeshIdx].triFrom;
		*smFTo = meshMappings[index][smIndex][orgMeshIdx].triTo;
		matID = meshMappings[index][smIndex][orgMeshIdx].material_id.toString();
	}

	return matID;
}

int CSharpWrapper::getNumSuperMeshes() const
{
	return superMeshes.size();
}

std::string CSharpWrapper::getRevisionList(
	const std::string &database,
	const std::string &project)
{
	auto revs = controller->getAllFromCollectionContinuous(token, database, project + ".history");
	repoTrace << "Trying to find revisions for " << database << "." << project;
	std::stringstream ss;
	bool first = true;
	for(const auto rev : revs)
	{
		auto id = repo::core::model::RepoNode(rev).getUniqueID().toString();
		if(first)
		{
			ss << id ;
			first = false;
		}
		else
		{
			ss << "," << id;
		}
	}

	return ss.str();
}

void CSharpWrapper::getSuperMeshBuffers(
	const int &index,
	float* &vertices,
	float* &normals,
	uint16_t* &faces,
	float* &uvs,
	int* &numOrgMeshes) const
{
	if (superMeshes.size() > index)
	{
		auto vBuf = superMeshes[index]->getVertices();
		size_t vByteSize = sizeof(*vBuf.data()) * vBuf.size();
		memcpy(vertices, vBuf.data(), vByteSize);
		auto normalsBuf = superMeshes[index]->getNormals();
		if(normalsBuf.size())
			memcpy(normals, normalsBuf.data(), vByteSize);
		memcpy(faces, serialisedFaceBuf[index].data(), sizeof(*serialisedFaceBuf[index].data()) * serialisedFaceBuf[index].size());

		auto uvs_in = superMeshes[index]->getUVChannelsSeparated();
		if (uvs_in.size())
		{
			memcpy(uvs, uvs_in[0].data(), sizeof(*uvs_in[0].data()) * uvs_in[0].size());
		}

		for (int i = 0; i < meshMappings[index].size(); ++i)
		{
			numOrgMeshes[i] = meshMappings[index][i].size();
		}

	}
}

void CSharpWrapper::getSubMeshInfo(const int &index,
	const int &subIdx,
	int32_t* &vFrom,
	int32_t* &vTo,
	int32_t* &fFrom,
	int32_t* &fTo) const
{
	if (superMeshes.size() > index)
	{
		auto smMapping = superMeshes[index]->getMeshMapping();
		if (smMapping.size() > subIdx)
		{
			auto mapping = smMapping[subIdx];
			*vFrom = mapping.vertFrom;
			*vTo = mapping.vertTo;
			*fFrom = mapping.triFrom;
			*fTo = mapping.triTo;
		}
	}
}

std::string CSharpWrapper::getSuperMeshInfo(
	const int &index,
	long* &subMeshes,
	long* &numVertices,
	long* &numFaces,
	bool* &hasNormals,
	bool* &hasUV,
	int* &primitiveType,
	int* &numMappings) const
{
	std::string res;
	if (superMeshes.size() > index)
	{
		*subMeshes = superMeshes[index]->getMeshMapping().size();
		*numVertices = superMeshes[index]->getVertices().size();
		*numFaces = superMeshes[index]->getFaces().size();
		*hasUV = superMeshes[index]->getUVChannels().size();
		*hasNormals = superMeshes[index]->getNormals().size();
		*primitiveType = static_cast<int>(superMeshes[index]->getPrimitive());
		*numMappings = numIdMappings[index];
		res = superMeshes[index]->getUniqueID().toString();
	}

	return res;
}

void CSharpWrapper::getTexture(
	char* materialID,
	char* texBuf) const
{
	auto it = matToTexture.find(materialID);
	if (it != matToTexture.end())
	{
		memcpy(texBuf, it->second.data(), sizeof(*texBuf) * it->second.size());
	}
}

std::string CSharpWrapper::getVersion() const
{
	std::stringstream ss;
	ss << "3D Repo Bouncer Version: " + controller->getVersion();
	return ss.str();
}

int CSharpWrapper::hasTexture(
	const std::string &materialID) const
{
	int res = -1;
	auto it = matToTexture.find(materialID);
	if (it != matToTexture.end())
	{
		res = it->second.size();
	}
	return res;
}

bool CSharpWrapper::initialiseSceneForAssetBundle(
	const std::string &database,
	const std::string &project,
	const std::string &revisionID)
{
	//clean up last job's data if available
	superMeshes.clear();
	jsonFiles.clear();
	serialisedFaceBuf.clear();
	idMapBuf.clear();
	meshMappings.clear();
	matNodes.clear();
	matToTexture.clear();
	numIdMappings.clear();

	if(scene)
		delete scene;

	if(revisionID.empty())
		scene = controller->fetchScene(token, database, project, REPO_HISTORY_MASTER_BRANCH, true,
				true, false, false, { repo::core::model::RevisionNode::UploadStatus::MISSING_BUNDLES });
	else
		scene = controller->fetchScene(token, database, project, revisionID, false,
				true, false, false, { repo::core::model::RevisionNode::UploadStatus::MISSING_BUNDLES });
	bool success  = false;
	if (scene)
	{
		projectName = project;
		databaseName = database;
		vrEnabled = controller->isVREnabled(token, scene);
		superMeshes = controller->initialiseAssetBuffer(token, scene, jsonFiles, unityAssets, serialisedFaceBuf, idMapBuf, meshMappings);
		success = superMeshes.size();

		// Get the total number of mappings contained in this supermesh. This is needed ahead of time to build things like textures.
		// We could consider passing this from the AssetModelExport in the future.

		for (auto splitMeshIdMap : idMapBuf) {
			numIdMappings.push_back(splitMeshIdMap.back().back() + 1);
		}

		//We dont' need the scene anymore
		for (auto mat : scene->getAllMaterials(repo::core::model::RepoScene::GraphType::OPTIMIZED))
		{
			auto matNode = dynamic_cast<repo::core::model::MaterialNode*>(mat);
			matNodes[mat->getUniqueID().toString()] = matNode->getMaterialStruct();
			auto textureChildren = scene->getChildrenNodesFiltered(
				repo::core::model::RepoScene::GraphType::OPTIMIZED,
				mat->getSharedID(),
				repo::core::model::NodeType::TEXTURE
				);
			if (textureChildren.size())
			{
				//There can only be 1 texture per material
				auto textNode = dynamic_cast<repo::core::model::TextureNode*>(textureChildren[0]);
				matToTexture[mat->getUniqueID().toString()] = textNode->getRawData();
			}
		}
		scene->clearStash();
	}

	return success;
}

bool CSharpWrapper::isVREnabled()
{
	return vrEnabled;
}

bool CSharpWrapper::isFederation(
				const std::string &database,
				const std::string &project) const
{
	auto tempScene = controller->fetchScene(token, database, project, REPO_HISTORY_MASTER_BRANCH, true, true);
	return tempScene && tempScene->getAllReferences(repo::core::model::RepoScene::GraphType::DEFAULT).size() > 0;
}

bool CSharpWrapper::saveAssetBundles(
	char** assetFiles,
	int      length
	)
{
	repo_web_buffers_t webBuffers;
	webBuffers.jsonFiles = jsonFiles;
	webBuffers.unityAssets = unityAssets;
	for (int i = 0; i < length; ++i)
	{
		std::ifstream inputStream;

		inputStream.open(assetFiles[i], std::ios::in | std::ios::binary);

		if (inputStream.is_open())
		{
			std::ostringstream ss;
			ss << inputStream.rdbuf();
			auto s = ss.str();
			boost::filesystem::path path(assetFiles[i]);
			std::string fileName = path.filename().string();
			fileName = "/" + databaseName + "/" + projectName + "/" + fileName;
			webBuffers.geoFiles[fileName] = std::vector<uint8_t>(s.begin(), s.end());
		}
		else
		{
			repoError << "Failed to find asset bundle";
			return false;
		}
	}

	return controller->commitAssetBundleBuffers(token, scene, webBuffers);
}
<|endoftext|>


<commit_before>#include <cstdio>
#include <fstream>
#include <unistd.h>

#include <kms++.h>
#include <kms++util.h>

using namespace std;
using namespace kms;

static void read_frame(ifstream& is, DumbFramebuffer* fb, Crtc* crtc, Plane* plane)
{
	for (unsigned i = 0; i < fb->num_planes(); ++i)
		is.read((char*)fb->map(i), fb->size(i));

	unsigned w = min(crtc->width(), fb->width());
	unsigned h = min(crtc->height(), fb->height());

	int r = crtc->set_plane(plane, *fb,
				0, 0, w, h,
				0, 0, fb->width(), fb->height());

	ASSERT(r == 0);
}

int main(int argc, char** argv)
{
	if (argc != 5) {
		printf("Usage: %s <file> <width> <height> <fourcc>\n", argv[0]);
		return -1;
	}

	string filename = argv[1];
	uint32_t w = stoi(argv[2]);
	uint32_t h = stoi(argv[3]);
	string modestr = argv[4];

	auto pixfmt = FourCCToPixelFormat(modestr);

	ifstream is(filename, ifstream::binary);

	is.seekg(0, std::ios::end);
	unsigned fsize = is.tellg();
	is.seekg(0);

	Card card;

	auto conn = card.get_first_connected_connector();
	auto crtc = conn->get_current_crtc();

	auto fb = new DumbFramebuffer(card, w, h, pixfmt);

	Plane* plane = 0;

	for (Plane* p : crtc->get_possible_planes()) {
		if (p->plane_type() != PlaneType::Overlay)
			continue;

		if (!p->supports_format(pixfmt))
			continue;

		plane = p;
		break;
	}

	FAIL_IF(!plane, "available plane not found");

	unsigned frame_size = 0;
	for (unsigned i = 0; i < fb->num_planes(); ++i)
		frame_size += fb->size(i);

	unsigned num_frames = fsize / frame_size;
	printf("file size %u, frame size %u, frames %u\n", fsize, frame_size, num_frames);

	for (unsigned i = 0; i < num_frames; ++i) {
		printf("frame %d\n", i);
		read_frame(is, fb, crtc, plane);
		usleep(1000*50);
	}

	printf("press enter to exit\n");

	is.close();

	getchar();

	delete fb;
}
<commit_msg>kmsview: small improvements<commit_after>#include <cstdio>
#include <fstream>
#include <unistd.h>

#include <kms++.h>
#include <kms++util.h>
#include <opts.h>

using namespace std;
using namespace kms;

static void read_frame(ifstream& is, DumbFramebuffer* fb, Crtc* crtc, Plane* plane)
{
	for (unsigned i = 0; i < fb->num_planes(); ++i)
		is.read((char*)fb->map(i), fb->size(i));

	unsigned w = min(crtc->width(), fb->width());
	unsigned h = min(crtc->height(), fb->height());

	int r = crtc->set_plane(plane, *fb,
				0, 0, w, h,
				0, 0, fb->width(), fb->height());

	ASSERT(r == 0);
}

static const char* usage_str =
		"Usage: kmsview [-t <ms>] <file> <width> <height> <fourcc>\n\n"
		"Options:\n"
		"  -t, --time        Milliseconds to sleep between frames\n"
		;

static void usage()
{
	puts(usage_str);
}

int main(int argc, char** argv)
{
	uint32_t time = 0;
	string dev_path = "/dev/dri/card0";

	OptionSet optionset = {
		Option("|device=", [&dev_path](string s)
		{
			dev_path = s;
		}),
		Option("t|time=", [&time](const string& str)
		{
			time = stoul(str);
		}),
		Option("h|help", []()
		{
			usage();
			exit(-1);
		}),
	};

	optionset.parse(argc, argv);

	vector<string> params = optionset.params();

	if (params.size() != 4) {
		usage();
		exit(-1);
	}

	string filename = params[0];
	uint32_t w = stoi(params[1]);
	uint32_t h = stoi(params[2]);
	string modestr = params[3];

	auto pixfmt = FourCCToPixelFormat(modestr);

	ifstream is(filename, ifstream::binary);

	is.seekg(0, std::ios::end);
	unsigned fsize = is.tellg();
	is.seekg(0);

	Card card(dev_path);

	auto conn = card.get_first_connected_connector();
	auto crtc = conn->get_current_crtc();

	auto fb = new DumbFramebuffer(card, w, h, pixfmt);

	Plane* plane = 0;

	for (Plane* p : crtc->get_possible_planes()) {
		if (p->plane_type() != PlaneType::Overlay)
			continue;

		if (!p->supports_format(pixfmt))
			continue;

		plane = p;
		break;
	}

	FAIL_IF(!plane, "available plane not found");

	unsigned frame_size = 0;
	for (unsigned i = 0; i < fb->num_planes(); ++i)
		frame_size += fb->size(i);

	unsigned num_frames = fsize / frame_size;
	printf("file size %u, frame size %u, frames %u\n", fsize, frame_size, num_frames);

	for (unsigned i = 0; i < num_frames; ++i) {
		printf("frame %d", i); fflush(stdout);
		read_frame(is, fb, crtc, plane);
		if (!time) {
			getchar();
		} else {
			usleep(time * 1000);
			printf("\n");
		}
	}

	is.close();

	if (time) {
		printf("press enter to exit\n");
		getchar();
	}

	delete fb;
}
<|endoftext|>