Home | History | Annotate | Download | only in glshared
      1 #ifndef _GLSFBOUTIL_HPP
      2 #define _GLSFBOUTIL_HPP
      3 
      4 /*-------------------------------------------------------------------------
      5  * drawElements Quality Program OpenGL (ES) Module
      6  * -----------------------------------------------
      7  *
      8  * Copyright 2014 The Android Open Source Project
      9  *
     10  * Licensed under the Apache License, Version 2.0 (the "License");
     11  * you may not use this file except in compliance with the License.
     12  * You may obtain a copy of the License at
     13  *
     14  *      http://www.apache.org/licenses/LICENSE-2.0
     15  *
     16  * Unless required by applicable law or agreed to in writing, software
     17  * distributed under the License is distributed on an "AS IS" BASIS,
     18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     19  * See the License for the specific language governing permissions and
     20  * limitations under the License.
     21  *
     22  *//*!
     23  * \file
     24  * \brief Utilities for framebuffer objects.
     25  *//*--------------------------------------------------------------------*/
     26 
     27 #include "gluRenderContext.hpp"
     28 #include "gluContextInfo.hpp"
     29 #include "glwDefs.hpp"
     30 #include "glwEnums.hpp"
     31 #include "glwFunctions.hpp"
     32 #include "gluTextureUtil.hpp"
     33 #include "tcuTestLog.hpp"
     34 #include "tcuDefs.hpp"
     35 
     36 #include <map>
     37 #include <set>
     38 #include <vector>
     39 #include <algorithm>
     40 #include <iterator>
     41 
     42 namespace deqp
     43 {
     44 namespace gls
     45 {
     46 
     47 // Utilities for standard containers. \todo [2013-12-10 lauri] Move to decpp?
     48 
     49 //! A pair of iterators to present a range.
     50 //! \note This must be POD to allow static initialization.
     51 //! \todo [2013-12-03 lauri] Move this to decpp?
     52 template <typename T>
     53 struct Range
     54 {
     55 	typedef const T*	const_iterator;
     56 
     57 	const T*	m_begin;
     58 	const T*	m_end;
     59 
     60 	const T*	begin		(void) const { return m_begin; }
     61 	const T*	end			(void) const { return m_end; }
     62 };
     63 
     64 #define GLS_ARRAY_RANGE(ARR) { DE_ARRAY_BEGIN(ARR), DE_ARRAY_END(ARR) }
     65 
     66 #define GLS_NULL_RANGE { DE_NULL, DE_NULL }
     67 
     68 
     69 //! A pair type that, unlike stl::pair, is POD so it can be statically initialized.
     70 template <typename T1, typename T2>
     71 struct Pair
     72 {
     73 	typedef	T1	first_type;
     74 	typedef T2	second_type;
     75 	T1			first;
     76 	T2			second;
     77 };
     78 
     79 template<typename C>
     80 C intersection(const C& s1, const C& s2)
     81 {
     82 	C ret;
     83 	std::set_intersection(s1.begin(), s1.end(), s2.begin(), s2.end(),
     84 						  std::insert_iterator<C>(ret, ret.begin()));
     85 	return ret;
     86 }
     87 
     88 // \todo [2013-12-03 lauri] move to decpp?
     89 template<typename C>
     90 inline bool isMember (const typename C::key_type& key, const C& container)
     91 {
     92 	typename C::const_iterator it = container.find(key);
     93 	return (it != container.end());
     94 }
     95 
     96 template <typename M> inline
     97 const typename M::mapped_type* lookupMaybe (const M& map,
     98 											const typename M::key_type& key)
     99 {
    100 	typename M::const_iterator it = map.find(key);
    101 	if (it == map.end())
    102 		return DE_NULL;
    103 	return &it->second;
    104 }
    105 
    106 template<typename M> inline
    107 const typename M::mapped_type& lookupDefault (const M& map,
    108 											  const typename M::key_type& key,
    109 											  const typename M::mapped_type& fallback)
    110 {
    111 	const typename M::mapped_type* ptr = lookupMaybe(map, key);
    112 	return ptr == DE_NULL ? fallback : *ptr;
    113 }
    114 
    115 
    116 template<typename M>
    117 const typename M::mapped_type& lookup (const M& map,
    118 									   const typename M::key_type& key)
    119 {
    120 	const typename M::mapped_type* ptr = lookupMaybe(map, key);
    121 	if (ptr == DE_NULL)
    122 		throw std::out_of_range("key not found in map");
    123 	return *ptr;
    124 }
    125 
    126 template<typename C>
    127 inline bool contains (const C& container, const typename C::value_type& item)
    128 {
    129 	const typename C::const_iterator it = container.find(item);
    130 	return (it != container.end());
    131 }
    132 
    133 
    134 template<typename M> static inline
    135 bool insert(const typename M::key_type& key, const typename M::mapped_type& value, M& map)
    136 {
    137 	typename M::value_type entry(key, value);
    138 	std::pair<typename M::iterator,bool> ret = map.insert(entry);
    139 	return ret.second;
    140 }
    141 
    142 std::vector<std::string> splitString(const std::string& s);
    143 
    144 namespace FboUtil
    145 {
    146 
    147 //! Configurations for framebuffer objects and their attachments.
    148 
    149 class FboVerifier;
    150 class FboBuilder;
    151 
    152 typedef deUint32		FormatKey;
    153 
    154 #define GLS_UNSIZED_FORMATKEY(FORMAT, TYPE) \
    155 	(deUint32(TYPE) << 16 | deUint32(FORMAT))
    156 
    157 typedef Range<FormatKey>	FormatKeys;
    158 
    159 struct ImageFormat
    160 {
    161 	glw::GLenum				format;
    162 
    163 	//! Type if format is unsized, GL_NONE if sized.
    164 	glw::GLenum				unsizedType;
    165 
    166 	bool 					operator<		(const ImageFormat& other) const
    167 	{
    168 		return (format < other.format ||
    169 				(format == other.format && unsizedType < other.unsizedType));
    170 	}
    171 
    172 	static ImageFormat		none			(void)
    173 	{
    174 		ImageFormat fmt = { GL_NONE, GL_NONE };
    175 		return fmt;
    176 	}
    177 };
    178 
    179 static inline ImageFormat formatKeyInfo(FormatKey key)
    180 {
    181 	ImageFormat fmt = { key & 0xffff, key >> 16 };
    182 	return fmt;
    183 }
    184 
    185 enum FormatFlags
    186 {
    187 	ANY_FORMAT			= 0,
    188 	COLOR_RENDERABLE	= 1 << 0,
    189 	DEPTH_RENDERABLE	= 1 << 1,
    190 	STENCIL_RENDERABLE	= 1 << 2,
    191 	RENDERBUFFER_VALID	= 1 << 3,
    192 	TEXTURE_VALID		= 1 << 4,
    193 	REQUIRED_RENDERABLE	= 1 << 5, //< Without this, renderability is allowed, not required.
    194 };
    195 
    196 static inline FormatFlags operator|(FormatFlags f1, FormatFlags f2)
    197 {
    198 	return FormatFlags(deUint32(f1) | deUint32(f2));
    199 }
    200 
    201 FormatFlags formatFlag(glw::GLenum context);
    202 
    203 typedef std::set<ImageFormat> Formats;
    204 
    205 class FormatDB
    206 {
    207 public:
    208 	void							addFormat		(ImageFormat format, FormatFlags flags);
    209 	Formats							getFormats		(FormatFlags requirements) const;
    210 	FormatFlags						getFormatInfo	(ImageFormat format,
    211 													 FormatFlags fallback) const;
    212 
    213 private:
    214 	typedef std::map<ImageFormat, FormatFlags>		FormatMap;
    215 
    216 	FormatMap						m_map;
    217 };
    218 
    219 typedef Pair<FormatFlags, FormatKeys>				FormatEntry;
    220 typedef Range<FormatEntry>							FormatEntries;
    221 
    222 // \todo [2013-12-20 lauri] It turns out that format properties in extensions
    223 // are actually far too fine-grained for this bundling to be reasonable,
    224 // especially given the syntactic cumbersomeness of static arrays. It's better
    225 // to list each entry separately.
    226 
    227 struct FormatExtEntry
    228 {
    229 	const char*									extensions;
    230 	deUint32									flags;
    231 	Range<FormatKey>							formats;
    232 };
    233 
    234 typedef Range<FormatExtEntry>						FormatExtEntries;
    235 
    236 void				addFormats			(FormatDB& db, FormatEntries stdFmts);
    237 void 				addExtFormats		(FormatDB& db, FormatExtEntries extFmts,
    238 										 const glu::RenderContext* ctx);
    239 glu::TransferFormat	transferImageFormat	(const ImageFormat& imgFormat);
    240 
    241 namespace config
    242 {
    243 
    244 struct Config
    245 {
    246 	virtual 					~Config			(void) {};
    247 };
    248 
    249 struct Image : public Config
    250 {
    251 	ImageFormat					internalFormat;
    252 	glw::GLsizei				width;
    253 	glw::GLsizei				height;
    254 
    255 protected:
    256 								Image			(void)
    257 									: internalFormat	(ImageFormat::none())
    258 									, width				(0)
    259 									, height			(0) {}
    260 };
    261 
    262 struct Renderbuffer : public Image
    263 {
    264 						Renderbuffer	(void) : numSamples(0) {}
    265 
    266 	glw::GLsizei		numSamples;
    267 };
    268 
    269 struct Texture : public Image
    270 {
    271 							Texture			(void) : numLevels(1) {}
    272 
    273 	glw::GLint 				numLevels;
    274 };
    275 
    276 struct TextureFlat : public Texture
    277 {
    278 };
    279 
    280 struct Texture2D : public TextureFlat
    281 {
    282 };
    283 
    284 struct TextureCubeMap : public TextureFlat
    285 {
    286 };
    287 
    288 struct TextureLayered : public Texture
    289 {
    290 							TextureLayered	(void) : numLayers(1) {}
    291 	glw::GLsizei			numLayers;
    292 };
    293 
    294 struct Texture3D : public TextureLayered
    295 {
    296 };
    297 
    298 struct Texture2DArray : public TextureLayered
    299 {
    300 };
    301 
    302 struct Attachment : public Config
    303 {
    304 							Attachment		(void) : target(GL_FRAMEBUFFER), imageName(0) {}
    305 
    306 	glw::GLenum 			target;
    307 	glw::GLuint 			imageName;
    308 
    309 	//! Returns `true` iff this attachment is "framebuffer attachment
    310 	//! complete" when bound to attachment point `attPoint`, and the current
    311 	//! image with name `imageName` is `image`, using `vfr` to check format
    312 	//! renderability.
    313 	bool					isComplete		(glw::GLenum attPoint, const Image* image,
    314 											 const FboVerifier& vfr) const;
    315 };
    316 
    317 struct RenderbufferAttachment : public Attachment
    318 {
    319 				RenderbufferAttachment	(void)
    320 				: renderbufferTarget(GL_RENDERBUFFER) {}
    321 
    322 	glw::GLenum renderbufferTarget;
    323 };
    324 
    325 struct TextureAttachment : public Attachment
    326 {
    327 							TextureAttachment	(void) : level(0) {}
    328 
    329 	glw::GLint				level;
    330 };
    331 
    332 struct TextureFlatAttachment : public TextureAttachment
    333 {
    334 							TextureFlatAttachment (void) : texTarget(GL_NONE) {}
    335 
    336 	glw::GLenum				texTarget;
    337 };
    338 
    339 struct TextureLayerAttachment : public TextureAttachment
    340 {
    341 							TextureLayerAttachment (void) : layer(0) {}
    342 
    343 	glw::GLsizei			layer;
    344 };
    345 
    346 glw::GLenum		attachmentType	(const Attachment& att);
    347 glw::GLsizei	imageNumSamples	(const Image& img);
    348 
    349 //! Mapping from attachment points to attachment configurations.
    350 typedef std::map<glw::GLenum, const Attachment*> AttachmentMap;
    351 
    352 //! Mapping from object names to texture configurations.
    353 typedef std::map<glw::GLuint, const Texture*> TextureMap;
    354 
    355 //! Mapping from object names to renderbuffer configurations.
    356 typedef std::map<glw::GLuint, const Renderbuffer*> RboMap;
    357 
    358 //! A framebuffer configuration.
    359 struct Framebuffer
    360 {
    361 	AttachmentMap			attachments;
    362 	TextureMap				textures;
    363 	RboMap					rbos;
    364 
    365 	void					attach			(glw::GLenum attPoint, const Attachment* att);
    366 	void					setTexture		(glw::GLuint texName, const Texture& texCfg);
    367 	void					setRbo			(glw::GLuint rbName, const Renderbuffer& rbCfg);
    368 	const Image*			getImage		(glw::GLenum type, glw::GLuint imgName) const;
    369 };
    370 
    371 } // config
    372 
    373 void logFramebufferConfig(const config::Framebuffer& cfg, tcu::TestLog& log);
    374 
    375 class FboBuilder : public config::Framebuffer
    376 {
    377 public:
    378 	void						glAttach		(glw::GLenum attPoint,
    379 												 const config::Attachment* att);
    380 	glw::GLuint					glCreateTexture	(const config::Texture& texCfg);
    381 	glw::GLuint					glCreateRbo		(const config::Renderbuffer& rbCfg);
    382 								FboBuilder		(glw::GLuint fbo, glw::GLenum target,
    383 												 const glw::Functions& gl);
    384 								~FboBuilder		(void);
    385 	glw::GLenum					getError		(void) { return m_error; }
    386 
    387 	//! Allocate a new configuration of type `Config` (which must be a
    388 	//! subclass of `config::Config`), and return a referenc to it. The newly
    389 	//! allocated object will be freed when this builder object is destroyed.
    390 	template<typename Config>
    391 	Config&						makeConfig		(void)
    392 	{
    393 		Config* cfg = new Config();
    394 		m_configs.insert(cfg);
    395 		return *cfg;
    396 	}
    397 
    398 private:
    399 	typedef std::set<config::Config*> Configs;
    400 
    401 	void						checkError		(void);
    402 
    403 	glw::GLenum					m_error;		//< The first GL error encountered.
    404 	glw::GLenum					m_target;
    405 	const glw::Functions&		m_gl;
    406 	Configs						m_configs;
    407 };
    408 
    409 typedef std::set<glw::GLenum> StatusCodes;
    410 
    411 class Checker
    412 {
    413 public:
    414 					Checker			(void) { m_statusCodes.insert(GL_FRAMEBUFFER_COMPLETE); }
    415 	virtual			~Checker		(void) {}
    416 	void			require			(bool condition, glw::GLenum error);
    417 	void			canRequire		(bool condition, glw::GLenum error);
    418 	StatusCodes		getStatusCodes	(void) { return m_statusCodes; }
    419 	virtual void	check			(glw::GLenum attPoint, const config::Attachment& att,
    420 									 const config::Image* image) = 0;
    421 private:
    422 
    423 	StatusCodes		m_statusCodes;	//< Allowed return values for glCheckFramebufferStatus.
    424 };
    425 
    426 class CheckerFactory
    427 {
    428 public:
    429 	virtual Checker*	createChecker	(void) = 0;
    430 };
    431 
    432 typedef std::set<glw::GLenum> AttachmentPoints;
    433 typedef std::set<ImageFormat> Formats;
    434 
    435 class FboVerifier
    436 {
    437 public:
    438 								FboVerifier				(const FormatDB& formats,
    439 														 CheckerFactory& factory);
    440 
    441 	StatusCodes					validStatusCodes		(const config::Framebuffer& cfg) const;
    442 
    443 private:
    444 	const FormatDB&				m_formats;
    445 	CheckerFactory&				m_factory;
    446 };
    447 
    448 } // FboUtil
    449 } // gls
    450 } // deqp
    451 
    452 #endif // _GLSFBOUTIL_HPP
    453