1/*-------------------------------------------------------------------------
2 * drawElements Internal Test Module
3 * ---------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Image comparison tests.
22 *//*--------------------------------------------------------------------*/
23
24#include "ditImageCompareTests.hpp"
25#include "tcuResource.hpp"
26#include "tcuImageCompare.hpp"
27#include "tcuFuzzyImageCompare.hpp"
28#include "tcuImageIO.hpp"
29#include "tcuTexture.hpp"
30#include "tcuTestLog.hpp"
31#include "tcuTextureUtil.hpp"
32#include "tcuRGBA.hpp"
33#include "deFilePath.hpp"
34#include "deClock.h"
35
36namespace dit
37{
38
39using tcu::TestLog;
40
41static const char*	BASE_DIR			= "data/imagecompare";
42
43static void loadImageRGBA8 (tcu::TextureLevel& dst, const tcu::Archive& archive, const char* path)
44{
45	tcu::TextureLevel tmp;
46	tcu::ImageIO::loadImage(tmp, archive, path);
47
48	dst.setStorage(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), tmp.getWidth(), tmp.getHeight());
49	tcu::copy(dst, tmp);
50}
51
52class FuzzyComparisonMetricCase : public tcu::TestCase
53{
54public:
55	FuzzyComparisonMetricCase (tcu::TestContext& testCtx, const char* name, const char* refImg, const char* cmpImg, const float minBound, const float maxBound)
56		: tcu::TestCase	(testCtx, name, "")
57		, m_refImg		(refImg)
58		, m_cmpImg		(cmpImg)
59		, m_minBound	(minBound)
60		, m_maxBound	(maxBound)
61	{
62	}
63
64	IterateResult iterate (void)
65	{
66		tcu::TextureLevel		refImg;
67		tcu::TextureLevel		cmpImg;
68		tcu::TextureLevel		errorMask;
69		tcu::FuzzyCompareParams	params;
70		float					result		= 0.0f;
71		deUint64				compareTime	= 0;
72
73		params.maxSampleSkip = 0;
74
75		tcu::ImageIO::loadImage(refImg, m_testCtx.getArchive(), de::FilePath::join(BASE_DIR, m_refImg).getPath());
76		tcu::ImageIO::loadImage(cmpImg, m_testCtx.getArchive(), de::FilePath::join(BASE_DIR, m_cmpImg).getPath());
77
78		errorMask.setStorage(refImg.getFormat(), refImg.getWidth(), refImg.getHeight(), refImg.getDepth());
79
80		{
81			const deUint64 startTime = deGetMicroseconds();
82			result = tcu::fuzzyCompare(params, refImg, cmpImg, errorMask);
83			compareTime = deGetMicroseconds()-startTime;
84		}
85
86		m_testCtx.getLog() << TestLog::Float("Result", "Result metric", "", QP_KEY_TAG_NONE, result)
87						   << TestLog::Float("MinBound", "Minimum bound", "", QP_KEY_TAG_NONE, m_minBound)
88						   << TestLog::Float("MaxBound", "Maximum bound", "", QP_KEY_TAG_NONE, m_maxBound)
89						   << TestLog::Integer("CompareTime", "Comparison time", "us", QP_KEY_TAG_TIME, compareTime);
90
91		{
92			const bool isOk = de::inRange(result, m_minBound, m_maxBound);
93			m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
94									isOk ? "Pass"				: "Metric out of bounds");
95		}
96
97		return STOP;
98	}
99
100private:
101	const std::string	m_refImg;
102	const std::string	m_cmpImg;
103	const float			m_minBound;
104	const float			m_maxBound;
105};
106
107class BilinearCompareCase : public tcu::TestCase
108{
109public:
110	BilinearCompareCase (tcu::TestContext& testCtx, const char* name, const char* refImg, const char* cmpImg, const tcu::RGBA& threshold, bool expectedResult)
111		: tcu::TestCase		(testCtx, name, "")
112		, m_refImg			(refImg)
113		, m_cmpImg			(cmpImg)
114		, m_threshold		(threshold)
115		, m_expectedResult	(expectedResult)
116	{
117	}
118
119	IterateResult iterate (void)
120	{
121		tcu::TextureLevel		refImg;
122		tcu::TextureLevel		cmpImg;
123		bool					result;
124		deUint64				compareTime	= 0;
125
126		loadImageRGBA8(refImg, m_testCtx.getArchive(), de::FilePath::join(BASE_DIR, m_refImg).getPath());
127		loadImageRGBA8(cmpImg, m_testCtx.getArchive(), de::FilePath::join(BASE_DIR, m_cmpImg).getPath());
128
129		{
130			const deUint64 startTime = deGetMicroseconds();
131			result = tcu::bilinearCompare(m_testCtx.getLog(), "CompareResult", "Image comparison result", refImg, cmpImg, m_threshold, tcu::COMPARE_LOG_EVERYTHING);
132			compareTime = deGetMicroseconds()-startTime;
133		}
134
135		m_testCtx.getLog() << TestLog::Integer("CompareTime", "Comparison time", "us", QP_KEY_TAG_TIME, compareTime);
136
137		{
138			const bool isOk = result == m_expectedResult;
139			m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
140									isOk ? "Pass"				: "Wrong comparison result");
141		}
142
143		return STOP;
144	}
145
146private:
147	const std::string		m_refImg;
148	const std::string		m_cmpImg;
149	const tcu::RGBA			m_threshold;
150	const bool				m_expectedResult;
151};
152
153class FuzzyComparisonMetricTests : public tcu::TestCaseGroup
154{
155public:
156	FuzzyComparisonMetricTests (tcu::TestContext& testCtx)
157		: tcu::TestCaseGroup(testCtx, "fuzzy_metric", "Fuzzy comparison metrics")
158	{
159	}
160
161	void init (void)
162	{
163		addChild(new FuzzyComparisonMetricCase(m_testCtx, "identical",		"cube_ref.png",				"cube_ref.png",				0.0f,			0.000001f));
164		addChild(new FuzzyComparisonMetricCase(m_testCtx, "cube",			"cube_ref.png",				"cube_cmp.png",				0.0029f,		0.0031f));
165		addChild(new FuzzyComparisonMetricCase(m_testCtx, "cube_2",			"cube_2_ref.png",			"cube_2_cmp.png",			0.0134f,		0.0140f));
166		addChild(new FuzzyComparisonMetricCase(m_testCtx, "cube_sphere",	"cube_sphere_ref.png",		"cube_sphere_cmp.png",		0.0730f,		0.0801f));
167		addChild(new FuzzyComparisonMetricCase(m_testCtx, "cube_nmap",		"cube_nmap_ref.png",		"cube_nmap_cmp.png",		0.0024f,		0.0025f));
168		addChild(new FuzzyComparisonMetricCase(m_testCtx, "cube_nmap_2",	"cube_nmap_2_ref.png",		"cube_nmap_2_cmp.png",		0.0172f,		0.0189f));
169		addChild(new FuzzyComparisonMetricCase(m_testCtx, "earth_diffuse",	"earth_diffuse_ref.png",	"earth_diffuse_cmp.png",	0.0f,			0.00002f));
170		addChild(new FuzzyComparisonMetricCase(m_testCtx, "eath_texture",	"earth_texture_ref.png",	"earth_texture_cmp.png",	0.0002f,		0.0003f));
171		addChild(new FuzzyComparisonMetricCase(m_testCtx, "earth_spot",		"earth_spot_ref.png",		"earth_spot_cmp.png",		0.0015f,		0.0018f));
172		addChild(new FuzzyComparisonMetricCase(m_testCtx, "earth_light",	"earth_light_ref.png",		"earth_light_cmp.png",		1.7050f,		1.7070f));
173		addChild(new FuzzyComparisonMetricCase(m_testCtx, "lessThan0",		"lessThan0-reference.png",	"lessThan0-result.png",		0.0003f,		0.0004f));
174		addChild(new FuzzyComparisonMetricCase(m_testCtx, "cube_sphere_2",	"cube_sphere_2_ref.png",	"cube_sphere_2_cmp.png",	0.0207f,		0.0230f));
175		addChild(new FuzzyComparisonMetricCase(m_testCtx, "earth_to_empty",	"earth_spot_ref.png",		"empty_256x256.png",		77074.0f,		77076.0f));
176	}
177};
178
179class BilinearCompareTests : public tcu::TestCaseGroup
180{
181public:
182	BilinearCompareTests (tcu::TestContext& testCtx)
183		: tcu::TestCaseGroup(testCtx, "bilinear_compare", "Bilinear Image Comparison Tests")
184	{
185	}
186
187	void init (void)
188	{
189		addChild(new BilinearCompareCase(m_testCtx, "identical",				"cube_ref.png",						"cube_ref.png",						tcu::RGBA(0,0,0,0),			true));
190		addChild(new BilinearCompareCase(m_testCtx, "empty_to_white",			"empty_256x256.png",				"white_256x256.png",				tcu::RGBA(7,7,7,2),			false));
191		addChild(new BilinearCompareCase(m_testCtx, "white_to_empty",			"white_256x256.png",				"empty_256x256.png",				tcu::RGBA(7,7,7,2),			false));
192		addChild(new BilinearCompareCase(m_testCtx, "cube",						"cube_ref.png",						"cube_cmp.png",						tcu::RGBA(7,7,7,2),			false));
193		addChild(new BilinearCompareCase(m_testCtx, "cube_2",					"cube_2_ref.png",					"cube_2_cmp.png",					tcu::RGBA(7,7,7,2),			false));
194		addChild(new BilinearCompareCase(m_testCtx, "cube_sphere",				"cube_sphere_ref.png",				"cube_sphere_cmp.png",				tcu::RGBA(7,7,7,2),			false));
195		addChild(new BilinearCompareCase(m_testCtx, "cube_nmap",				"cube_nmap_ref.png",				"cube_nmap_cmp.png",				tcu::RGBA(7,7,7,2),			false));
196		addChild(new BilinearCompareCase(m_testCtx, "cube_nmap_2",				"cube_nmap_2_ref.png",				"cube_nmap_2_cmp.png",				tcu::RGBA(7,7,7,2),			false));
197		addChild(new BilinearCompareCase(m_testCtx, "earth_diffuse",			"earth_diffuse_ref.png",			"earth_diffuse_cmp.png",			tcu::RGBA(20,20,20,2),		true));
198		addChild(new BilinearCompareCase(m_testCtx, "eath_texture",				"earth_texture_ref.png",			"earth_texture_cmp.png",			tcu::RGBA(7,7,7,2),			false));
199		addChild(new BilinearCompareCase(m_testCtx, "earth_spot",				"earth_spot_ref.png",				"earth_spot_cmp.png",				tcu::RGBA(7,7,7,2),			false));
200		addChild(new BilinearCompareCase(m_testCtx, "earth_light",				"earth_light_ref.png",				"earth_light_cmp.png",				tcu::RGBA(7,7,7,2),			false));
201		addChild(new BilinearCompareCase(m_testCtx, "lessThan0",				"lessThan0-reference.png",			"lessThan0-result.png",				tcu::RGBA(36,36,36,2),		true));
202		addChild(new BilinearCompareCase(m_testCtx, "cube_sphere_2",			"cube_sphere_2_ref.png",			"cube_sphere_2_cmp.png",			tcu::RGBA(7,7,7,2),			false));
203		addChild(new BilinearCompareCase(m_testCtx, "earth_to_empty",			"earth_spot_ref.png",				"empty_256x256.png",				tcu::RGBA(7,7,7,2),			false));
204		addChild(new BilinearCompareCase(m_testCtx, "texfilter",				"texfilter_ref.png",				"texfilter_cmp.png",				tcu::RGBA(7,7,7,2),			true));
205		addChild(new BilinearCompareCase(m_testCtx, "refract_vtx",				"refract_vtx_ref.png",				"refract_vtx_cmp.png",				tcu::RGBA(7,7,7,2),			true));
206		addChild(new BilinearCompareCase(m_testCtx, "refract_frag",				"refract_frag_ref.png",				"refract_frag_cmp.png",				tcu::RGBA(7,7,7,2),			true));
207		addChild(new BilinearCompareCase(m_testCtx, "lessthan_vtx",				"lessthan_vtx_ref.png",				"lessthan_vtx_cmp.png",				tcu::RGBA(7,7,7,2),			true));
208		addChild(new BilinearCompareCase(m_testCtx, "2_units_2d",				"2_units_2d_ref.png",				"2_units_2d_cmp.png",				tcu::RGBA(7,7,7,2),			false));
209		addChild(new BilinearCompareCase(m_testCtx, "4_units_cube_vtx",			"4_units_cube_ref.png",				"4_units_cube_cmp.png",				tcu::RGBA(7,7,7,2),			false));
210		addChild(new BilinearCompareCase(m_testCtx, "texfilter_vtx_nearest",	"texfilter_vtx_nearest_ref.png",	"texfilter_vtx_nearest_cmp.png",	tcu::RGBA(7,7,7,2),			false));
211		addChild(new BilinearCompareCase(m_testCtx, "texfilter_vtx_linear",		"texfilter_vtx_linear_ref.png",		"texfilter_vtx_linear_cmp.png",		tcu::RGBA(7,7,7,2),			false));
212		addChild(new BilinearCompareCase(m_testCtx, "readpixels_msaa",			"readpixels_ref.png",				"readpixels_msaa.png",				tcu::RGBA(1,1,1,1),			true));
213	}
214};
215
216ImageCompareTests::ImageCompareTests (tcu::TestContext& testCtx)
217	: tcu::TestCaseGroup(testCtx, "image_compare", "Image comparison tests")
218{
219}
220
221ImageCompareTests::~ImageCompareTests (void)
222{
223}
224
225void ImageCompareTests::init (void)
226{
227	addChild(new FuzzyComparisonMetricTests	(m_testCtx));
228	addChild(new BilinearCompareTests		(m_testCtx));
229}
230
231} // dit
232