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 //! A pair of iterators to present a range.
     48 //! \note This must be POD to allow static initialization.
     49 //! \todo [2013-12-03 lauri] Move this to decpp?
     50 template <typename T>
     51 struct Range
     52 {
     53 	typedef const T*	const_iterator;
     54 
     55 	const T*	m_begin;
     56 	const T*	m_end;
     57 
     58 	const T*	begin		(void) const { return m_begin; }
     59 	const T*	end			(void) const { return m_end; }
     60 };
     61 
     62 #define GLS_ARRAY_RANGE(ARR) { DE_ARRAY_BEGIN(ARR), DE_ARRAY_END(ARR) }
     63 
     64 #define GLS_NULL_RANGE { DE_NULL, DE_NULL }
     65 
     66 
     67 //! A pair type that, unlike stl::pair, is POD so it can be statically initialized.
     68 template <typename T1, typename T2>
     69 struct Pair
     70 {
     71 	typedef	T1	first_type;
     72 	typedef T2	second_type;
     73 	T1			first;
     74 	T2			second;
     75 };
     76 
     77 namespace FboUtil
     78 {
     79 
     80 //! Configurations for framebuffer objects and their attachments.
     81 
     82 class FboVerifier;
     83 class FboBuilder;
     84 
     85 typedef deUint32		FormatKey;
     86 
     87 #define GLS_UNSIZED_FORMATKEY(FORMAT, TYPE) \
     88 	(deUint32(TYPE) << 16 | deUint32(FORMAT))
     89 
     90 typedef Range<FormatKey>	FormatKeys;
     91 
     92 struct ImageFormat
     93 {
     94 	glw::GLenum				format;
     95 
     96 	//! Type if format is unsized, GL_NONE if sized.
     97 	glw::GLenum				unsizedType;
     98 
     99 	bool					operator<		(const ImageFormat& other) const
    100 	{
    101 		return (format < other.format ||
    102 				(format == other.format && unsizedType < other.unsizedType));
    103 	}
    104 
    105 	static ImageFormat		none			(void)
    106 	{
    107 		ImageFormat fmt = { GL_NONE, GL_NONE };
    108 		return fmt;
    109 	}
    110 };
    111 
    112 std::ostream& operator<< (std::ostream& stream, const ImageFormat& format);
    113 
    114 static inline ImageFormat formatKeyInfo(FormatKey key)
    115 {
    116 	ImageFormat fmt = { key & 0xffff, key >> 16 };
    117 	return fmt;
    118 }
    119 
    120 enum FormatFlags
    121 {
    122 	ANY_FORMAT			= 0,
    123 	COLOR_RENDERABLE	= 1 << 0,
    124 	DEPTH_RENDERABLE	= 1 << 1,
    125 	STENCIL_RENDERABLE	= 1 << 2,
    126 	RENDERBUFFER_VALID	= 1 << 3,
    127 	TEXTURE_VALID		= 1 << 4,
    128 	REQUIRED_RENDERABLE	= 1 << 5, //< Without this, renderability is allowed, not required.
    129 };
    130 
    131 static inline FormatFlags operator|(FormatFlags f1, FormatFlags f2)
    132 {
    133 	return FormatFlags(deUint32(f1) | deUint32(f2));
    134 }
    135 
    136 FormatFlags formatFlag(glw::GLenum context);
    137 
    138 typedef std::set<ImageFormat> Formats;
    139 
    140 class FormatDB
    141 {
    142 public:
    143 	void								addCoreFormat				(ImageFormat format, FormatFlags flags);
    144 	void								addExtensionFormat			(ImageFormat format, FormatFlags flags, const std::set<std::string>& requiredExtensions);
    145 
    146 	Formats								getFormats					(FormatFlags requirements) const;
    147 	bool								isKnownFormat				(ImageFormat format) const;
    148 	FormatFlags							getFormatInfo				(ImageFormat format) const;
    149 	std::set<std::set<std::string> >	getFormatFeatureExtensions	(ImageFormat format, FormatFlags requirements) const;
    150 
    151 private:
    152 	struct ExtensionInfo
    153 	{
    154 		FormatFlags					flags;
    155 		std::set<std::string>		requiredExtensions;
    156 
    157 		bool						operator<			(const ExtensionInfo& other) const;
    158 	};
    159 
    160 	typedef std::map<ImageFormat, FormatFlags>					FormatMap;
    161 	typedef std::map<ImageFormat, std::set<ExtensionInfo> >		FormatExtensionMap;
    162 
    163 	FormatMap							m_formatFlags;
    164 	FormatExtensionMap					m_formatExtensions;
    165 };
    166 
    167 typedef Pair<FormatFlags, FormatKeys>				FormatEntry;
    168 typedef Range<FormatEntry>							FormatEntries;
    169 
    170 // \todo [2013-12-20 lauri] It turns out that format properties in extensions
    171 // are actually far too fine-grained for this bundling to be reasonable,
    172 // especially given the syntactic cumbersomeness of static arrays. It's better
    173 // to list each entry separately.
    174 
    175 struct FormatExtEntry
    176 {
    177 	const char*									extensions;
    178 	deUint32									flags;
    179 	Range<FormatKey>							formats;
    180 };
    181 
    182 typedef Range<FormatExtEntry>						FormatExtEntries;
    183 
    184 // Check support for GL_* and DEQP_* extensions
    185 bool				checkExtensionSupport		(const glu::RenderContext& ctx, const std::string& extension);
    186 
    187 // Accepts GL_* and DEQP_* extension strings and converts DEQP_* strings to a human readable string
    188 std::string			getExtensionDescription		(const std::string& extensionName);
    189 
    190 void				addFormats					(FormatDB& db, FormatEntries stdFmts);
    191 void				addExtFormats				(FormatDB& db, FormatExtEntries extFmts, const glu::RenderContext* ctx);
    192 glu::TransferFormat	transferImageFormat			(const ImageFormat& imgFormat);
    193 
    194 namespace config
    195 {
    196 
    197 struct Config
    198 {
    199 	virtual						~Config			(void) {};
    200 };
    201 
    202 struct Image : public Config
    203 {
    204 	ImageFormat					internalFormat;
    205 	glw::GLsizei				width;
    206 	glw::GLsizei				height;
    207 
    208 protected:
    209 								Image			(void)
    210 									: internalFormat	(ImageFormat::none())
    211 									, width				(0)
    212 									, height			(0) {}
    213 };
    214 
    215 struct Renderbuffer : public Image
    216 {
    217 						Renderbuffer	(void) : numSamples(0) {}
    218 
    219 	glw::GLsizei		numSamples;
    220 };
    221 
    222 struct Texture : public Image
    223 {
    224 							Texture			(void) : numLevels(1) {}
    225 
    226 	glw::GLint				numLevels;
    227 };
    228 
    229 struct TextureFlat : public Texture
    230 {
    231 };
    232 
    233 struct Texture2D : public TextureFlat
    234 {
    235 };
    236 
    237 struct TextureCubeMap : public TextureFlat
    238 {
    239 };
    240 
    241 struct TextureLayered : public Texture
    242 {
    243 							TextureLayered	(void) : numLayers(1) {}
    244 	glw::GLsizei			numLayers;
    245 };
    246 
    247 struct Texture3D : public TextureLayered
    248 {
    249 };
    250 
    251 struct Texture2DArray : public TextureLayered
    252 {
    253 };
    254 
    255 struct Attachment : public Config
    256 {
    257 							Attachment		(void) : target(GL_FRAMEBUFFER), imageName(0) {}
    258 
    259 	glw::GLenum				target;
    260 	glw::GLuint				imageName;
    261 
    262 	//! Returns `true` iff this attachment is "framebuffer attachment
    263 	//! complete" when bound to attachment point `attPoint`, and the current
    264 	//! image with name `imageName` is `image`, using `vfr` to check format
    265 	//! renderability.
    266 	bool					isComplete		(glw::GLenum attPoint, const Image* image,
    267 											 const FboVerifier& vfr) const;
    268 };
    269 
    270 struct RenderbufferAttachment : public Attachment
    271 {
    272 				RenderbufferAttachment	(void)
    273 				: renderbufferTarget(GL_RENDERBUFFER) {}
    274 
    275 	glw::GLenum renderbufferTarget;
    276 };
    277 
    278 struct TextureAttachment : public Attachment
    279 {
    280 							TextureAttachment	(void) : level(0) {}
    281 
    282 	glw::GLint				level;
    283 };
    284 
    285 struct TextureFlatAttachment : public TextureAttachment
    286 {
    287 							TextureFlatAttachment (void) : texTarget(GL_NONE) {}
    288 
    289 	glw::GLenum				texTarget;
    290 };
    291 
    292 struct TextureLayerAttachment : public TextureAttachment
    293 {
    294 							TextureLayerAttachment (void) : layer(0) {}
    295 
    296 	glw::GLsizei			layer;
    297 };
    298 
    299 glw::GLenum		attachmentType	(const Attachment& att);
    300 glw::GLsizei	imageNumSamples	(const Image& img);
    301 
    302 //! Mapping from attachment points to attachment configurations.
    303 typedef std::map<glw::GLenum, const Attachment*> AttachmentMap;
    304 
    305 //! Mapping from object names to texture configurations.
    306 typedef std::map<glw::GLuint, const Texture*> TextureMap;
    307 
    308 //! Mapping from object names to renderbuffer configurations.
    309 typedef std::map<glw::GLuint, const Renderbuffer*> RboMap;
    310 
    311 //! A framebuffer configuration.
    312 struct Framebuffer
    313 {
    314 	AttachmentMap			attachments;
    315 	TextureMap				textures;
    316 	RboMap					rbos;
    317 
    318 	void					attach			(glw::GLenum attPoint, const Attachment* att);
    319 	void					setTexture		(glw::GLuint texName, const Texture& texCfg);
    320 	void					setRbo			(glw::GLuint rbName, const Renderbuffer& rbCfg);
    321 	const Image*			getImage		(glw::GLenum type, glw::GLuint imgName) const;
    322 };
    323 
    324 } // config
    325 
    326 class FboBuilder : public config::Framebuffer
    327 {
    328 public:
    329 	void						glAttach		(glw::GLenum attPoint,
    330 												 const config::Attachment* att);
    331 	glw::GLuint					glCreateTexture	(const config::Texture& texCfg);
    332 	glw::GLuint					glCreateRbo		(const config::Renderbuffer& rbCfg);
    333 								FboBuilder		(glw::GLuint fbo, glw::GLenum target,
    334 												 const glw::Functions& gl);
    335 								~FboBuilder		(void);
    336 	glw::GLenum					getError		(void) { return m_error; }
    337 
    338 	//! Allocate a new configuration of type `Config` (which must be a
    339 	//! subclass of `config::Config`), and return a referenc to it. The newly
    340 	//! allocated object will be freed when this builder object is destroyed.
    341 	template<typename Config>
    342 	Config&						makeConfig		(void)
    343 	{
    344 		Config* cfg = new Config();
    345 		m_configs.insert(cfg);
    346 		return *cfg;
    347 	}
    348 
    349 private:
    350 	typedef std::set<config::Config*> Configs;
    351 
    352 	void						checkError		(void);
    353 
    354 	glw::GLenum					m_error;		//< The first GL error encountered.
    355 	glw::GLenum					m_target;
    356 	const glw::Functions&		m_gl;
    357 	Configs						m_configs;
    358 };
    359 
    360 struct ValidStatusCodes
    361 {
    362 								ValidStatusCodes		(void);
    363 
    364 	bool						isFBOStatusValid		(glw::GLenum fboStatus) const;
    365 	bool						isFBOStatusRequired		(glw::GLenum fboStatus) const;
    366 	bool						isErrorCodeValid		(glw::GLenum errorCode) const;
    367 	bool						isErrorCodeRequired		(glw::GLenum errorCode) const;
    368 
    369 	void						addErrorCode			(glw::GLenum error, const char* description);
    370 	void						addFBOErrorStatus		(glw::GLenum status, const char* description);
    371 	void						setAllowComplete		(bool);
    372 
    373 	void						logLegalResults			(tcu::TestLog& log) const;
    374 	void						logRules				(tcu::TestLog& log) const;
    375 
    376 private:
    377 	struct RuleViolation
    378 	{
    379 		glw::GLenum				errorCode;
    380 		std::set<std::string>	rules;
    381 	};
    382 
    383 	void						logRule					(tcu::TestLog& log, const std::string& ruleName, const std::set<std::string>& rules) const;
    384 	void						addViolation			(std::vector<RuleViolation>& dst, glw::GLenum code, const char* description) const;
    385 
    386 	std::vector<RuleViolation>	m_errorCodes;			//!< Allowed GL errors, GL_NO_ERROR is not allowed
    387 	std::vector<RuleViolation>	m_errorStatuses;		//!< Allowed FBO error statuses, GL_FRAMEBUFFER_COMPLETE is not allowed
    388 	bool						m_allowComplete;		//!< true if (GL_NO_ERROR && GL_FRAMEBUFFER_COMPLETE) is allowed
    389 };
    390 
    391 void logFramebufferConfig (const config::Framebuffer& cfg, tcu::TestLog& log);
    392 
    393 class Checker
    394 {
    395 public:
    396 								Checker					(const glu::RenderContext&);
    397 	virtual						~Checker				(void) {}
    398 
    399 	void						addGLError				(glw::GLenum error, const char* description);
    400 	void						addPotentialGLError		(glw::GLenum error, const char* description);
    401 	void						addFBOStatus			(glw::GLenum status, const char* description);
    402 	void						addPotentialFBOStatus	(glw::GLenum status, const char* description);
    403 
    404 	ValidStatusCodes			getStatusCodes			(void) { return m_statusCodes; }
    405 
    406 	virtual void				check					(glw::GLenum				attPoint,
    407 														 const config::Attachment&	att,
    408 														 const config::Image*		image) = 0;
    409 
    410 protected:
    411 	const glu::RenderContext&	m_renderCtx;
    412 
    413 private:
    414 	ValidStatusCodes			m_statusCodes;	//< Allowed return values for glCheckFramebufferStatus.
    415 };
    416 
    417 class CheckerFactory
    418 {
    419 public:
    420 	virtual Checker*	createChecker	(const glu::RenderContext&) = 0;
    421 };
    422 
    423 typedef std::set<glw::GLenum> AttachmentPoints;
    424 typedef std::set<ImageFormat> Formats;
    425 
    426 class FboVerifier
    427 {
    428 public:
    429 								FboVerifier				(const FormatDB&			formats,
    430 														 CheckerFactory&			factory,
    431 														 const glu::RenderContext&	renderCtx);
    432 
    433 	ValidStatusCodes			validStatusCodes		(const config::Framebuffer& cfg) const;
    434 
    435 private:
    436 	const FormatDB&				m_formats;
    437 	CheckerFactory&				m_factory;
    438 	const glu::RenderContext&	m_renderCtx;
    439 };
    440 
    441 } // FboUtil
    442 } // gls
    443 } // deqp
    444 
    445 #endif // _GLSFBOUTIL_HPP
    446