text: /*-------------------------------------------------------------------------
   * drawElements Quality Program EGL Module
   * ---------------------------------------
   *
   * 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 Simple Context construction test.
   *//*--------------------------------------------------------------------*/
  
  #include "teglSimpleConfigCase.hpp"
  #include "tcuTestLog.hpp"
  #include "tcuFormatUtil.hpp"
  #include "egluUtil.hpp"
  #include "eglwLibrary.hpp"
  #include "eglwEnums.hpp"
  #include "deStringUtil.hpp"
  
  namespace deqp
  {
  namespace egl
  {
  
  using std::vector;
  using std::string;
  using tcu::TestLog;
  using eglu::ConfigInfo;
  using namespace eglw;
  using namespace eglu;
  
  SimpleConfigCase::SimpleConfigCase (EglTestContext& eglTestCtx, const char* name, const char* description, const FilterList& filters)
  	: TestCase	(eglTestCtx, name, description)
  	, m_filters	(filters)
  	, m_display	(EGL_NO_DISPLAY)
  {
  }
  
  SimpleConfigCase::~SimpleConfigCase (void)
  {
  }
  
  void SimpleConfigCase::init (void)
  {
  	const Library&		egl		= m_eglTestCtx.getLibrary();
  
  	DE_ASSERT(m_display == EGL_NO_DISPLAY && m_configs.empty());
  
  	m_display	= getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
  	m_configs	= chooseConfigs(egl, m_display, m_filters);
  
  	// Log matching configs.
  	{
  		vector<EGLint> configIds(m_configs.size());
  
  		for (size_t ndx = 0; ndx < m_configs.size(); ndx++)
  			configIds[ndx] = getConfigID(egl, m_display, m_configs[ndx]);
  
  		m_testCtx.getLog() << TestLog::Message << "Compatible configs: " << tcu::formatArray(configIds.begin(), configIds.end()) << TestLog::EndMessage;
  	}
  
  	if (m_configs.empty())
  	{
  		egl.terminate(m_display);
  		m_display = EGL_NO_DISPLAY;
  		TCU_THROW(NotSupportedError, "No compatible configs found");
  	}
  
  	// Init config iter
  	m_configIter = m_configs.begin();
  
  	// Init test case result to Pass
  	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
  }
  
  void SimpleConfigCase::deinit (void)
  {
  	if (m_display != EGL_NO_DISPLAY)
  	{
  		m_eglTestCtx.getLibrary().terminate(m_display);
  		m_display = EGL_NO_DISPLAY;
  	}
  	m_configs.clear();
  }
  
  SimpleConfigCase::IterateResult SimpleConfigCase::iterate (void)
  {
  	DE_ASSERT(m_configIter != m_configs.end());
  
  	EGLConfig	config	= *m_configIter++;
  
  	try
  	{
  		executeForConfig(m_display, config);
  	}
  	catch (const tcu::TestError& e)
  	{
  		m_testCtx.getLog() << e;
  		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
  	}
  	// \note Other errors are handled by framework (resource / internal errors).
  
  	return (m_configIter != m_configs.end()) ? CONTINUE : STOP;
  }
  
  template <int Red, int Green, int Blue, int Alpha>
  static bool colorBits (const eglu::CandidateConfig& c)
  {
  	return c.redSize()		== Red		&&
  		   c.greenSize()	== Green	&&
  		   c.blueSize()		== Blue		&&
  		   c.alphaSize()	== Alpha;
  }
  
  template <int Red, int Green, int Blue, int Alpha>
  static bool notColorBits (const eglu::CandidateConfig& c)
  {
  	return c.redSize()		!= Red		||
  		   c.greenSize()	!= Green	||
  		   c.blueSize()		!= Blue		||
  		   c.alphaSize()	!= Alpha;
  }
  
  static bool	hasDepth	(const eglu::CandidateConfig& c)	{ return c.depthSize() > 0;		}
  static bool	noDepth		(const eglu::CandidateConfig& c)	{ return c.depthSize() == 0;	}
  static bool	hasStencil	(const eglu::CandidateConfig& c)	{ return c.stencilSize() > 0;	}
  static bool	noStencil	(const eglu::CandidateConfig& c)	{ return c.stencilSize() == 0;	}
  
  static bool isConformant (const eglu::CandidateConfig& c)
  {
  	return c.get(EGL_CONFIG_CAVEAT) != EGL_NON_CONFORMANT_CONFIG;
  }
  
  static bool notFloat (const eglu::CandidateConfig& c)
  {
  	return c.colorComponentType() != EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT;
  }
  
  static bool notYUV (const eglu::CandidateConfig& c)
  {
  	return c.get(EGL_COLOR_BUFFER_TYPE) != EGL_YUV_BUFFER_EXT;
  }
  
  void getDefaultFilterLists (vector<NamedFilterList>& lists, const FilterList& baseFilters)
  {
  	static const struct
  	{
  		const char*			name;
  		eglu::ConfigFilter	filter;
  	} s_colorRules[] =
  	{
  		{ "rgb565",		colorBits<5, 6, 5, 0> },
  		{ "rgb888",		colorBits<8, 8, 8, 0> },
  		{ "rgba4444",	colorBits<4, 4, 4, 4> },
  		{ "rgba5551",	colorBits<5, 5, 5, 1> },
  		{ "rgba8888",	colorBits<8, 8, 8, 8> }
  	};
  
  	static const struct
  	{
  		const char*			name;
  		eglu::ConfigFilter	filter;
  	} s_depthRules[] =
  	{
  		{ "no_depth",	noDepth		},
  		{ "depth",		hasDepth	},
  	};
  
  	static const struct
  	{
  		const char*			name;
  		eglu::ConfigFilter	filter;
  	} s_stencilRules[] =
  	{
  		{ "no_stencil",	noStencil	},
  		{ "stencil",	hasStencil	},
  	};
  
  	for (int colorRuleNdx = 0; colorRuleNdx < DE_LENGTH_OF_ARRAY(s_colorRules); colorRuleNdx++)
  	{
  		for (int depthRuleNdx = 0; depthRuleNdx < DE_LENGTH_OF_ARRAY(s_depthRules); depthRuleNdx++)
  		{
  			for (int stencilRuleNdx = 0; stencilRuleNdx < DE_LENGTH_OF_ARRAY(s_stencilRules); stencilRuleNdx++)
  			{
  				const string		name		= string(s_colorRules[colorRuleNdx].name) + "_" + s_depthRules[depthRuleNdx].name + "_" + s_stencilRules[stencilRuleNdx].name;
  				NamedFilterList		filters		(name.c_str(), "");
  
  				filters << baseFilters
  						<< s_colorRules[colorRuleNdx].filter
  						<< s_depthRules[depthRuleNdx].filter
  						<< s_stencilRules[stencilRuleNdx].filter
  						<< isConformant;
  
  				lists.push_back(filters);
  			}
  		}
  	}
  
  	// Build "other" set - not configs that don't match any of known color rules
  	{
  		NamedFilterList		filters		("other", "All other configs");
  
  		// \todo [2014-12-18 pyry] Optimize rules
  		filters << baseFilters
  				<< notColorBits<5, 6, 5, 0>
  				<< notColorBits<8, 8, 8, 0>
  				<< notColorBits<4, 4, 4, 4>
  				<< notColorBits<5, 5, 5, 1>
  				<< notColorBits<8, 8, 8, 8>
  				<< isConformant
  				<< notFloat
  				<< notYUV;
  
  		lists.push_back(filters);
  	}
  }
  
  } // egl
  } // deqp
  