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 42namespace deqp 43{ 44namespace 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? 50template <typename T> 51struct 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. 68template <typename T1, typename T2> 69struct Pair 70{ 71 typedef T1 first_type; 72 typedef T2 second_type; 73 T1 first; 74 T2 second; 75}; 76 77namespace FboUtil 78{ 79 80//! Configurations for framebuffer objects and their attachments. 81 82class FboVerifier; 83class FboBuilder; 84 85typedef deUint32 FormatKey; 86 87#define GLS_UNSIZED_FORMATKEY(FORMAT, TYPE) \ 88 (deUint32(TYPE) << 16 | deUint32(FORMAT)) 89 90typedef Range<FormatKey> FormatKeys; 91 92struct 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 112std::ostream& operator<< (std::ostream& stream, const ImageFormat& format); 113 114static inline ImageFormat formatKeyInfo(FormatKey key) 115{ 116 ImageFormat fmt = { key & 0xffff, key >> 16 }; 117 return fmt; 118} 119 120enum 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 131static inline FormatFlags operator|(FormatFlags f1, FormatFlags f2) 132{ 133 return FormatFlags(deUint32(f1) | deUint32(f2)); 134} 135 136FormatFlags formatFlag(glw::GLenum context); 137 138typedef std::set<ImageFormat> Formats; 139 140class FormatDB 141{ 142public: 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 151private: 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 167typedef Pair<FormatFlags, FormatKeys> FormatEntry; 168typedef 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 175struct FormatExtEntry 176{ 177 const char* extensions; 178 deUint32 flags; 179 Range<FormatKey> formats; 180}; 181 182typedef Range<FormatExtEntry> FormatExtEntries; 183 184// Check support for GL_* and DEQP_* extensions 185bool 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 188std::string getExtensionDescription (const std::string& extensionName); 189 190void addFormats (FormatDB& db, FormatEntries stdFmts); 191void addExtFormats (FormatDB& db, FormatExtEntries extFmts, const glu::RenderContext* ctx); 192glu::TransferFormat transferImageFormat (const ImageFormat& imgFormat); 193 194namespace config 195{ 196 197struct Config 198{ 199 virtual ~Config (void) {}; 200}; 201 202struct Image : public Config 203{ 204 ImageFormat internalFormat; 205 glw::GLsizei width; 206 glw::GLsizei height; 207 208protected: 209 Image (void) 210 : internalFormat (ImageFormat::none()) 211 , width (0) 212 , height (0) {} 213}; 214 215struct Renderbuffer : public Image 216{ 217 Renderbuffer (void) : numSamples(0) {} 218 219 glw::GLsizei numSamples; 220}; 221 222struct Texture : public Image 223{ 224 Texture (void) : numLevels(1) {} 225 226 glw::GLint numLevels; 227}; 228 229struct TextureFlat : public Texture 230{ 231}; 232 233struct Texture2D : public TextureFlat 234{ 235}; 236 237struct TextureCubeMap : public TextureFlat 238{ 239}; 240 241struct TextureLayered : public Texture 242{ 243 TextureLayered (void) : numLayers(1) {} 244 glw::GLsizei numLayers; 245}; 246 247struct Texture3D : public TextureLayered 248{ 249}; 250 251struct Texture2DArray : public TextureLayered 252{ 253}; 254 255struct 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 270struct RenderbufferAttachment : public Attachment 271{ 272 RenderbufferAttachment (void) 273 : renderbufferTarget(GL_RENDERBUFFER) {} 274 275 glw::GLenum renderbufferTarget; 276}; 277 278struct TextureAttachment : public Attachment 279{ 280 TextureAttachment (void) : level(0) {} 281 282 glw::GLint level; 283}; 284 285struct TextureFlatAttachment : public TextureAttachment 286{ 287 TextureFlatAttachment (void) : texTarget(GL_NONE) {} 288 289 glw::GLenum texTarget; 290}; 291 292struct TextureLayerAttachment : public TextureAttachment 293{ 294 TextureLayerAttachment (void) : layer(0) {} 295 296 glw::GLsizei layer; 297}; 298 299glw::GLenum attachmentType (const Attachment& att); 300glw::GLsizei imageNumSamples (const Image& img); 301 302//! Mapping from attachment points to attachment configurations. 303typedef std::map<glw::GLenum, const Attachment*> AttachmentMap; 304 305//! Mapping from object names to texture configurations. 306typedef std::map<glw::GLuint, const Texture*> TextureMap; 307 308//! Mapping from object names to renderbuffer configurations. 309typedef std::map<glw::GLuint, const Renderbuffer*> RboMap; 310 311//! A framebuffer configuration. 312struct 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 326class FboBuilder : public config::Framebuffer 327{ 328public: 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 349private: 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 360struct 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 376private: 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 391void logFramebufferConfig (const config::Framebuffer& cfg, tcu::TestLog& log); 392 393class Checker 394{ 395public: 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 410protected: 411 const glu::RenderContext& m_renderCtx; 412 413private: 414 ValidStatusCodes m_statusCodes; //< Allowed return values for glCheckFramebufferStatus. 415}; 416 417class CheckerFactory 418{ 419public: 420 virtual Checker* createChecker (const glu::RenderContext&) = 0; 421}; 422 423typedef std::set<glw::GLenum> AttachmentPoints; 424typedef std::set<ImageFormat> Formats; 425 426class FboVerifier 427{ 428public: 429 FboVerifier (const FormatDB& formats, 430 CheckerFactory& factory, 431 const glu::RenderContext& renderCtx); 432 433 ValidStatusCodes validStatusCodes (const config::Framebuffer& cfg) const; 434 435private: 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