Blame libfreerdp/primitives/test/TestPrimitivesYUV.c

Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_CONFIG_H
Packit 1fb8d4
#include "config.h"
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#include <math.h>
Packit 1fb8d4
Packit 1fb8d4
#include "prim_test.h"
Packit 1fb8d4
Packit 1fb8d4
#include <winpr/wlog.h>
Packit 1fb8d4
#include <winpr/crypto.h>
Packit 1fb8d4
#include <freerdp/primitives.h>
Packit 1fb8d4
#include <freerdp/utils/profiler.h>
Packit 1fb8d4
Packit 1fb8d4
#define TAG __FILE__
Packit 1fb8d4
Packit 1fb8d4
/* YUV to RGB conversion is lossy, so consider every value only
Packit 1fb8d4
 * differing by less than 2 abs equal. */
Packit 1fb8d4
static BOOL similar(const BYTE* src, const BYTE* dst, size_t size)
Packit 1fb8d4
{
Packit 1fb8d4
	size_t x;
Packit 1fb8d4
Packit 1fb8d4
	for (x = 0; x < size; x++)
Packit 1fb8d4
	{
Packit 1fb8d4
		int diff = src[x] - dst[x];
Packit 1fb8d4
Packit 1fb8d4
		if (abs(diff) > 4)
Packit 1fb8d4
		{
Packit 1fb8d4
			fprintf(stderr, "%"PRIuz" %02"PRIX8" : %02"PRIX8" diff=%d\n", x, src[x], dst[x], abs(diff));
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL similarRGB(const BYTE* src, const BYTE* dst, size_t size, UINT32 format)
Packit 1fb8d4
{
Packit 1fb8d4
	size_t x;
Packit 1fb8d4
	const UINT32 bpp = GetBytesPerPixel(format);
Packit 1fb8d4
Packit 1fb8d4
	for (x = 0; x < size; x++)
Packit 1fb8d4
	{
Packit 1fb8d4
		const double maxDiff = 4.0;
Packit 1fb8d4
		UINT32 sColor, dColor;
Packit 1fb8d4
		BYTE sR, sG, sB, sA;
Packit 1fb8d4
		BYTE dR, dG, dB, dA;
Packit 1fb8d4
		sColor = ReadColor(src, format);
Packit 1fb8d4
		dColor = ReadColor(dst, format);
Packit 1fb8d4
		src += bpp;
Packit 1fb8d4
		dst += bpp;
Packit 1fb8d4
		SplitColor(sColor, format, &sR, &sG, &sB, &sA, NULL);
Packit 1fb8d4
		SplitColor(dColor, format, &dR, &dG, &dB, &dA, NULL);
Packit 1fb8d4
Packit 1fb8d4
		if ((abs(sR - dR) > maxDiff) || (abs(sG - dG) > maxDiff) || (abs(sB - dB) > maxDiff))
Packit 1fb8d4
		{
Packit 1fb8d4
			fprintf(stderr, "Color value  mismatch R[%02X %02X], G[%02X %02X], B[%02X %02X] at position %lu",
Packit 1fb8d4
			        sR, dR, sG, dG, sA, dA, x);
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (dA != 0xFF)
Packit 1fb8d4
		{
Packit 1fb8d4
			fprintf(stderr, "Invalid destination alpha value %02X at position %lu", dA, x);
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static void get_size(BOOL large, UINT32* width, UINT32* height)
Packit 1fb8d4
{
Packit 1fb8d4
	UINT32 shift = large ? 8 : 1;
Packit 1fb8d4
	winpr_RAND((BYTE*)width, sizeof(*width));
Packit 1fb8d4
	winpr_RAND((BYTE*)height, sizeof(*height));
Packit 1fb8d4
	// TODO: Algorithm only works on even resolutions...
Packit 1fb8d4
	*width = (*width % 64 + 1) << shift;
Packit 1fb8d4
	*height = (*height % 64 + 1) << shift;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL check_padding(const BYTE* psrc, size_t size, size_t padding,
Packit 1fb8d4
                          const char* buffer)
Packit 1fb8d4
{
Packit 1fb8d4
	size_t x;
Packit 1fb8d4
	BOOL rc = TRUE;
Packit 1fb8d4
	const BYTE* src;
Packit 1fb8d4
	const BYTE* esrc;
Packit 1fb8d4
	size_t halfPad = (padding + 1) / 2;
Packit 1fb8d4
Packit 1fb8d4
	if (!psrc)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	src = psrc - halfPad;
Packit 1fb8d4
	esrc = src + size + halfPad;
Packit 1fb8d4
Packit 1fb8d4
	for (x = 0; x < halfPad; x++)
Packit 1fb8d4
	{
Packit 1fb8d4
		const BYTE s = *src++;
Packit 1fb8d4
		const BYTE d = *esrc++;
Packit 1fb8d4
Packit 1fb8d4
		if (s != 'A')
Packit 1fb8d4
		{
Packit 1fb8d4
			size_t start = x;
Packit 1fb8d4
Packit 1fb8d4
			while ((x < halfPad) && (*esrc++ != 'A'))
Packit 1fb8d4
				x++;
Packit 1fb8d4
Packit 1fb8d4
			fprintf(stderr, "Buffer underflow detected %02"PRIx8" != %02X %s [%"PRIuz"-%"PRIuz"]\n",
Packit 1fb8d4
			        d, 'A', buffer, start, x);
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (d != 'A')
Packit 1fb8d4
		{
Packit 1fb8d4
			size_t start = x;
Packit 1fb8d4
Packit 1fb8d4
			while ((x < halfPad) && (*esrc++ != 'A'))
Packit 1fb8d4
				x++;
Packit 1fb8d4
Packit 1fb8d4
			fprintf(stderr, "Buffer overflow detected %02"PRIx8" != %02X %s [%"PRIuz"-%"PRIuz"]\n",
Packit 1fb8d4
			        d, 'A', buffer, start, x);
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return rc;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static void* set_padding(size_t size, size_t padding)
Packit 1fb8d4
{
Packit 1fb8d4
	size_t halfPad = (padding + 1) / 2;
Packit 1fb8d4
	BYTE* psrc;
Packit 1fb8d4
	BYTE* src = _aligned_malloc(size + 2 * halfPad, 16);
Packit 1fb8d4
Packit 1fb8d4
	if (!src)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	memset(&src[0], 'A', halfPad);
Packit 1fb8d4
	memset(&src[halfPad], 0, size);
Packit 1fb8d4
	memset(&src[halfPad + size], 'A', halfPad);
Packit 1fb8d4
	psrc = &src[halfPad];
Packit 1fb8d4
Packit 1fb8d4
	if (!check_padding(psrc, size, padding, "init"))
Packit 1fb8d4
	{
Packit 1fb8d4
		_aligned_free(src);
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return psrc;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static void free_padding(void* src, size_t padding)
Packit 1fb8d4
{
Packit 1fb8d4
	BYTE* ptr;
Packit 1fb8d4
Packit 1fb8d4
	if (!src)
Packit 1fb8d4
		return;
Packit 1fb8d4
Packit 1fb8d4
	ptr = ((BYTE*)src) - (padding + 1) / 2;
Packit 1fb8d4
	_aligned_free(ptr);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/* Create 2 pseudo YUV420 frames of same size.
Packit 1fb8d4
 * Combine them and check, if the data is at the expected position. */
Packit 1fb8d4
static BOOL TestPrimitiveYUVCombine(primitives_t* prims, prim_size_t roi)
Packit 1fb8d4
{
Packit 1fb8d4
	UINT32 x, y, i;
Packit 1fb8d4
	UINT32 awidth, aheight;
Packit 1fb8d4
	BOOL rc = FALSE;
Packit 1fb8d4
	BYTE* luma[3] = { 0 };
Packit 1fb8d4
	BYTE* chroma[3] = { 0 };
Packit 1fb8d4
	BYTE* yuv[3] = { 0 };
Packit 1fb8d4
	BYTE* pmain[3] = { 0 };
Packit 1fb8d4
	BYTE* paux[3] = { 0 };
Packit 1fb8d4
	UINT32 lumaStride[3];
Packit 1fb8d4
	UINT32 chromaStride[3];
Packit 1fb8d4
	UINT32 yuvStride[3];
Packit 1fb8d4
	const size_t padding = 10000;
Packit 1fb8d4
	RECTANGLE_16 rect;
Packit 1fb8d4
	PROFILER_DEFINE(yuvCombine)
Packit 1fb8d4
	PROFILER_DEFINE(yuvSplit)
Packit 1fb8d4
	awidth = roi.width + 16 - roi.width % 16;
Packit 1fb8d4
	aheight = roi.height + 16 - roi.height % 16;
Packit 1fb8d4
	fprintf(stderr, "Running YUVCombine on frame size %"PRIu32"x%"PRIu32" [%"PRIu32"x%"PRIu32"]\n",
Packit 1fb8d4
	        roi.width, roi.height, awidth, aheight);
Packit 1fb8d4
	PROFILER_CREATE(yuvCombine, "YUV420CombineToYUV444")
Packit 1fb8d4
	PROFILER_CREATE(yuvSplit, "YUV444SplitToYUV420")
Packit 1fb8d4
	rect.left = 0;
Packit 1fb8d4
	rect.top = 0;
Packit 1fb8d4
	rect.right = roi.width;
Packit 1fb8d4
	rect.bottom = roi.height;
Packit 1fb8d4
Packit 1fb8d4
	if (!prims || !prims->YUV420CombineToYUV444)
Packit 1fb8d4
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	for (x = 0; x < 3; x++)
Packit 1fb8d4
	{
Packit 1fb8d4
		size_t halfStride = ((x > 0) ? awidth / 2 : awidth);
Packit 1fb8d4
		size_t size = aheight * awidth;
Packit 1fb8d4
		size_t halfSize = ((x > 0) ? halfStride * aheight / 2 : awidth * aheight);
Packit 1fb8d4
		yuvStride[x] = awidth;
Packit 1fb8d4
Packit 1fb8d4
		if (!(yuv[x] = set_padding(size, padding)))
Packit 1fb8d4
			goto fail;
Packit 1fb8d4
Packit 1fb8d4
		lumaStride[x] = halfStride;
Packit 1fb8d4
Packit 1fb8d4
		if (!(luma[x] = set_padding(halfSize, padding)))
Packit 1fb8d4
			goto fail;
Packit 1fb8d4
Packit 1fb8d4
		if (!(pmain[x] = set_padding(halfSize, padding)))
Packit 1fb8d4
			goto fail;
Packit 1fb8d4
Packit 1fb8d4
		chromaStride[x] = halfStride;
Packit 1fb8d4
Packit 1fb8d4
		if (!(chroma[x] = set_padding(halfSize, padding)))
Packit 1fb8d4
			goto fail;
Packit 1fb8d4
Packit 1fb8d4
		if (!(paux[x] = set_padding(halfSize, padding)))
Packit 1fb8d4
			goto fail;
Packit 1fb8d4
Packit 1fb8d4
		memset(luma[x], 0xAB + 3 * x, halfSize);
Packit 1fb8d4
		memset(chroma[x], 0x80 + 2 * x, halfSize);
Packit 1fb8d4
Packit 1fb8d4
		if (!check_padding(luma[x], halfSize, padding, "luma"))
Packit 1fb8d4
			goto fail;
Packit 1fb8d4
Packit 1fb8d4
		if (!check_padding(chroma[x], halfSize, padding, "chroma"))
Packit 1fb8d4
			goto fail;
Packit 1fb8d4
Packit 1fb8d4
		if (!check_padding(pmain[x], halfSize, padding, "main"))
Packit 1fb8d4
			goto fail;
Packit 1fb8d4
Packit 1fb8d4
		if (!check_padding(paux[x], halfSize, padding, "aux"))
Packit 1fb8d4
			goto fail;
Packit 1fb8d4
Packit 1fb8d4
		if (!check_padding(yuv[x], size, padding, "yuv"))
Packit 1fb8d4
			goto fail;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	PROFILER_ENTER(yuvCombine)
Packit 1fb8d4
Packit 1fb8d4
	if (prims->YUV420CombineToYUV444(AVC444_LUMA,
Packit 1fb8d4
	                                 (const BYTE**)luma, lumaStride,
Packit 1fb8d4
	                                 roi.width, roi.height,
Packit 1fb8d4
	                                 yuv, yuvStride, &rect) != PRIMITIVES_SUCCESS)
Packit 1fb8d4
	{
Packit 1fb8d4
		PROFILER_EXIT(yuvCombine)
Packit 1fb8d4
		goto fail;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (prims->YUV420CombineToYUV444(AVC444_CHROMAv1,
Packit 1fb8d4
	                                 (const BYTE**)chroma, chromaStride,
Packit 1fb8d4
	                                 roi.width, roi.height,
Packit 1fb8d4
	                                 yuv, yuvStride, &rect) != PRIMITIVES_SUCCESS)
Packit 1fb8d4
	{
Packit 1fb8d4
		PROFILER_EXIT(yuvCombine)
Packit 1fb8d4
		goto fail;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	PROFILER_EXIT(yuvCombine)
Packit 1fb8d4
Packit 1fb8d4
	for (x = 0; x < 3; x++)
Packit 1fb8d4
	{
Packit 1fb8d4
		size_t halfStride = ((x > 0) ? awidth / 2 : awidth);
Packit 1fb8d4
		size_t size = aheight * awidth;
Packit 1fb8d4
		size_t halfSize = ((x > 0) ? halfStride * aheight / 2 : awidth * aheight);
Packit 1fb8d4
Packit 1fb8d4
		if (!check_padding(luma[x], halfSize, padding, "luma"))
Packit 1fb8d4
			goto fail;
Packit 1fb8d4
Packit 1fb8d4
		if (!check_padding(chroma[x], halfSize, padding, "chroma"))
Packit 1fb8d4
			goto fail;
Packit 1fb8d4
Packit 1fb8d4
		if (!check_padding(yuv[x], size, padding, "yuv"))
Packit 1fb8d4
			goto fail;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	PROFILER_ENTER(yuvSplit)
Packit 1fb8d4
Packit 1fb8d4
	if (prims->YUV444SplitToYUV420((const BYTE**)yuv, yuvStride, pmain, lumaStride,
Packit 1fb8d4
	                               paux, chromaStride, &roi) != PRIMITIVES_SUCCESS)
Packit 1fb8d4
	{
Packit 1fb8d4
		PROFILER_EXIT(yuvSplit)
Packit 1fb8d4
		goto fail;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	PROFILER_EXIT(yuvSplit)
Packit 1fb8d4
Packit 1fb8d4
	for (x = 0; x < 3; x++)
Packit 1fb8d4
	{
Packit 1fb8d4
		size_t halfStride = ((x > 0) ? awidth / 2 : awidth);
Packit 1fb8d4
		size_t size = aheight * awidth;
Packit 1fb8d4
		size_t halfSize = ((x > 0) ? halfStride * aheight / 2 : awidth * aheight);
Packit 1fb8d4
Packit 1fb8d4
		if (!check_padding(pmain[x], halfSize, padding, "main"))
Packit 1fb8d4
			goto fail;
Packit 1fb8d4
Packit 1fb8d4
		if (!check_padding(paux[x], halfSize, padding, "aux"))
Packit 1fb8d4
			goto fail;
Packit 1fb8d4
Packit 1fb8d4
		if (!check_padding(yuv[x], size, padding, "yuv"))
Packit 1fb8d4
			goto fail;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	for (i = 0; i < 3; i++)
Packit 1fb8d4
	{
Packit 1fb8d4
		for (y = 0; y < roi.height; y++)
Packit 1fb8d4
		{
Packit 1fb8d4
			UINT32 w = roi.width;
Packit 1fb8d4
			UINT32 lstride = lumaStride[i];
Packit 1fb8d4
			UINT32 cstride = chromaStride[i];
Packit 1fb8d4
Packit 1fb8d4
			if (i > 0)
Packit 1fb8d4
			{
Packit 1fb8d4
				w = (roi.width + 3) / 4;
Packit 1fb8d4
Packit 1fb8d4
				if (roi.height > (roi.height + 1) / 2)
Packit 1fb8d4
					continue;
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			if (!similar(luma[i] + y * lstride,
Packit 1fb8d4
			             pmain[i]  + y * lstride,
Packit 1fb8d4
			             w))
Packit 1fb8d4
				goto fail;
Packit 1fb8d4
Packit 1fb8d4
			/* Need to ignore lines of destination Y plane,
Packit 1fb8d4
			 * if the lines are not a multiple of 16
Packit 1fb8d4
			 * as the UV planes are packed in 8 line stripes. */
Packit 1fb8d4
			if (i == 0)
Packit 1fb8d4
			{
Packit 1fb8d4
				/* TODO: This check is not perfect, it does not
Packit 1fb8d4
				 * include the last V lines packed to the Y
Packit 1fb8d4
				 * frame. */
Packit 1fb8d4
				UINT32 rem = roi.height % 16;
Packit 1fb8d4
Packit 1fb8d4
				if (y > roi.height - rem)
Packit 1fb8d4
					continue;
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			if (!similar(chroma[i] + y * cstride,
Packit 1fb8d4
			             paux[i]  + y * cstride,
Packit 1fb8d4
			             w))
Packit 1fb8d4
				goto fail;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	PROFILER_PRINT_HEADER
Packit 1fb8d4
	PROFILER_PRINT(yuvSplit)
Packit 1fb8d4
	PROFILER_PRINT(yuvCombine)
Packit 1fb8d4
	PROFILER_PRINT_FOOTER
Packit 1fb8d4
	rc = TRUE;
Packit 1fb8d4
fail:
Packit 1fb8d4
	PROFILER_FREE(yuvCombine)
Packit 1fb8d4
	PROFILER_FREE(yuvSplit)
Packit 1fb8d4
Packit 1fb8d4
	for (x = 0; x < 3; x++)
Packit 1fb8d4
	{
Packit 1fb8d4
		free_padding(yuv[x], padding);
Packit 1fb8d4
		free_padding(luma[x], padding);
Packit 1fb8d4
		free_padding(chroma[x], padding);
Packit 1fb8d4
		free_padding(pmain[x], padding);
Packit 1fb8d4
		free_padding(paux[x], padding);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return rc;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL TestPrimitiveYUV(primitives_t* prims, prim_size_t roi, BOOL use444)
Packit 1fb8d4
{
Packit 1fb8d4
	BOOL rc = FALSE;
Packit 1fb8d4
	UINT32 x, y;
Packit 1fb8d4
	UINT32 awidth, aheight;
Packit 1fb8d4
	BYTE* yuv[3] = {0};
Packit 1fb8d4
	UINT32 yuv_step[3];
Packit 1fb8d4
	BYTE* rgb = NULL;
Packit 1fb8d4
	BYTE* rgb_dst = NULL;
Packit 1fb8d4
	size_t size;
Packit 1fb8d4
	size_t uvsize, uvwidth;
Packit 1fb8d4
	size_t padding = 100 * 16;
Packit 1fb8d4
	UINT32 stride;
Packit 1fb8d4
	const UINT32 formats[] =
Packit 1fb8d4
	{
Packit 1fb8d4
		PIXEL_FORMAT_XRGB32,
Packit 1fb8d4
		PIXEL_FORMAT_XBGR32,
Packit 1fb8d4
		PIXEL_FORMAT_ARGB32,
Packit 1fb8d4
		PIXEL_FORMAT_ABGR32,
Packit 1fb8d4
		PIXEL_FORMAT_RGBA32,
Packit 1fb8d4
		PIXEL_FORMAT_RGBX32,
Packit 1fb8d4
		PIXEL_FORMAT_BGRA32,
Packit 1fb8d4
		PIXEL_FORMAT_BGRX32
Packit 1fb8d4
	};
Packit 1fb8d4
	PROFILER_DEFINE(rgbToYUV420)
Packit 1fb8d4
	PROFILER_DEFINE(rgbToYUV444)
Packit 1fb8d4
	PROFILER_DEFINE(yuv420ToRGB)
Packit 1fb8d4
	PROFILER_DEFINE(yuv444ToRGB)
Packit 1fb8d4
	/* Buffers need to be 16x16 aligned. */
Packit 1fb8d4
	awidth = roi.width + 16 - roi.width % 16;
Packit 1fb8d4
	aheight = roi.height + 16 - roi.height % 16;
Packit 1fb8d4
	stride = awidth * sizeof(UINT32);
Packit 1fb8d4
	size = awidth * aheight;
Packit 1fb8d4
Packit 1fb8d4
	if (use444)
Packit 1fb8d4
	{
Packit 1fb8d4
		uvwidth = awidth;
Packit 1fb8d4
		uvsize = size;
Packit 1fb8d4
Packit 1fb8d4
		if (!prims || !prims->RGBToYUV444_8u_P3AC4R || !prims->YUV444ToRGB_8u_P3AC4R)
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		uvwidth = (awidth + 1) / 2;
Packit 1fb8d4
		uvsize = (aheight + 1) / 2 * uvwidth;
Packit 1fb8d4
Packit 1fb8d4
		if (!prims || !prims->RGBToYUV420_8u_P3AC4R || !prims->YUV420ToRGB_8u_P3AC4R)
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	fprintf(stderr, "Running AVC%s on frame size %"PRIu32"x%"PRIu32"\n", use444 ? "444" : "420",
Packit 1fb8d4
	        roi.width, roi.height);
Packit 1fb8d4
Packit 1fb8d4
	/* Test RGB to YUV444 conversion and vice versa */
Packit 1fb8d4
	if (!(rgb = set_padding(size * sizeof(UINT32), padding)))
Packit 1fb8d4
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	if (!(rgb_dst = set_padding(size * sizeof(UINT32), padding)))
Packit 1fb8d4
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	if (!(yuv[0] = set_padding(size, padding)))
Packit 1fb8d4
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	if (!(yuv[1] = set_padding(uvsize, padding)))
Packit 1fb8d4
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	if (!(yuv[2] = set_padding(uvsize, padding)))
Packit 1fb8d4
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	for (y = 0; y < roi.height; y++)
Packit 1fb8d4
	{
Packit 1fb8d4
		BYTE* line = &rgb[y * stride];
Packit 1fb8d4
Packit 1fb8d4
		for (x = 0; x < roi.width; x++)
Packit 1fb8d4
		{
Packit 1fb8d4
			line[x * 4 + 0] = 0x81;
Packit 1fb8d4
			line[x * 4 + 1] = 0x33;
Packit 1fb8d4
			line[x * 4 + 2] = 0xAB;
Packit 1fb8d4
			line[x * 4 + 3] = 0xFF;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	yuv_step[0] = awidth;
Packit 1fb8d4
	yuv_step[1] = uvwidth;
Packit 1fb8d4
	yuv_step[2] = uvwidth;
Packit 1fb8d4
Packit 1fb8d4
	for (x = 0; x < sizeof(formats) / sizeof(formats[0]); x++)
Packit 1fb8d4
	{
Packit 1fb8d4
		pstatus_t rc;
Packit 1fb8d4
		const UINT32 DstFormat = formats[x];
Packit 1fb8d4
		printf("Testing destination color format %s\n", FreeRDPGetColorFormatName(DstFormat));
Packit 1fb8d4
		PROFILER_CREATE(rgbToYUV420, "RGBToYUV420")
Packit 1fb8d4
		PROFILER_CREATE(rgbToYUV444, "RGBToYUV444")
Packit 1fb8d4
		PROFILER_CREATE(yuv420ToRGB, "YUV420ToRGB")
Packit 1fb8d4
		PROFILER_CREATE(yuv444ToRGB, "YUV444ToRGB")
Packit 1fb8d4
Packit 1fb8d4
		if (use444)
Packit 1fb8d4
		{
Packit 1fb8d4
			PROFILER_ENTER(rgbToYUV444)
Packit 1fb8d4
			rc = prims->RGBToYUV444_8u_P3AC4R(rgb, DstFormat,
Packit 1fb8d4
			                                  stride, yuv, yuv_step,
Packit 1fb8d4
			                                  &roi;;
Packit 1fb8d4
			PROFILER_EXIT(rgbToYUV444)
Packit 1fb8d4
Packit 1fb8d4
			if (rc != PRIMITIVES_SUCCESS)
Packit 1fb8d4
				goto loop_fail;
Packit 1fb8d4
Packit 1fb8d4
			PROFILER_PRINT_HEADER
Packit 1fb8d4
			PROFILER_PRINT(rgbToYUV444)
Packit 1fb8d4
			PROFILER_PRINT_FOOTER
Packit 1fb8d4
		}
Packit 1fb8d4
		else
Packit 1fb8d4
		{
Packit 1fb8d4
			PROFILER_ENTER(rgbToYUV420)
Packit 1fb8d4
			rc = prims->RGBToYUV420_8u_P3AC4R(rgb, DstFormat,
Packit 1fb8d4
			                                  stride, yuv, yuv_step,
Packit 1fb8d4
			                                  &roi;;
Packit 1fb8d4
			PROFILER_EXIT(rgbToYUV420)
Packit 1fb8d4
Packit 1fb8d4
			if (rc != PRIMITIVES_SUCCESS)
Packit 1fb8d4
				goto loop_fail;
Packit 1fb8d4
Packit 1fb8d4
			PROFILER_PRINT_HEADER
Packit 1fb8d4
			PROFILER_PRINT(rgbToYUV420)
Packit 1fb8d4
			PROFILER_PRINT_FOOTER
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (!check_padding(rgb, size * sizeof(UINT32), padding, "rgb"))
Packit 1fb8d4
		{
Packit 1fb8d4
			rc = -1;
Packit 1fb8d4
			goto loop_fail;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if ((!check_padding(yuv[0], size, padding, "Y")) ||
Packit 1fb8d4
		    (!check_padding(yuv[1], uvsize, padding, "U")) ||
Packit 1fb8d4
		    (!check_padding(yuv[2], uvsize, padding, "V")))
Packit 1fb8d4
		{
Packit 1fb8d4
			rc = -1;
Packit 1fb8d4
			goto loop_fail;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (use444)
Packit 1fb8d4
		{
Packit 1fb8d4
			PROFILER_ENTER(yuv444ToRGB)
Packit 1fb8d4
			rc = prims->YUV444ToRGB_8u_P3AC4R((const BYTE**)yuv, yuv_step, rgb_dst, stride,
Packit 1fb8d4
			                                  DstFormat,
Packit 1fb8d4
			                                  &roi;;
Packit 1fb8d4
			PROFILER_EXIT(yuv444ToRGB)
Packit 1fb8d4
Packit 1fb8d4
			if (rc != PRIMITIVES_SUCCESS)
Packit 1fb8d4
				goto loop_fail;
Packit 1fb8d4
Packit 1fb8d4
		loop_fail:
Packit 1fb8d4
			PROFILER_EXIT(yuv444ToRGB)
Packit 1fb8d4
			PROFILER_PRINT_HEADER
Packit 1fb8d4
			PROFILER_PRINT(yuv444ToRGB)
Packit 1fb8d4
			PROFILER_PRINT_FOOTER
Packit 1fb8d4
Packit 1fb8d4
			if (rc != PRIMITIVES_SUCCESS)
Packit 1fb8d4
				goto fail;
Packit 1fb8d4
		}
Packit 1fb8d4
		else
Packit 1fb8d4
		{
Packit 1fb8d4
			PROFILER_ENTER(yuv420ToRGB)
Packit 1fb8d4
Packit 1fb8d4
			if (prims->YUV420ToRGB_8u_P3AC4R((const BYTE**)yuv, yuv_step, rgb_dst,
Packit 1fb8d4
			                                 stride, DstFormat, &roi) != PRIMITIVES_SUCCESS)
Packit 1fb8d4
			{
Packit 1fb8d4
				PROFILER_EXIT(yuv420ToRGB)
Packit 1fb8d4
				goto fail;
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			PROFILER_EXIT(yuv420ToRGB)
Packit 1fb8d4
			PROFILER_PRINT_HEADER
Packit 1fb8d4
			PROFILER_PRINT(yuv420ToRGB)
Packit 1fb8d4
			PROFILER_PRINT_FOOTER
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (!check_padding(rgb_dst, size * sizeof(UINT32), padding, "rgb dst"))
Packit 1fb8d4
			goto fail;
Packit 1fb8d4
Packit 1fb8d4
		if ((!check_padding(yuv[0], size, padding, "Y")) ||
Packit 1fb8d4
		    (!check_padding(yuv[1], uvsize, padding, "U")) ||
Packit 1fb8d4
		    (!check_padding(yuv[2], uvsize, padding, "V")))
Packit 1fb8d4
			goto fail;
Packit 1fb8d4
Packit 1fb8d4
		for (y = 0; y < roi.height; y++)
Packit 1fb8d4
		{
Packit 1fb8d4
			BYTE* srgb = &rgb[y * stride];
Packit 1fb8d4
			BYTE* drgb = &rgb_dst[y * stride];
Packit 1fb8d4
Packit 1fb8d4
			if (!similarRGB(srgb, drgb, roi.width, DstFormat))
Packit 1fb8d4
				goto fail;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		PROFILER_FREE(rgbToYUV420)
Packit 1fb8d4
		PROFILER_FREE(rgbToYUV444)
Packit 1fb8d4
		PROFILER_FREE(yuv420ToRGB)
Packit 1fb8d4
		PROFILER_FREE(yuv444ToRGB)
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	rc = TRUE;
Packit 1fb8d4
fail:
Packit 1fb8d4
	free_padding(rgb, padding);
Packit 1fb8d4
	free_padding(rgb_dst, padding);
Packit 1fb8d4
	free_padding(yuv[0], padding);
Packit 1fb8d4
	free_padding(yuv[1], padding);
Packit 1fb8d4
	free_padding(yuv[2], padding);
Packit 1fb8d4
	return rc;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL allocate_yuv420(BYTE** planes, UINT32 width, UINT32 height, UINT32 padding)
Packit 1fb8d4
{
Packit 1fb8d4
	const size_t size = width * height;
Packit 1fb8d4
	const size_t uvwidth = (width + 1) / 2;
Packit 1fb8d4
	const size_t uvsize = (height + 1) / 2 * uvwidth;
Packit 1fb8d4
Packit 1fb8d4
	if (!(planes[0] = set_padding(size, padding)))
Packit 1fb8d4
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	if (!(planes[1] = set_padding(uvsize, padding)))
Packit 1fb8d4
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	if (!(planes[2] = set_padding(uvsize, padding)))
Packit 1fb8d4
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
fail:
Packit 1fb8d4
	free_padding(planes[0], padding);
Packit 1fb8d4
	free_padding(planes[1], padding);
Packit 1fb8d4
	free_padding(planes[2], padding);
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static void free_yuv420(BYTE** planes, UINT32 padding)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!planes)
Packit 1fb8d4
		return;
Packit 1fb8d4
Packit 1fb8d4
	free_padding(planes[0], padding);
Packit 1fb8d4
	free_padding(planes[1], padding);
Packit 1fb8d4
	free_padding(planes[2], padding);
Packit 1fb8d4
	planes[0] = NULL;
Packit 1fb8d4
	planes[1] = NULL;
Packit 1fb8d4
	planes[2] = NULL;
Packit 1fb8d4
}
Packit 1fb8d4
static BOOL check_yuv420(BYTE** planes, UINT32 width, UINT32 height, UINT32 padding)
Packit 1fb8d4
{
Packit 1fb8d4
	const size_t size = width * height;
Packit 1fb8d4
	const size_t uvwidth = (width + 1) / 2;
Packit 1fb8d4
	const size_t uvsize = (height + 1) / 2 * uvwidth;
Packit 1fb8d4
	const BOOL yOk = check_padding(planes[0], size, padding, "Y");
Packit 1fb8d4
	const BOOL uOk = check_padding(planes[1], uvsize, padding, "U");
Packit 1fb8d4
	const BOOL vOk = check_padding(planes[2], uvsize, padding, "V");
Packit 1fb8d4
	return (yOk && uOk && vOk);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL check_for_mismatches(const BYTE* planeA, const BYTE* planeB, UINT32 size)
Packit 1fb8d4
{
Packit 1fb8d4
	BOOL rc = FALSE;
Packit 1fb8d4
	UINT32 x;
Packit 1fb8d4
Packit 1fb8d4
	for (x = 0; x < size; x++)
Packit 1fb8d4
	{
Packit 1fb8d4
		const BYTE a = planeA[x];
Packit 1fb8d4
		const BYTE b = planeB[x];
Packit 1fb8d4
Packit 1fb8d4
		if (fabsf((float)a - (float)b) > 2.0f)
Packit 1fb8d4
		{
Packit 1fb8d4
			rc = TRUE;
Packit 1fb8d4
			fprintf(stderr, "[%08x] %02x != %02x\n",
Packit 1fb8d4
			        x, a, b);
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return rc;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL compare_yuv420(BYTE** planesA, BYTE** planesB, UINT32 width, UINT32 height,
Packit 1fb8d4
                           UINT32 padding)
Packit 1fb8d4
{
Packit 1fb8d4
	BOOL rc = TRUE;
Packit 1fb8d4
	const size_t size = width * height;
Packit 1fb8d4
	const size_t uvwidth = (width + 1) / 2;
Packit 1fb8d4
	const size_t uvsize = (height + 1) / 2 * uvwidth;
Packit 1fb8d4
Packit 1fb8d4
	if (check_for_mismatches(planesA[0], planesB[0], size))
Packit 1fb8d4
	{
Packit 1fb8d4
		fprintf(stderr, "Mismatch in Y planes!");
Packit 1fb8d4
		rc = FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (check_for_mismatches(planesA[1], planesB[1], uvsize))
Packit 1fb8d4
	{
Packit 1fb8d4
		fprintf(stderr, "Mismatch in U planes!");
Packit 1fb8d4
		rc = FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (check_for_mismatches(planesA[2], planesB[2], uvsize))
Packit 1fb8d4
	{
Packit 1fb8d4
		fprintf(stderr, "Mismatch in V planes!");
Packit 1fb8d4
		rc = FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return rc;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL TestPrimitiveRgbToLumaChroma(primitives_t* prims, prim_size_t roi, UINT32 version)
Packit 1fb8d4
{
Packit 1fb8d4
	BOOL rc = FALSE;
Packit 1fb8d4
	UINT32 x, y, cnt;
Packit 1fb8d4
	UINT32 awidth, aheight;
Packit 1fb8d4
	BYTE* luma[3] = {0};
Packit 1fb8d4
	BYTE* chroma[3] = {0};
Packit 1fb8d4
	BYTE* lumaGeneric[3] = {0};
Packit 1fb8d4
	BYTE* chromaGeneric[3] = {0};
Packit 1fb8d4
	UINT32 yuv_step[3];
Packit 1fb8d4
	BYTE* rgb = NULL;
Packit 1fb8d4
	size_t size;
Packit 1fb8d4
	size_t uvsize, uvwidth;
Packit 1fb8d4
	const size_t padding = 0x1000;
Packit 1fb8d4
	UINT32 stride;
Packit 1fb8d4
	__RGBToAVC444YUV_t fkt, gen;
Packit 1fb8d4
	const UINT32 formats[] =
Packit 1fb8d4
	{
Packit 1fb8d4
		PIXEL_FORMAT_XRGB32,
Packit 1fb8d4
		PIXEL_FORMAT_XBGR32,
Packit 1fb8d4
		PIXEL_FORMAT_ARGB32,
Packit 1fb8d4
		PIXEL_FORMAT_ABGR32,
Packit 1fb8d4
		PIXEL_FORMAT_RGBA32,
Packit 1fb8d4
		PIXEL_FORMAT_RGBX32,
Packit 1fb8d4
		PIXEL_FORMAT_BGRA32,
Packit 1fb8d4
		PIXEL_FORMAT_BGRX32
Packit 1fb8d4
	};
Packit 1fb8d4
	PROFILER_DEFINE(rgbToYUV444)
Packit 1fb8d4
	PROFILER_DEFINE(rgbToYUV444opt)
Packit 1fb8d4
	/* Buffers need to be 16x16 aligned. */
Packit 1fb8d4
	awidth = roi.width;
Packit 1fb8d4
Packit 1fb8d4
	if (awidth % 16 != 0)
Packit 1fb8d4
		awidth += 16 - roi.width % 16;
Packit 1fb8d4
Packit 1fb8d4
	aheight = roi.height;
Packit 1fb8d4
Packit 1fb8d4
	if (aheight % 16 != 0)
Packit 1fb8d4
		aheight += 16 - roi.height % 16;
Packit 1fb8d4
Packit 1fb8d4
	stride = awidth * sizeof(UINT32);
Packit 1fb8d4
	size = awidth * aheight;
Packit 1fb8d4
	uvwidth = (awidth + 1) / 2;
Packit 1fb8d4
	uvsize = (aheight + 1) / 2 * uvwidth;
Packit 1fb8d4
Packit 1fb8d4
	if (!prims || !generic)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	switch (version)
Packit 1fb8d4
	{
Packit 1fb8d4
		case 1:
Packit 1fb8d4
			fkt = prims->RGBToAVC444YUV;
Packit 1fb8d4
			gen = generic->RGBToAVC444YUV;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case 2:
Packit 1fb8d4
			fkt = prims->RGBToAVC444YUVv2;
Packit 1fb8d4
			gen = generic->RGBToAVC444YUVv2;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		default:
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!fkt || !gen)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	fprintf(stderr, "Running AVC444 on frame size %"PRIu32"x%"PRIu32"\n",
Packit 1fb8d4
	        roi.width, roi.height);
Packit 1fb8d4
Packit 1fb8d4
	/* Test RGB to YUV444 conversion and vice versa */
Packit 1fb8d4
	if (!(rgb = set_padding(size * sizeof(UINT32), padding)))
Packit 1fb8d4
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	if (!allocate_yuv420(luma, awidth, aheight, padding))
Packit 1fb8d4
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	if (!allocate_yuv420(chroma, awidth, aheight, padding))
Packit 1fb8d4
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	if (!allocate_yuv420(lumaGeneric, awidth, aheight, padding))
Packit 1fb8d4
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	if (!allocate_yuv420(chromaGeneric, awidth, aheight, padding))
Packit 1fb8d4
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	for (y = 0; y < roi.height; y++)
Packit 1fb8d4
	{
Packit 1fb8d4
		BYTE* line = &rgb[y * stride];
Packit 1fb8d4
Packit 1fb8d4
		for (x = 0; x < roi.width; x++)
Packit 1fb8d4
		{
Packit 1fb8d4
#if 1
Packit 1fb8d4
			line[x * 4 + 0] = rand();
Packit 1fb8d4
			line[x * 4 + 1] = rand();
Packit 1fb8d4
			line[x * 4 + 2] = rand();
Packit 1fb8d4
			line[x * 4 + 3] = rand();
Packit 1fb8d4
#else
Packit 1fb8d4
			line[x * 4 + 0] = (y * roi.width + x) * 16 + 5;
Packit 1fb8d4
			line[x * 4 + 1] = (y * roi.width + x) * 16 + 7;
Packit 1fb8d4
			line[x * 4 + 2] = (y * roi.width + x) * 16 + 11;
Packit 1fb8d4
			line[x * 4 + 3] = (y * roi.width + x) * 16 + 0;
Packit 1fb8d4
#endif
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	yuv_step[0] = awidth;
Packit 1fb8d4
	yuv_step[1] = uvwidth;
Packit 1fb8d4
	yuv_step[2] = uvwidth;
Packit 1fb8d4
Packit 1fb8d4
	for (x = 0; x < sizeof(formats) / sizeof(formats[0]); x++)
Packit 1fb8d4
	{
Packit 1fb8d4
		pstatus_t rc;
Packit 1fb8d4
		const UINT32 DstFormat = formats[x];
Packit 1fb8d4
		printf("Testing destination color format %s\n", FreeRDPGetColorFormatName(DstFormat));
Packit 1fb8d4
		PROFILER_CREATE(rgbToYUV444, "RGBToYUV444-generic")
Packit 1fb8d4
		PROFILER_CREATE(rgbToYUV444opt, "RGBToYUV444-optimized")
Packit 1fb8d4
Packit 1fb8d4
		for (cnt = 0; cnt < 10; cnt++)
Packit 1fb8d4
		{
Packit 1fb8d4
			PROFILER_ENTER(rgbToYUV444opt)
Packit 1fb8d4
			rc = fkt(rgb, DstFormat, stride, luma, yuv_step, chroma, yuv_step, &roi;;
Packit 1fb8d4
			PROFILER_EXIT(rgbToYUV444opt)
Packit 1fb8d4
Packit 1fb8d4
			if (rc != PRIMITIVES_SUCCESS)
Packit 1fb8d4
				goto loop_fail;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		PROFILER_PRINT_HEADER
Packit 1fb8d4
		PROFILER_PRINT(rgbToYUV444opt)
Packit 1fb8d4
		PROFILER_PRINT_FOOTER
Packit 1fb8d4
Packit 1fb8d4
		if (!check_padding(rgb, size * sizeof(UINT32), padding, "rgb"))
Packit 1fb8d4
		{
Packit 1fb8d4
			rc = -1;
Packit 1fb8d4
			goto loop_fail;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (!check_yuv420(luma, awidth, aheight, padding) ||
Packit 1fb8d4
		    !check_yuv420(chroma, awidth, aheight, padding))
Packit 1fb8d4
		{
Packit 1fb8d4
			rc = -1;
Packit 1fb8d4
			goto loop_fail;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		for (cnt = 0; cnt < 10; cnt++)
Packit 1fb8d4
		{
Packit 1fb8d4
			PROFILER_ENTER(rgbToYUV444)
Packit 1fb8d4
			rc = gen(rgb, DstFormat, stride, lumaGeneric, yuv_step, chromaGeneric, yuv_step, &roi;;
Packit 1fb8d4
			PROFILER_EXIT(rgbToYUV444)
Packit 1fb8d4
Packit 1fb8d4
			if (rc != PRIMITIVES_SUCCESS)
Packit 1fb8d4
				goto loop_fail;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		PROFILER_PRINT_HEADER
Packit 1fb8d4
		PROFILER_PRINT(rgbToYUV444)
Packit 1fb8d4
		PROFILER_PRINT_FOOTER
Packit 1fb8d4
Packit 1fb8d4
		if (!check_padding(rgb, size * sizeof(UINT32), padding, "rgb"))
Packit 1fb8d4
		{
Packit 1fb8d4
			rc = -1;
Packit 1fb8d4
			goto loop_fail;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (!check_yuv420(lumaGeneric, awidth, aheight, padding) ||
Packit 1fb8d4
		    !check_yuv420(chromaGeneric, awidth, aheight, padding))
Packit 1fb8d4
		{
Packit 1fb8d4
			rc = -1;
Packit 1fb8d4
			goto loop_fail;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (!compare_yuv420(luma, lumaGeneric, awidth, aheight, padding) ||
Packit 1fb8d4
		    !compare_yuv420(chroma, chromaGeneric, awidth, aheight, padding))
Packit 1fb8d4
		{
Packit 1fb8d4
			rc = -1;
Packit 1fb8d4
			goto loop_fail;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
	loop_fail:
Packit 1fb8d4
		PROFILER_FREE(rgbToYUV444)
Packit 1fb8d4
		PROFILER_FREE(rgbToYUV444opt)
Packit 1fb8d4
Packit 1fb8d4
		if (rc != PRIMITIVES_SUCCESS)
Packit 1fb8d4
			goto fail;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	rc = TRUE;
Packit 1fb8d4
fail:
Packit 1fb8d4
	free_padding(rgb, padding);
Packit 1fb8d4
	free_yuv420(luma, padding);
Packit 1fb8d4
	free_yuv420(chroma, padding);
Packit 1fb8d4
	free_yuv420(lumaGeneric, padding);
Packit 1fb8d4
	free_yuv420(chromaGeneric, padding);
Packit 1fb8d4
	return rc;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
int TestPrimitivesYUV(int argc, char* argv[])
Packit 1fb8d4
{
Packit 1fb8d4
	BOOL large = (argc > 1);
Packit 1fb8d4
	UINT32 x;
Packit 1fb8d4
	int rc = -1;
Packit 1fb8d4
	prim_test_setup(FALSE);
Packit 1fb8d4
	primitives_t* prims = primitives_get();
Packit 1fb8d4
Packit 1fb8d4
	for (x = 0; x < 10; x++)
Packit 1fb8d4
	{
Packit 1fb8d4
		prim_size_t roi;
Packit 1fb8d4
Packit 1fb8d4
		if (argc > 1)
Packit 1fb8d4
		{
Packit 1fb8d4
			int rc = sscanf(argv[1], "%"PRIu32"x%"PRIu32, &roi.width, &roi.height);
Packit 1fb8d4
Packit 1fb8d4
			if (rc != 2)
Packit 1fb8d4
			{
Packit 1fb8d4
				roi.width = 1920;
Packit 1fb8d4
				roi.height = 1080;
Packit 1fb8d4
			}
Packit 1fb8d4
		}
Packit 1fb8d4
		else
Packit 1fb8d4
			get_size(large, &roi.width, &roi.height);
Packit 1fb8d4
Packit 1fb8d4
		printf("-------------------- GENERIC ------------------------\n");
Packit 1fb8d4
Packit 1fb8d4
		if (!TestPrimitiveYUV(generic, roi, TRUE))
Packit 1fb8d4
		{
Packit 1fb8d4
			printf("TestPrimitiveYUV (444) failed.\n");
Packit 1fb8d4
			goto end;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		printf("---------------------- END --------------------------\n");
Packit 1fb8d4
		printf("------------------- OPTIMIZED -----------------------\n");
Packit 1fb8d4
Packit 1fb8d4
		if (!TestPrimitiveYUV(prims, roi, TRUE))
Packit 1fb8d4
		{
Packit 1fb8d4
			printf("TestPrimitiveYUV (444) failed.\n");
Packit 1fb8d4
			goto end;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		printf("---------------------- END --------------------------\n");
Packit 1fb8d4
		printf("-------------------- GENERIC ------------------------\n");
Packit 1fb8d4
Packit 1fb8d4
		if (!TestPrimitiveYUV(generic, roi, FALSE))
Packit 1fb8d4
		{
Packit 1fb8d4
			printf("TestPrimitiveYUV (420) failed.\n");
Packit 1fb8d4
			goto end;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		printf("---------------------- END --------------------------\n");
Packit 1fb8d4
		printf("------------------- OPTIMIZED -----------------------\n");
Packit 1fb8d4
Packit 1fb8d4
		if (!TestPrimitiveYUV(prims, roi, FALSE))
Packit 1fb8d4
		{
Packit 1fb8d4
			printf("TestPrimitiveYUV (420) failed.\n");
Packit 1fb8d4
			goto end;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		printf("---------------------- END --------------------------\n");
Packit 1fb8d4
		printf("-------------------- GENERIC ------------------------\n");
Packit 1fb8d4
Packit 1fb8d4
		if (!TestPrimitiveYUVCombine(generic, roi))
Packit 1fb8d4
		{
Packit 1fb8d4
			printf("TestPrimitiveYUVCombine failed.\n");
Packit 1fb8d4
			goto end;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		printf("---------------------- END --------------------------\n");
Packit 1fb8d4
		printf("------------------- OPTIMIZED -----------------------\n");
Packit 1fb8d4
Packit 1fb8d4
		if (!TestPrimitiveYUVCombine(prims, roi))
Packit 1fb8d4
		{
Packit 1fb8d4
			printf("TestPrimitiveYUVCombine failed.\n");
Packit 1fb8d4
			goto end;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		printf("---------------------- END --------------------------\n");
Packit 1fb8d4
		printf("------------------- OPTIMIZED -----------------------\n");
Packit 1fb8d4
Packit 1fb8d4
		if (!TestPrimitiveRgbToLumaChroma(prims, roi, 1))
Packit 1fb8d4
		{
Packit 1fb8d4
			printf("TestPrimitiveRgbToLumaChroma failed.\n");
Packit 1fb8d4
			goto end;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		printf("---------------------- END --------------------------\n");
Packit 1fb8d4
		printf("-------------------- GENERIC ------------------------\n");
Packit 1fb8d4
Packit 1fb8d4
		if (!TestPrimitiveRgbToLumaChroma(prims, roi, 2))
Packit 1fb8d4
		{
Packit 1fb8d4
			printf("TestPrimitiveYUVCombine failed.\n");
Packit 1fb8d4
			goto end;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		printf("---------------------- END --------------------------\n");
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	rc = 0;
Packit 1fb8d4
end:
Packit 1fb8d4
	return rc;
Packit 1fb8d4
}
Packit 1fb8d4