/*-------------------------------------------------------------------------
 * 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 EGL Config selection helper.
 *//*--------------------------------------------------------------------*/

#include "egluConfigFilter.hpp"
#include "egluUtil.hpp"
#include "egluConfigInfo.hpp"
#include "eglwEnums.hpp"
#include "deSTLUtil.hpp"

#include <algorithm>

using std::vector;

namespace eglu
{

using namespace eglw;


CandidateConfig::CandidateConfig (const eglw::Library& egl, eglw::EGLDisplay display, eglw::EGLConfig config)
	: m_type(TYPE_EGL_OBJECT)
{
	m_cfg.object.egl		= &egl;
	m_cfg.object.display	= display;
	m_cfg.object.config		= config;
}

CandidateConfig::CandidateConfig (const ConfigInfo& configInfo)
	: m_type(TYPE_CONFIG_INFO)
{
	m_cfg.configInfo = &configInfo;
}

int CandidateConfig::get (deUint32 attrib) const
{
	if (m_type == TYPE_CONFIG_INFO)
		return m_cfg.configInfo->getAttribute(attrib);
	else
	{
		if (attrib == EGL_COLOR_COMPONENT_TYPE_EXT)
		{
			const std::vector<std::string>	extensions	= getDisplayExtensions(*m_cfg.object.egl, m_cfg.object.display);

			if (de::contains(extensions.begin(), extensions.end(), "EGL_EXT_pixel_format_float"))
				return getConfigAttribInt(*m_cfg.object.egl, m_cfg.object.display, m_cfg.object.config, attrib);
			else
				return EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
		}
		else
			return getConfigAttribInt(*m_cfg.object.egl, m_cfg.object.display, m_cfg.object.config, attrib);
	}
}

int			CandidateConfig::id					(void) const { return get(EGL_CONFIG_ID);							}
int			CandidateConfig::redSize			(void) const { return get(EGL_RED_SIZE);							}
int			CandidateConfig::greenSize			(void) const { return get(EGL_GREEN_SIZE);							}
int			CandidateConfig::blueSize			(void) const { return get(EGL_BLUE_SIZE);							}
int			CandidateConfig::alphaSize			(void) const { return get(EGL_ALPHA_SIZE);							}
int			CandidateConfig::depthSize			(void) const { return get(EGL_DEPTH_SIZE);							}
int			CandidateConfig::stencilSize		(void) const { return get(EGL_STENCIL_SIZE);						}
int			CandidateConfig::samples			(void) const { return get(EGL_SAMPLES);								}
deUint32	CandidateConfig::renderableType		(void) const { return (deUint32)get(EGL_RENDERABLE_TYPE);			}
deUint32	CandidateConfig::surfaceType		(void) const { return (deUint32)get(EGL_SURFACE_TYPE);				}
deUint32	CandidateConfig::colorComponentType	(void) const { return (deUint32)get(EGL_COLOR_COMPONENT_TYPE_EXT);	}

FilterList& FilterList::operator<< (ConfigFilter filter)
{
	m_rules.push_back(filter);
	return *this;
}

FilterList& FilterList::operator<< (const FilterList& other)
{
	size_t oldEnd = m_rules.size();
	m_rules.resize(m_rules.size()+other.m_rules.size());
	std::copy(other.m_rules.begin(), other.m_rules.end(), m_rules.begin()+oldEnd);
	return *this;
}

bool FilterList::match (const Library& egl, EGLDisplay display, EGLConfig config) const
{
	return match(CandidateConfig(egl, display, config));
}

bool FilterList::match (const ConfigInfo& configInfo) const
{
	return match(CandidateConfig(configInfo));
}

bool FilterList::match (const CandidateConfig& candidate) const
{
	for (vector<ConfigFilter>::const_iterator filterIter = m_rules.begin(); filterIter != m_rules.end(); filterIter++)
	{
		ConfigFilter filter = *filterIter;

		if (!filter(candidate))
			return false;
	}

	return true;
}


} // eglu
