Merge "Check only what's needed and use threshold"
[platform/upstream/VK-GL-CTS.git] / modules / glshared / glsFboUtil.hpp
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