You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
446 lines
12 KiB
446 lines
12 KiB
#ifndef _GLSFBOUTIL_HPP
|
|
#define _GLSFBOUTIL_HPP
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* drawElements Quality Program OpenGL (ES) 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 Utilities for framebuffer objects.
|
|
*//*--------------------------------------------------------------------*/
|
|
|
|
#include "gluRenderContext.hpp"
|
|
#include "gluContextInfo.hpp"
|
|
#include "glwDefs.hpp"
|
|
#include "glwEnums.hpp"
|
|
#include "glwFunctions.hpp"
|
|
#include "gluTextureUtil.hpp"
|
|
#include "tcuTestLog.hpp"
|
|
#include "tcuDefs.hpp"
|
|
|
|
#include <map>
|
|
#include <set>
|
|
#include <vector>
|
|
#include <algorithm>
|
|
#include <iterator>
|
|
|
|
namespace deqp
|
|
{
|
|
namespace gls
|
|
{
|
|
|
|
//! A pair of iterators to present a range.
|
|
//! \note This must be POD to allow static initialization.
|
|
//! \todo [2013-12-03 lauri] Move this to decpp?
|
|
template <typename T>
|
|
struct Range
|
|
{
|
|
typedef const T* const_iterator;
|
|
|
|
const T* m_begin;
|
|
const T* m_end;
|
|
|
|
const T* begin (void) const { return m_begin; }
|
|
const T* end (void) const { return m_end; }
|
|
};
|
|
|
|
#define GLS_ARRAY_RANGE(ARR) { DE_ARRAY_BEGIN(ARR), DE_ARRAY_END(ARR) }
|
|
|
|
#define GLS_NULL_RANGE { DE_NULL, DE_NULL }
|
|
|
|
|
|
//! A pair type that, unlike stl::pair, is POD so it can be statically initialized.
|
|
template <typename T1, typename T2>
|
|
struct Pair
|
|
{
|
|
typedef T1 first_type;
|
|
typedef T2 second_type;
|
|
T1 first;
|
|
T2 second;
|
|
};
|
|
|
|
namespace FboUtil
|
|
{
|
|
|
|
//! Configurations for framebuffer objects and their attachments.
|
|
|
|
class FboVerifier;
|
|
class FboBuilder;
|
|
|
|
typedef deUint32 FormatKey;
|
|
|
|
#define GLS_UNSIZED_FORMATKEY(FORMAT, TYPE) \
|
|
(deUint32(TYPE) << 16 | deUint32(FORMAT))
|
|
|
|
typedef Range<FormatKey> FormatKeys;
|
|
|
|
struct ImageFormat
|
|
{
|
|
glw::GLenum format;
|
|
|
|
//! Type if format is unsized, GL_NONE if sized.
|
|
glw::GLenum unsizedType;
|
|
|
|
bool operator< (const ImageFormat& other) const
|
|
{
|
|
return (format < other.format ||
|
|
(format == other.format && unsizedType < other.unsizedType));
|
|
}
|
|
|
|
static ImageFormat none (void)
|
|
{
|
|
ImageFormat fmt = { GL_NONE, GL_NONE };
|
|
return fmt;
|
|
}
|
|
};
|
|
|
|
std::ostream& operator<< (std::ostream& stream, const ImageFormat& format);
|
|
|
|
static inline ImageFormat formatKeyInfo(FormatKey key)
|
|
{
|
|
ImageFormat fmt = { key & 0xffff, key >> 16 };
|
|
return fmt;
|
|
}
|
|
|
|
enum FormatFlags
|
|
{
|
|
ANY_FORMAT = 0,
|
|
COLOR_RENDERABLE = 1 << 0,
|
|
DEPTH_RENDERABLE = 1 << 1,
|
|
STENCIL_RENDERABLE = 1 << 2,
|
|
RENDERBUFFER_VALID = 1 << 3,
|
|
TEXTURE_VALID = 1 << 4,
|
|
REQUIRED_RENDERABLE = 1 << 5, //< Without this, renderability is allowed, not required.
|
|
};
|
|
|
|
static inline FormatFlags operator|(FormatFlags f1, FormatFlags f2)
|
|
{
|
|
return FormatFlags(deUint32(f1) | deUint32(f2));
|
|
}
|
|
|
|
FormatFlags formatFlag(glw::GLenum context);
|
|
|
|
typedef std::set<ImageFormat> Formats;
|
|
|
|
class FormatDB
|
|
{
|
|
public:
|
|
void addCoreFormat (ImageFormat format, FormatFlags flags);
|
|
void addExtensionFormat (ImageFormat format, FormatFlags flags, const std::set<std::string>& requiredExtensions);
|
|
|
|
Formats getFormats (FormatFlags requirements) const;
|
|
bool isKnownFormat (ImageFormat format) const;
|
|
FormatFlags getFormatInfo (ImageFormat format) const;
|
|
std::set<std::set<std::string> > getFormatFeatureExtensions (ImageFormat format, FormatFlags requirements) const;
|
|
|
|
private:
|
|
struct ExtensionInfo
|
|
{
|
|
FormatFlags flags;
|
|
std::set<std::string> requiredExtensions;
|
|
|
|
bool operator< (const ExtensionInfo& other) const;
|
|
};
|
|
|
|
typedef std::map<ImageFormat, FormatFlags> FormatMap;
|
|
typedef std::map<ImageFormat, std::set<ExtensionInfo> > FormatExtensionMap;
|
|
|
|
FormatMap m_formatFlags;
|
|
FormatExtensionMap m_formatExtensions;
|
|
};
|
|
|
|
typedef Pair<FormatFlags, FormatKeys> FormatEntry;
|
|
typedef Range<FormatEntry> FormatEntries;
|
|
|
|
// \todo [2013-12-20 lauri] It turns out that format properties in extensions
|
|
// are actually far too fine-grained for this bundling to be reasonable,
|
|
// especially given the syntactic cumbersomeness of static arrays. It's better
|
|
// to list each entry separately.
|
|
|
|
struct FormatExtEntry
|
|
{
|
|
const char* extensions;
|
|
deUint32 flags;
|
|
Range<FormatKey> formats;
|
|
};
|
|
|
|
typedef Range<FormatExtEntry> FormatExtEntries;
|
|
|
|
// Check support for GL_* and DEQP_* extensions
|
|
bool checkExtensionSupport (const glu::RenderContext& ctx, const std::string& extension);
|
|
|
|
// Accepts GL_* and DEQP_* extension strings and converts DEQP_* strings to a human readable string
|
|
std::string getExtensionDescription (const std::string& extensionName);
|
|
|
|
void addFormats (FormatDB& db, FormatEntries stdFmts);
|
|
void addExtFormats (FormatDB& db, FormatExtEntries extFmts, const glu::RenderContext* ctx);
|
|
glu::TransferFormat transferImageFormat (const ImageFormat& imgFormat);
|
|
|
|
namespace config
|
|
{
|
|
|
|
struct Config
|
|
{
|
|
virtual ~Config (void) {};
|
|
};
|
|
|
|
struct Image : public Config
|
|
{
|
|
ImageFormat internalFormat;
|
|
glw::GLsizei width;
|
|
glw::GLsizei height;
|
|
|
|
protected:
|
|
Image (void)
|
|
: internalFormat (ImageFormat::none())
|
|
, width (0)
|
|
, height (0) {}
|
|
};
|
|
|
|
struct Renderbuffer : public Image
|
|
{
|
|
Renderbuffer (void) : numSamples(0) {}
|
|
|
|
glw::GLsizei numSamples;
|
|
};
|
|
|
|
struct Texture : public Image
|
|
{
|
|
Texture (void) : numLevels(1) {}
|
|
|
|
glw::GLint numLevels;
|
|
};
|
|
|
|
struct TextureFlat : public Texture
|
|
{
|
|
};
|
|
|
|
struct Texture2D : public TextureFlat
|
|
{
|
|
};
|
|
|
|
struct TextureCubeMap : public TextureFlat
|
|
{
|
|
};
|
|
|
|
struct TextureLayered : public Texture
|
|
{
|
|
TextureLayered (void) : numLayers(1) {}
|
|
glw::GLsizei numLayers;
|
|
};
|
|
|
|
struct Texture3D : public TextureLayered
|
|
{
|
|
};
|
|
|
|
struct Texture2DArray : public TextureLayered
|
|
{
|
|
};
|
|
|
|
struct Attachment : public Config
|
|
{
|
|
Attachment (void) : target(GL_FRAMEBUFFER), imageName(0) {}
|
|
|
|
glw::GLenum target;
|
|
glw::GLuint imageName;
|
|
|
|
//! Returns `true` iff this attachment is "framebuffer attachment
|
|
//! complete" when bound to attachment point `attPoint`, and the current
|
|
//! image with name `imageName` is `image`, using `vfr` to check format
|
|
//! renderability.
|
|
bool isComplete (glw::GLenum attPoint, const Image* image,
|
|
const FboVerifier& vfr) const;
|
|
};
|
|
|
|
struct RenderbufferAttachment : public Attachment
|
|
{
|
|
RenderbufferAttachment (void)
|
|
: renderbufferTarget(GL_RENDERBUFFER) {}
|
|
|
|
glw::GLenum renderbufferTarget;
|
|
};
|
|
|
|
struct TextureAttachment : public Attachment
|
|
{
|
|
TextureAttachment (void) : level(0) {}
|
|
|
|
glw::GLint level;
|
|
};
|
|
|
|
struct TextureFlatAttachment : public TextureAttachment
|
|
{
|
|
TextureFlatAttachment (void) : texTarget(GL_NONE) {}
|
|
|
|
glw::GLenum texTarget;
|
|
};
|
|
|
|
struct TextureLayerAttachment : public TextureAttachment
|
|
{
|
|
TextureLayerAttachment (void) : layer(0) {}
|
|
|
|
glw::GLsizei layer;
|
|
};
|
|
|
|
glw::GLenum attachmentType (const Attachment& att);
|
|
glw::GLsizei imageNumSamples (const Image& img);
|
|
|
|
//! Mapping from attachment points to attachment configurations.
|
|
typedef std::map<glw::GLenum, const Attachment*> AttachmentMap;
|
|
|
|
//! Mapping from object names to texture configurations.
|
|
typedef std::map<glw::GLuint, const Texture*> TextureMap;
|
|
|
|
//! Mapping from object names to renderbuffer configurations.
|
|
typedef std::map<glw::GLuint, const Renderbuffer*> RboMap;
|
|
|
|
//! A framebuffer configuration.
|
|
struct Framebuffer
|
|
{
|
|
AttachmentMap attachments;
|
|
TextureMap textures;
|
|
RboMap rbos;
|
|
|
|
void attach (glw::GLenum attPoint, const Attachment* att);
|
|
void setTexture (glw::GLuint texName, const Texture& texCfg);
|
|
void setRbo (glw::GLuint rbName, const Renderbuffer& rbCfg);
|
|
const Image* getImage (glw::GLenum type, glw::GLuint imgName) const;
|
|
};
|
|
|
|
} // config
|
|
|
|
class FboBuilder : public config::Framebuffer
|
|
{
|
|
public:
|
|
void glAttach (glw::GLenum attPoint,
|
|
const config::Attachment* att);
|
|
glw::GLuint glCreateTexture (const config::Texture& texCfg);
|
|
glw::GLuint glCreateRbo (const config::Renderbuffer& rbCfg);
|
|
FboBuilder (glw::GLuint fbo, glw::GLenum target,
|
|
const glw::Functions& gl);
|
|
~FboBuilder (void);
|
|
glw::GLenum getError (void) { return m_error; }
|
|
|
|
//! Allocate a new configuration of type `Config` (which must be a
|
|
//! subclass of `config::Config`), and return a referenc to it. The newly
|
|
//! allocated object will be freed when this builder object is destroyed.
|
|
template<typename Config>
|
|
Config& makeConfig (void)
|
|
{
|
|
Config* cfg = new Config();
|
|
m_configs.insert(cfg);
|
|
return *cfg;
|
|
}
|
|
|
|
private:
|
|
typedef std::set<config::Config*> Configs;
|
|
|
|
void checkError (void);
|
|
|
|
glw::GLenum m_error; //< The first GL error encountered.
|
|
glw::GLenum m_target;
|
|
const glw::Functions& m_gl;
|
|
Configs m_configs;
|
|
};
|
|
|
|
struct ValidStatusCodes
|
|
{
|
|
ValidStatusCodes (void);
|
|
|
|
bool isFBOStatusValid (glw::GLenum fboStatus) const;
|
|
bool isFBOStatusRequired (glw::GLenum fboStatus) const;
|
|
bool isErrorCodeValid (glw::GLenum errorCode) const;
|
|
bool isErrorCodeRequired (glw::GLenum errorCode) const;
|
|
|
|
void addErrorCode (glw::GLenum error, const char* description);
|
|
void addFBOErrorStatus (glw::GLenum status, const char* description);
|
|
void setAllowComplete (bool);
|
|
|
|
void logLegalResults (tcu::TestLog& log) const;
|
|
void logRules (tcu::TestLog& log) const;
|
|
|
|
private:
|
|
struct RuleViolation
|
|
{
|
|
glw::GLenum errorCode;
|
|
std::set<std::string> rules;
|
|
};
|
|
|
|
void logRule (tcu::TestLog& log, const std::string& ruleName, const std::set<std::string>& rules) const;
|
|
void addViolation (std::vector<RuleViolation>& dst, glw::GLenum code, const char* description) const;
|
|
|
|
std::vector<RuleViolation> m_errorCodes; //!< Allowed GL errors, GL_NO_ERROR is not allowed
|
|
std::vector<RuleViolation> m_errorStatuses; //!< Allowed FBO error statuses, GL_FRAMEBUFFER_COMPLETE is not allowed
|
|
bool m_allowComplete; //!< true if (GL_NO_ERROR && GL_FRAMEBUFFER_COMPLETE) is allowed
|
|
};
|
|
|
|
void logFramebufferConfig (const config::Framebuffer& cfg, tcu::TestLog& log);
|
|
|
|
class Checker
|
|
{
|
|
public:
|
|
Checker (const glu::RenderContext&);
|
|
virtual ~Checker (void) {}
|
|
|
|
void addGLError (glw::GLenum error, const char* description);
|
|
void addPotentialGLError (glw::GLenum error, const char* description);
|
|
void addFBOStatus (glw::GLenum status, const char* description);
|
|
void addPotentialFBOStatus (glw::GLenum status, const char* description);
|
|
|
|
ValidStatusCodes getStatusCodes (void) { return m_statusCodes; }
|
|
|
|
virtual void check (glw::GLenum attPoint,
|
|
const config::Attachment& att,
|
|
const config::Image* image) = 0;
|
|
|
|
protected:
|
|
const glu::RenderContext& m_renderCtx;
|
|
|
|
private:
|
|
ValidStatusCodes m_statusCodes; //< Allowed return values for glCheckFramebufferStatus.
|
|
};
|
|
|
|
class CheckerFactory
|
|
{
|
|
public:
|
|
virtual Checker* createChecker (const glu::RenderContext&) = 0;
|
|
};
|
|
|
|
typedef std::set<glw::GLenum> AttachmentPoints;
|
|
typedef std::set<ImageFormat> Formats;
|
|
|
|
class FboVerifier
|
|
{
|
|
public:
|
|
FboVerifier (const FormatDB& formats,
|
|
CheckerFactory& factory,
|
|
const glu::RenderContext& renderCtx);
|
|
|
|
ValidStatusCodes validStatusCodes (const config::Framebuffer& cfg) const;
|
|
|
|
private:
|
|
const FormatDB& m_formats;
|
|
CheckerFactory& m_factory;
|
|
const glu::RenderContext& m_renderCtx;
|
|
};
|
|
|
|
} // FboUtil
|
|
} // gls
|
|
} // deqp
|
|
|
|
#endif // _GLSFBOUTIL_HPP
|