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