/*-------------------------------------------------------------------------
 * drawElements Quality Program Tester Core
 * ----------------------------------------
 *
 * Copyright 2014 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 Fuzzy image comparison.
 *//*--------------------------------------------------------------------*/

#include "tcuFuzzyImageCompare.hpp"
#include "tcuTexture.hpp"
#include "tcuTextureUtil.hpp"
#include "deMath.h"
#include "deRandom.hpp"

#include <vector>

namespace tcu
{

enum
{
	MIN_ERR_THRESHOLD	= 4 // Magic to make small differences go away
};

using std::vector;

template<int Channel>
static inline deUint8 getChannel (deUint32 color)
{
	return (deUint8)((color >> (Channel*8)) & 0xff);
}

static inline deUint8 getChannel (deUint32 color, int channel)
{
	return (deUint8)((color >> (channel*8)) & 0xff);
}

static inline deUint32 setChannel (deUint32 color, int channel, deUint8 val)
{
	return (color & ~(0xffu << (8*channel))) | (val << (8*channel));
}

static inline Vec4 toFloatVec (deUint32 color)
{
	return Vec4((float)getChannel<0>(color), (float)getChannel<1>(color), (float)getChannel<2>(color), (float)getChannel<3>(color));
}

static inline deUint8 roundToUint8Sat (float v)
{
	return (deUint8)de::clamp((int)(v + 0.5f), 0, 255);
}

static inline deUint32 toColor (Vec4 v)
{
	return roundToUint8Sat(v[0]) | (roundToUint8Sat(v[1]) << 8) | (roundToUint8Sat(v[2]) << 16) | (roundToUint8Sat(v[3]) << 24);
}

template<int NumChannels>
static inline deUint32 readUnorm8 (const tcu::ConstPixelBufferAccess& src, int x, int y)
{
	const deUint8*	ptr	= (const deUint8*)src.getDataPtr() + src.getRowPitch()*y + x*NumChannels;
	deUint32		v	= 0;

	for (int c = 0; c < NumChannels; c++)
		v |= ptr[c] << (c*8);

	if (NumChannels < 4)
		v |= 0xffu << 24;

	return v;
}

#if (DE_ENDIANNESS == DE_LITTLE_ENDIAN)
template<>
inline deUint32 readUnorm8<4> (const tcu::ConstPixelBufferAccess& src, int x, int y)
{
	return *(const deUint32*)((const deUint8*)src.getDataPtr() + src.getRowPitch()*y + x*4);
}
#endif

template<int NumChannels>
static inline void writeUnorm8 (const tcu::PixelBufferAccess& dst, int x, int y, deUint32 val)
{
	deUint8* ptr = (deUint8*)dst.getDataPtr() + dst.getRowPitch()*y + x*NumChannels;

	for (int c = 0; c < NumChannels; c++)
		ptr[c] = getChannel(val, c);
}

#if (DE_ENDIANNESS == DE_LITTLE_ENDIAN)
template<>
inline void writeUnorm8<4> (const tcu::PixelBufferAccess& dst, int x, int y, deUint32 val)
{
	*(deUint32*)((deUint8*)dst.getDataPtr() + dst.getRowPitch()*y + x*4) = val;
}
#endif

static inline deUint32 colorDistSquared (deUint32 pa, deUint32 pb)
{
	const int	r	= de::max<int>(de::abs((int)getChannel<0>(pa) - (int)getChannel<0>(pb)) - MIN_ERR_THRESHOLD, 0);
	const int	g	= de::max<int>(de::abs((int)getChannel<1>(pa) - (int)getChannel<1>(pb)) - MIN_ERR_THRESHOLD, 0);
	const int	b	= de::max<int>(de::abs((int)getChannel<2>(pa) - (int)getChannel<2>(pb)) - MIN_ERR_THRESHOLD, 0);
	const int	a	= de::max<int>(de::abs((int)getChannel<3>(pa) - (int)getChannel<3>(pb)) - MIN_ERR_THRESHOLD, 0);

	return deUint32(r*r + g*g + b*b + a*a);
}

template<int NumChannels>
inline deUint32 bilinearSample (const ConstPixelBufferAccess& src, float u, float v)
{
	int w = src.getWidth();
	int h = src.getHeight();

	int x0 = deFloorFloatToInt32(u-0.5f);
	int x1 = x0+1;
	int y0 = deFloorFloatToInt32(v-0.5f);
	int y1 = y0+1;

	int i0 = de::clamp(x0, 0, w-1);
	int i1 = de::clamp(x1, 0, w-1);
	int j0 = de::clamp(y0, 0, h-1);
	int j1 = de::clamp(y1, 0, h-1);

	float a = deFloatFrac(u-0.5f);
	float b = deFloatFrac(v-0.5f);

	deUint32 p00	= readUnorm8<NumChannels>(src, i0, j0);
	deUint32 p10	= readUnorm8<NumChannels>(src, i1, j0);
	deUint32 p01	= readUnorm8<NumChannels>(src, i0, j1);
	deUint32 p11	= readUnorm8<NumChannels>(src, i1, j1);
	deUint32 dst	= 0;

	// Interpolate.
	for (int c = 0; c < NumChannels; c++)
	{
		float f = (getChannel(p00, c)*(1.0f-a)*(1.0f-b)) +
				  (getChannel(p10, c)*(     a)*(1.0f-b)) +
				  (getChannel(p01, c)*(1.0f-a)*(     b)) +
				  (getChannel(p11, c)*(     a)*(     b));
		dst = setChannel(dst, c, roundToUint8Sat(f));
	}

	return dst;
}

template<int DstChannels, int SrcChannels>
static void separableConvolve (const PixelBufferAccess& dst, const ConstPixelBufferAccess& src, int shiftX, int shiftY, const std::vector<float>& kernelX, const std::vector<float>& kernelY)
{
	DE_ASSERT(dst.getWidth() == src.getWidth() && dst.getHeight() == src.getHeight());

	TextureLevel		tmp			(dst.getFormat(), dst.getHeight(), dst.getWidth());
	PixelBufferAccess	tmpAccess	= tmp.getAccess();

	int kw = (int)kernelX.size();
	int kh = (int)kernelY.size();

	// Horizontal pass
	// \note Temporary surface is written in column-wise order
	for (int j = 0; j < src.getHeight(); j++)
	{
		for (int i = 0; i < src.getWidth(); i++)
		{
			Vec4 sum(0);

			for (int kx = 0; kx < kw; kx++)
			{
				float		f = kernelX[kw-kx-1];
				deUint32	p = readUnorm8<SrcChannels>(src, de::clamp(i+kx-shiftX, 0, src.getWidth()-1), j);

				sum += toFloatVec(p)*f;
			}

			writeUnorm8<DstChannels>(tmpAccess, j, i, toColor(sum));
		}
	}

	// Vertical pass
	for (int j = 0; j < src.getHeight(); j++)
	{
		for (int i = 0; i < src.getWidth(); i++)
		{
			Vec4 sum(0.0f);

			for (int ky = 0; ky < kh; ky++)
			{
				float		f = kernelY[kh-ky-1];
				deUint32	p = readUnorm8<DstChannels>(tmpAccess, de::clamp(j+ky-shiftY, 0, tmp.getWidth()-1), i);

				sum += toFloatVec(p)*f;
			}

			writeUnorm8<DstChannels>(dst, i, j, toColor(sum));
		}
	}
}

template<int NumChannels>
static deUint32 distSquaredToNeighbor (de::Random& rnd, deUint32 pixel, const ConstPixelBufferAccess& surface, int x, int y)
{
	// (x, y) + (0, 0)
	deUint32	minDist		= colorDistSquared(pixel, readUnorm8<NumChannels>(surface, x, y));

	if (minDist == 0)
		return minDist;

	// Area around (x, y)
	static const int s_coords[8][2] =
	{
		{-1, -1},
		{ 0, -1},
		{+1, -1},
		{-1,  0},
		{+1,  0},
		{-1, +1},
		{ 0, +1},
		{+1, +1}
	};

	for (int d = 0; d < (int)DE_LENGTH_OF_ARRAY(s_coords); d++)
	{
		int dx = x + s_coords[d][0];
		int dy = y + s_coords[d][1];

		if (!deInBounds32(dx, 0, surface.getWidth()) || !deInBounds32(dy, 0, surface.getHeight()))
			continue;

		minDist = de::min(minDist, colorDistSquared(pixel, readUnorm8<NumChannels>(surface, dx, dy)));
		if (minDist == 0)
			return minDist;
	}

	// Random bilinear-interpolated samples around (x, y)
	for (int s = 0; s < 32; s++)
	{
		float dx = (float)x + rnd.getFloat()*2.0f - 0.5f;
		float dy = (float)y + rnd.getFloat()*2.0f - 0.5f;

		deUint32 sample = bilinearSample<NumChannels>(surface, dx, dy);

		minDist = de::min(minDist, colorDistSquared(pixel, sample));
		if (minDist == 0)
			return minDist;
	}

	return minDist;
}

static inline float toGrayscale (const Vec4& c)
{
	return 0.2126f*c[0] + 0.7152f*c[1] + 0.0722f*c[2];
}

static bool isFormatSupported (const TextureFormat& format)
{
	return format.type == TextureFormat::UNORM_INT8 && (format.order == TextureFormat::RGB || format.order == TextureFormat::RGBA);
}

float fuzzyCompare (const FuzzyCompareParams& params, const ConstPixelBufferAccess& ref, const ConstPixelBufferAccess& cmp, const PixelBufferAccess& errorMask)
{
	DE_ASSERT(ref.getWidth() == cmp.getWidth() && ref.getHeight() == cmp.getHeight());
	DE_ASSERT(errorMask.getWidth() == ref.getWidth() && errorMask.getHeight() == ref.getHeight());

	if (!isFormatSupported(ref.getFormat()) || !isFormatSupported(cmp.getFormat()))
		throw InternalError("Unsupported format in fuzzy comparison", DE_NULL, __FILE__, __LINE__);

	int			width	= ref.getWidth();
	int			height	= ref.getHeight();
	de::Random	rnd		(667);

	// Filtered
	TextureLevel refFiltered(TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), width, height);
	TextureLevel cmpFiltered(TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), width, height);

	// Kernel = {0.1, 0.8, 0.1}
	vector<float> kernel(3);
	kernel[0] = kernel[2] = 0.1f; kernel[1]= 0.8f;
	int shift = (int)(kernel.size() - 1) / 2;

	switch (ref.getFormat().order)
	{
		case TextureFormat::RGBA:	separableConvolve<4, 4>(refFiltered, ref, shift, shift, kernel, kernel);	break;
		case TextureFormat::RGB:	separableConvolve<4, 3>(refFiltered, ref, shift, shift, kernel, kernel);	break;
		default:
			DE_ASSERT(DE_FALSE);
	}

	switch (cmp.getFormat().order)
	{
		case TextureFormat::RGBA:	separableConvolve<4, 4>(cmpFiltered, cmp, shift, shift, kernel, kernel);	break;
		case TextureFormat::RGB:	separableConvolve<4, 3>(cmpFiltered, cmp, shift, shift, kernel, kernel);	break;
		default:
			DE_ASSERT(DE_FALSE);
	}

	int			numSamples	= 0;
	deUint64	distSum4	= 0ull;

	// Clear error mask to green.
	clear(errorMask, Vec4(0.0f, 1.0f, 0.0f, 1.0f));

	ConstPixelBufferAccess refAccess = refFiltered.getAccess();
	ConstPixelBufferAccess cmpAccess = cmpFiltered.getAccess();

	for (int y = 1; y < height-1; y++)
	{
		for (int x = 1; x < width-1; x += params.maxSampleSkip > 0 ? (int)rnd.getInt(1, params.maxSampleSkip) : 1)
		{
			const deUint32	minDist2RefToCmp	= distSquaredToNeighbor<4>(rnd, readUnorm8<4>(refAccess, x, y), cmpAccess, x, y);
			const deUint32	minDist2CmpToRef	= distSquaredToNeighbor<4>(rnd, readUnorm8<4>(cmpAccess, x, y), refAccess, x, y);
			const deUint32	minDist2			= de::min(minDist2RefToCmp, minDist2CmpToRef);
			const deUint64	newSum4				= distSum4 + minDist2*minDist2;

			distSum4	 = (newSum4 >= distSum4) ? newSum4 : ~0ull; // In case of overflow
			numSamples	+= 1;

			// Build error image.
			{
				const int	scale	= 255-MIN_ERR_THRESHOLD;
				const float	err2	= float(minDist2) / float(scale*scale);
				const float	err4	= err2*err2;
				const float	red		= err4 * 500.0f;
				const float	luma	= toGrayscale(cmp.getPixel(x, y));
				const float	rF		= 0.7f + 0.3f*luma;

				errorMask.setPixel(Vec4(red*rF, (1.0f-red)*rF, 0.0f, 1.0f), x, y);
			}
		}
	}

	{
		// Scale error sum based on number of samples taken
		const double	pSamples	= double((width-2) * (height-2)) / double(numSamples);
		const deUint64	colScale	= deUint64(255-MIN_ERR_THRESHOLD);
		const deUint64	colScale4	= colScale*colScale*colScale*colScale;

		return float(double(distSum4) / double(colScale4) * pSamples);
	}
}

} // tcu
