xref: /aosp_15_r20/external/deqp/modules/glshared/glsFboUtil.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker  * drawElements Quality Program OpenGL (ES) Module
3*35238bceSAndroid Build Coastguard Worker  * -----------------------------------------------
4*35238bceSAndroid Build Coastguard Worker  *
5*35238bceSAndroid Build Coastguard Worker  * Copyright 2014 The Android Open Source Project
6*35238bceSAndroid Build Coastguard Worker  *
7*35238bceSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
8*35238bceSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
9*35238bceSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
10*35238bceSAndroid Build Coastguard Worker  *
11*35238bceSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
12*35238bceSAndroid Build Coastguard Worker  *
13*35238bceSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
14*35238bceSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
15*35238bceSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*35238bceSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
17*35238bceSAndroid Build Coastguard Worker  * limitations under the License.
18*35238bceSAndroid Build Coastguard Worker  *
19*35238bceSAndroid Build Coastguard Worker  *//*!
20*35238bceSAndroid Build Coastguard Worker  * \file
21*35238bceSAndroid Build Coastguard Worker  * \brief Utilities for framebuffer objects.
22*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker 
24*35238bceSAndroid Build Coastguard Worker #include "glsFboUtil.hpp"
25*35238bceSAndroid Build Coastguard Worker 
26*35238bceSAndroid Build Coastguard Worker #include "glwEnums.hpp"
27*35238bceSAndroid Build Coastguard Worker #include "deUniquePtr.hpp"
28*35238bceSAndroid Build Coastguard Worker #include "gluTextureUtil.hpp"
29*35238bceSAndroid Build Coastguard Worker #include "gluStrUtil.hpp"
30*35238bceSAndroid Build Coastguard Worker #include "deStringUtil.hpp"
31*35238bceSAndroid Build Coastguard Worker #include "deSTLUtil.hpp"
32*35238bceSAndroid Build Coastguard Worker #include <sstream>
33*35238bceSAndroid Build Coastguard Worker 
34*35238bceSAndroid Build Coastguard Worker using namespace glw;
35*35238bceSAndroid Build Coastguard Worker using de::toString;
36*35238bceSAndroid Build Coastguard Worker using de::UniquePtr;
37*35238bceSAndroid Build Coastguard Worker using glu::ContextInfo;
38*35238bceSAndroid Build Coastguard Worker using glu::ContextType;
39*35238bceSAndroid Build Coastguard Worker using glu::getFramebufferAttachmentName;
40*35238bceSAndroid Build Coastguard Worker using glu::getFramebufferAttachmentTypeName;
41*35238bceSAndroid Build Coastguard Worker using glu::getFramebufferTargetName;
42*35238bceSAndroid Build Coastguard Worker using glu::getTextureFormatName;
43*35238bceSAndroid Build Coastguard Worker using glu::getTextureTargetName;
44*35238bceSAndroid Build Coastguard Worker using glu::getTransferFormat;
45*35238bceSAndroid Build Coastguard Worker using glu::getTypeName;
46*35238bceSAndroid Build Coastguard Worker using glu::mapGLInternalFormat;
47*35238bceSAndroid Build Coastguard Worker using glu::mapGLTransferFormat;
48*35238bceSAndroid Build Coastguard Worker using glu::RenderContext;
49*35238bceSAndroid Build Coastguard Worker using glu::TransferFormat;
50*35238bceSAndroid Build Coastguard Worker using std::istream_iterator;
51*35238bceSAndroid Build Coastguard Worker using std::istringstream;
52*35238bceSAndroid Build Coastguard Worker using std::set;
53*35238bceSAndroid Build Coastguard Worker using std::string;
54*35238bceSAndroid Build Coastguard Worker using std::vector;
55*35238bceSAndroid Build Coastguard Worker using tcu::NotSupportedError;
56*35238bceSAndroid Build Coastguard Worker using tcu::TestLog;
57*35238bceSAndroid Build Coastguard Worker using tcu::TextureFormat;
58*35238bceSAndroid Build Coastguard Worker 
59*35238bceSAndroid Build Coastguard Worker namespace deqp
60*35238bceSAndroid Build Coastguard Worker {
61*35238bceSAndroid Build Coastguard Worker namespace gls
62*35238bceSAndroid Build Coastguard Worker {
63*35238bceSAndroid Build Coastguard Worker 
64*35238bceSAndroid Build Coastguard Worker namespace FboUtil
65*35238bceSAndroid Build Coastguard Worker {
66*35238bceSAndroid Build Coastguard Worker 
67*35238bceSAndroid Build Coastguard Worker #if defined(DE_DEBUG)
isFramebufferStatus(glw::GLenum fboStatus)68*35238bceSAndroid Build Coastguard Worker static bool isFramebufferStatus(glw::GLenum fboStatus)
69*35238bceSAndroid Build Coastguard Worker {
70*35238bceSAndroid Build Coastguard Worker     return glu::getFramebufferStatusName(fboStatus) != DE_NULL;
71*35238bceSAndroid Build Coastguard Worker }
72*35238bceSAndroid Build Coastguard Worker 
isErrorCode(glw::GLenum errorCode)73*35238bceSAndroid Build Coastguard Worker static bool isErrorCode(glw::GLenum errorCode)
74*35238bceSAndroid Build Coastguard Worker {
75*35238bceSAndroid Build Coastguard Worker     return glu::getErrorName(errorCode) != DE_NULL;
76*35238bceSAndroid Build Coastguard Worker }
77*35238bceSAndroid Build Coastguard Worker #endif
78*35238bceSAndroid Build Coastguard Worker 
operator <<(std::ostream & stream,const ImageFormat & format)79*35238bceSAndroid Build Coastguard Worker std::ostream &operator<<(std::ostream &stream, const ImageFormat &format)
80*35238bceSAndroid Build Coastguard Worker {
81*35238bceSAndroid Build Coastguard Worker     if (format.unsizedType == GL_NONE)
82*35238bceSAndroid Build Coastguard Worker     {
83*35238bceSAndroid Build Coastguard Worker         // sized format
84*35238bceSAndroid Build Coastguard Worker         return stream << glu::getTextureFormatStr(format.format);
85*35238bceSAndroid Build Coastguard Worker     }
86*35238bceSAndroid Build Coastguard Worker     else
87*35238bceSAndroid Build Coastguard Worker     {
88*35238bceSAndroid Build Coastguard Worker         // unsized format
89*35238bceSAndroid Build Coastguard Worker         return stream << "(format = " << glu::getTextureFormatStr(format.format)
90*35238bceSAndroid Build Coastguard Worker                       << ", type = " << glu::getTypeStr(format.unsizedType) << ")";
91*35238bceSAndroid Build Coastguard Worker     }
92*35238bceSAndroid Build Coastguard Worker }
93*35238bceSAndroid Build Coastguard Worker 
addCoreFormat(ImageFormat format,FormatFlags newFlags)94*35238bceSAndroid Build Coastguard Worker void FormatDB::addCoreFormat(ImageFormat format, FormatFlags newFlags)
95*35238bceSAndroid Build Coastguard Worker {
96*35238bceSAndroid Build Coastguard Worker     FormatFlags &flags = m_formatFlags[format];
97*35238bceSAndroid Build Coastguard Worker     flags              = FormatFlags(flags | newFlags);
98*35238bceSAndroid Build Coastguard Worker }
99*35238bceSAndroid Build Coastguard Worker 
addExtensionFormat(ImageFormat format,FormatFlags newFlags,const std::set<std::string> & requiredExtensions)100*35238bceSAndroid Build Coastguard Worker void FormatDB::addExtensionFormat(ImageFormat format, FormatFlags newFlags,
101*35238bceSAndroid Build Coastguard Worker                                   const std::set<std::string> &requiredExtensions)
102*35238bceSAndroid Build Coastguard Worker {
103*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(!requiredExtensions.empty());
104*35238bceSAndroid Build Coastguard Worker 
105*35238bceSAndroid Build Coastguard Worker     {
106*35238bceSAndroid Build Coastguard Worker         FormatFlags &flags = m_formatFlags[format];
107*35238bceSAndroid Build Coastguard Worker         flags              = FormatFlags(flags | newFlags);
108*35238bceSAndroid Build Coastguard Worker     }
109*35238bceSAndroid Build Coastguard Worker 
110*35238bceSAndroid Build Coastguard Worker     {
111*35238bceSAndroid Build Coastguard Worker         std::set<ExtensionInfo> &extensionInfo = m_formatExtensions[format];
112*35238bceSAndroid Build Coastguard Worker         ExtensionInfo extensionRecord;
113*35238bceSAndroid Build Coastguard Worker 
114*35238bceSAndroid Build Coastguard Worker         extensionRecord.flags              = newFlags;
115*35238bceSAndroid Build Coastguard Worker         extensionRecord.requiredExtensions = requiredExtensions;
116*35238bceSAndroid Build Coastguard Worker 
117*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(!de::contains(extensionInfo, extensionRecord)); // extensions specified only once
118*35238bceSAndroid Build Coastguard Worker         extensionInfo.insert(extensionRecord);
119*35238bceSAndroid Build Coastguard Worker     }
120*35238bceSAndroid Build Coastguard Worker }
121*35238bceSAndroid Build Coastguard Worker 
122*35238bceSAndroid Build Coastguard Worker // Not too fast at the moment, might consider indexing?
getFormats(FormatFlags requirements) const123*35238bceSAndroid Build Coastguard Worker Formats FormatDB::getFormats(FormatFlags requirements) const
124*35238bceSAndroid Build Coastguard Worker {
125*35238bceSAndroid Build Coastguard Worker     Formats ret;
126*35238bceSAndroid Build Coastguard Worker     for (FormatMap::const_iterator it = m_formatFlags.begin(); it != m_formatFlags.end(); it++)
127*35238bceSAndroid Build Coastguard Worker     {
128*35238bceSAndroid Build Coastguard Worker         if ((it->second & requirements) == requirements)
129*35238bceSAndroid Build Coastguard Worker             ret.insert(it->first);
130*35238bceSAndroid Build Coastguard Worker     }
131*35238bceSAndroid Build Coastguard Worker     return ret;
132*35238bceSAndroid Build Coastguard Worker }
133*35238bceSAndroid Build Coastguard Worker 
isKnownFormat(ImageFormat format) const134*35238bceSAndroid Build Coastguard Worker bool FormatDB::isKnownFormat(ImageFormat format) const
135*35238bceSAndroid Build Coastguard Worker {
136*35238bceSAndroid Build Coastguard Worker     return de::contains(m_formatFlags, format);
137*35238bceSAndroid Build Coastguard Worker }
138*35238bceSAndroid Build Coastguard Worker 
getFormatInfo(ImageFormat format) const139*35238bceSAndroid Build Coastguard Worker FormatFlags FormatDB::getFormatInfo(ImageFormat format) const
140*35238bceSAndroid Build Coastguard Worker {
141*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(de::contains(m_formatFlags, format));
142*35238bceSAndroid Build Coastguard Worker     return de::lookup(m_formatFlags, format);
143*35238bceSAndroid Build Coastguard Worker }
144*35238bceSAndroid Build Coastguard Worker 
getFormatFeatureExtensions(ImageFormat format,FormatFlags requirements) const145*35238bceSAndroid Build Coastguard Worker std::set<std::set<std::string>> FormatDB::getFormatFeatureExtensions(ImageFormat format, FormatFlags requirements) const
146*35238bceSAndroid Build Coastguard Worker {
147*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(de::contains(m_formatExtensions, format));
148*35238bceSAndroid Build Coastguard Worker 
149*35238bceSAndroid Build Coastguard Worker     const std::set<ExtensionInfo> &extensionInfo = de::lookup(m_formatExtensions, format);
150*35238bceSAndroid Build Coastguard Worker     std::set<std::set<std::string>> ret;
151*35238bceSAndroid Build Coastguard Worker 
152*35238bceSAndroid Build Coastguard Worker     for (std::set<ExtensionInfo>::const_iterator it = extensionInfo.begin(); it != extensionInfo.end(); ++it)
153*35238bceSAndroid Build Coastguard Worker     {
154*35238bceSAndroid Build Coastguard Worker         if ((it->flags & requirements) == requirements)
155*35238bceSAndroid Build Coastguard Worker             ret.insert(it->requiredExtensions);
156*35238bceSAndroid Build Coastguard Worker     }
157*35238bceSAndroid Build Coastguard Worker 
158*35238bceSAndroid Build Coastguard Worker     return ret;
159*35238bceSAndroid Build Coastguard Worker }
160*35238bceSAndroid Build Coastguard Worker 
operator <(const ExtensionInfo & other) const161*35238bceSAndroid Build Coastguard Worker bool FormatDB::ExtensionInfo::operator<(const ExtensionInfo &other) const
162*35238bceSAndroid Build Coastguard Worker {
163*35238bceSAndroid Build Coastguard Worker     return (requiredExtensions < other.requiredExtensions) ||
164*35238bceSAndroid Build Coastguard Worker            ((requiredExtensions == other.requiredExtensions) && (flags < other.flags));
165*35238bceSAndroid Build Coastguard Worker }
166*35238bceSAndroid Build Coastguard Worker 
detectGLESCompatibleContext(const RenderContext & ctx,int requiredMajor,int requiredMinor)167*35238bceSAndroid Build Coastguard Worker static bool detectGLESCompatibleContext(const RenderContext &ctx, int requiredMajor, int requiredMinor)
168*35238bceSAndroid Build Coastguard Worker {
169*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl = ctx.getFunctions();
170*35238bceSAndroid Build Coastguard Worker     glw::GLint majorVersion  = 0;
171*35238bceSAndroid Build Coastguard Worker     glw::GLint minorVersion  = 0;
172*35238bceSAndroid Build Coastguard Worker 
173*35238bceSAndroid Build Coastguard Worker     // Detect compatible GLES context by querying GL_MAJOR_VERSION.
174*35238bceSAndroid Build Coastguard Worker     // This query does not exist on GLES2 so a failing query implies
175*35238bceSAndroid Build Coastguard Worker     // GLES2 context.
176*35238bceSAndroid Build Coastguard Worker 
177*35238bceSAndroid Build Coastguard Worker     gl.getIntegerv(GL_MAJOR_VERSION, &majorVersion);
178*35238bceSAndroid Build Coastguard Worker     if (gl.getError() != GL_NO_ERROR)
179*35238bceSAndroid Build Coastguard Worker         majorVersion = 2;
180*35238bceSAndroid Build Coastguard Worker 
181*35238bceSAndroid Build Coastguard Worker     gl.getIntegerv(GL_MINOR_VERSION, &minorVersion);
182*35238bceSAndroid Build Coastguard Worker     if (gl.getError() != GL_NO_ERROR)
183*35238bceSAndroid Build Coastguard Worker         minorVersion = 0;
184*35238bceSAndroid Build Coastguard Worker 
185*35238bceSAndroid Build Coastguard Worker     return (majorVersion > requiredMajor) || (majorVersion == requiredMajor && minorVersion >= requiredMinor);
186*35238bceSAndroid Build Coastguard Worker }
187*35238bceSAndroid Build Coastguard Worker 
checkExtensionSupport(const ContextInfo & ctxInfo,const RenderContext & ctx,const std::string & extension)188*35238bceSAndroid Build Coastguard Worker static bool checkExtensionSupport(const ContextInfo &ctxInfo, const RenderContext &ctx, const std::string &extension)
189*35238bceSAndroid Build Coastguard Worker {
190*35238bceSAndroid Build Coastguard Worker     if (de::beginsWith(extension, "GL_"))
191*35238bceSAndroid Build Coastguard Worker         return ctxInfo.isExtensionSupported(extension.c_str());
192*35238bceSAndroid Build Coastguard Worker     else if (extension == "DEQP_gles3_core_compatible")
193*35238bceSAndroid Build Coastguard Worker         return detectGLESCompatibleContext(ctx, 3, 0);
194*35238bceSAndroid Build Coastguard Worker     else if (extension == "DEQP_gles31_core_compatible")
195*35238bceSAndroid Build Coastguard Worker         return detectGLESCompatibleContext(ctx, 3, 1);
196*35238bceSAndroid Build Coastguard Worker     else
197*35238bceSAndroid Build Coastguard Worker     {
198*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
199*35238bceSAndroid Build Coastguard Worker         return false;
200*35238bceSAndroid Build Coastguard Worker     }
201*35238bceSAndroid Build Coastguard Worker }
202*35238bceSAndroid Build Coastguard Worker 
checkExtensionSupport(const RenderContext & ctx,const std::string & extension)203*35238bceSAndroid Build Coastguard Worker bool checkExtensionSupport(const RenderContext &ctx, const std::string &extension)
204*35238bceSAndroid Build Coastguard Worker {
205*35238bceSAndroid Build Coastguard Worker     const de::UniquePtr<ContextInfo> info(ContextInfo::create(ctx));
206*35238bceSAndroid Build Coastguard Worker     return checkExtensionSupport(*info, ctx, extension);
207*35238bceSAndroid Build Coastguard Worker }
208*35238bceSAndroid Build Coastguard Worker 
getExtensionDescription(const std::string & extension)209*35238bceSAndroid Build Coastguard Worker std::string getExtensionDescription(const std::string &extension)
210*35238bceSAndroid Build Coastguard Worker {
211*35238bceSAndroid Build Coastguard Worker     if (de::beginsWith(extension, "GL_"))
212*35238bceSAndroid Build Coastguard Worker         return extension;
213*35238bceSAndroid Build Coastguard Worker     else if (extension == "DEQP_gles3_core_compatible")
214*35238bceSAndroid Build Coastguard Worker         return "GLES3 compatible context";
215*35238bceSAndroid Build Coastguard Worker     else if (extension == "DEQP_gles31_core_compatible")
216*35238bceSAndroid Build Coastguard Worker         return "GLES3.1 compatible context";
217*35238bceSAndroid Build Coastguard Worker     else
218*35238bceSAndroid Build Coastguard Worker     {
219*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
220*35238bceSAndroid Build Coastguard Worker         return "";
221*35238bceSAndroid Build Coastguard Worker     }
222*35238bceSAndroid Build Coastguard Worker }
223*35238bceSAndroid Build Coastguard Worker 
addFormats(FormatDB & db,FormatEntries stdFmts)224*35238bceSAndroid Build Coastguard Worker void addFormats(FormatDB &db, FormatEntries stdFmts)
225*35238bceSAndroid Build Coastguard Worker {
226*35238bceSAndroid Build Coastguard Worker     for (const FormatEntry *it = stdFmts.begin(); it != stdFmts.end(); it++)
227*35238bceSAndroid Build Coastguard Worker     {
228*35238bceSAndroid Build Coastguard Worker         for (const FormatKey *it2 = it->second.begin(); it2 != it->second.end(); it2++)
229*35238bceSAndroid Build Coastguard Worker             db.addCoreFormat(formatKeyInfo(*it2), it->first);
230*35238bceSAndroid Build Coastguard Worker     }
231*35238bceSAndroid Build Coastguard Worker }
232*35238bceSAndroid Build Coastguard Worker 
addExtFormats(FormatDB & db,FormatExtEntries extFmts,const RenderContext * ctx)233*35238bceSAndroid Build Coastguard Worker void addExtFormats(FormatDB &db, FormatExtEntries extFmts, const RenderContext *ctx)
234*35238bceSAndroid Build Coastguard Worker {
235*35238bceSAndroid Build Coastguard Worker     const UniquePtr<ContextInfo> ctxInfo(ctx != DE_NULL ? ContextInfo::create(*ctx) : DE_NULL);
236*35238bceSAndroid Build Coastguard Worker     for (const FormatExtEntry *entryIt = extFmts.begin(); entryIt != extFmts.end(); entryIt++)
237*35238bceSAndroid Build Coastguard Worker     {
238*35238bceSAndroid Build Coastguard Worker         bool supported = true;
239*35238bceSAndroid Build Coastguard Worker         std::set<std::string> requiredExtensions;
240*35238bceSAndroid Build Coastguard Worker 
241*35238bceSAndroid Build Coastguard Worker         // parse required extensions
242*35238bceSAndroid Build Coastguard Worker         {
243*35238bceSAndroid Build Coastguard Worker             istringstream tokenStream(string(entryIt->extensions));
244*35238bceSAndroid Build Coastguard Worker             istream_iterator<string> tokens((tokenStream)), end;
245*35238bceSAndroid Build Coastguard Worker 
246*35238bceSAndroid Build Coastguard Worker             while (tokens != end)
247*35238bceSAndroid Build Coastguard Worker             {
248*35238bceSAndroid Build Coastguard Worker                 requiredExtensions.insert(*tokens);
249*35238bceSAndroid Build Coastguard Worker                 ++tokens;
250*35238bceSAndroid Build Coastguard Worker             }
251*35238bceSAndroid Build Coastguard Worker         }
252*35238bceSAndroid Build Coastguard Worker 
253*35238bceSAndroid Build Coastguard Worker         // check support
254*35238bceSAndroid Build Coastguard Worker         if (ctxInfo)
255*35238bceSAndroid Build Coastguard Worker         {
256*35238bceSAndroid Build Coastguard Worker             for (std::set<std::string>::const_iterator extIt = requiredExtensions.begin();
257*35238bceSAndroid Build Coastguard Worker                  extIt != requiredExtensions.end(); ++extIt)
258*35238bceSAndroid Build Coastguard Worker             {
259*35238bceSAndroid Build Coastguard Worker                 if (!checkExtensionSupport(*ctxInfo, *ctx, *extIt))
260*35238bceSAndroid Build Coastguard Worker                 {
261*35238bceSAndroid Build Coastguard Worker                     supported = false;
262*35238bceSAndroid Build Coastguard Worker                     break;
263*35238bceSAndroid Build Coastguard Worker                 }
264*35238bceSAndroid Build Coastguard Worker             }
265*35238bceSAndroid Build Coastguard Worker         }
266*35238bceSAndroid Build Coastguard Worker 
267*35238bceSAndroid Build Coastguard Worker         if (supported)
268*35238bceSAndroid Build Coastguard Worker             for (const FormatKey *i2 = entryIt->formats.begin(); i2 != entryIt->formats.end(); i2++)
269*35238bceSAndroid Build Coastguard Worker                 db.addExtensionFormat(formatKeyInfo(*i2), FormatFlags(entryIt->flags), requiredExtensions);
270*35238bceSAndroid Build Coastguard Worker     }
271*35238bceSAndroid Build Coastguard Worker }
272*35238bceSAndroid Build Coastguard Worker 
formatFlag(GLenum context)273*35238bceSAndroid Build Coastguard Worker FormatFlags formatFlag(GLenum context)
274*35238bceSAndroid Build Coastguard Worker {
275*35238bceSAndroid Build Coastguard Worker     switch (context)
276*35238bceSAndroid Build Coastguard Worker     {
277*35238bceSAndroid Build Coastguard Worker     case GL_NONE:
278*35238bceSAndroid Build Coastguard Worker         return FormatFlags(0);
279*35238bceSAndroid Build Coastguard Worker     case GL_RENDERBUFFER:
280*35238bceSAndroid Build Coastguard Worker         return RENDERBUFFER_VALID;
281*35238bceSAndroid Build Coastguard Worker     case GL_TEXTURE:
282*35238bceSAndroid Build Coastguard Worker         return TEXTURE_VALID;
283*35238bceSAndroid Build Coastguard Worker     case GL_STENCIL_ATTACHMENT:
284*35238bceSAndroid Build Coastguard Worker         return STENCIL_RENDERABLE;
285*35238bceSAndroid Build Coastguard Worker     case GL_DEPTH_ATTACHMENT:
286*35238bceSAndroid Build Coastguard Worker         return DEPTH_RENDERABLE;
287*35238bceSAndroid Build Coastguard Worker     default:
288*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(context >= GL_COLOR_ATTACHMENT0 && context <= GL_COLOR_ATTACHMENT15);
289*35238bceSAndroid Build Coastguard Worker         return COLOR_RENDERABLE;
290*35238bceSAndroid Build Coastguard Worker     }
291*35238bceSAndroid Build Coastguard Worker }
292*35238bceSAndroid Build Coastguard Worker 
getAttachmentRenderabilityFlag(GLenum attachment)293*35238bceSAndroid Build Coastguard Worker static FormatFlags getAttachmentRenderabilityFlag(GLenum attachment)
294*35238bceSAndroid Build Coastguard Worker {
295*35238bceSAndroid Build Coastguard Worker     switch (attachment)
296*35238bceSAndroid Build Coastguard Worker     {
297*35238bceSAndroid Build Coastguard Worker     case GL_STENCIL_ATTACHMENT:
298*35238bceSAndroid Build Coastguard Worker         return STENCIL_RENDERABLE;
299*35238bceSAndroid Build Coastguard Worker     case GL_DEPTH_ATTACHMENT:
300*35238bceSAndroid Build Coastguard Worker         return DEPTH_RENDERABLE;
301*35238bceSAndroid Build Coastguard Worker 
302*35238bceSAndroid Build Coastguard Worker     default:
303*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15);
304*35238bceSAndroid Build Coastguard Worker         return COLOR_RENDERABLE;
305*35238bceSAndroid Build Coastguard Worker     }
306*35238bceSAndroid Build Coastguard Worker }
307*35238bceSAndroid Build Coastguard Worker 
308*35238bceSAndroid Build Coastguard Worker namespace config
309*35238bceSAndroid Build Coastguard Worker {
310*35238bceSAndroid Build Coastguard Worker 
imageNumSamples(const Image & img)311*35238bceSAndroid Build Coastguard Worker GLsizei imageNumSamples(const Image &img)
312*35238bceSAndroid Build Coastguard Worker {
313*35238bceSAndroid Build Coastguard Worker     if (const Renderbuffer *rbo = dynamic_cast<const Renderbuffer *>(&img))
314*35238bceSAndroid Build Coastguard Worker         return rbo->numSamples;
315*35238bceSAndroid Build Coastguard Worker     return 0;
316*35238bceSAndroid Build Coastguard Worker }
317*35238bceSAndroid Build Coastguard Worker 
glTarget(const Image & img)318*35238bceSAndroid Build Coastguard Worker static GLenum glTarget(const Image &img)
319*35238bceSAndroid Build Coastguard Worker {
320*35238bceSAndroid Build Coastguard Worker     if (dynamic_cast<const Renderbuffer *>(&img) != DE_NULL)
321*35238bceSAndroid Build Coastguard Worker         return GL_RENDERBUFFER;
322*35238bceSAndroid Build Coastguard Worker     if (dynamic_cast<const Texture2D *>(&img) != DE_NULL)
323*35238bceSAndroid Build Coastguard Worker         return GL_TEXTURE_2D;
324*35238bceSAndroid Build Coastguard Worker     if (dynamic_cast<const TextureCubeMap *>(&img) != DE_NULL)
325*35238bceSAndroid Build Coastguard Worker         return GL_TEXTURE_CUBE_MAP;
326*35238bceSAndroid Build Coastguard Worker     if (dynamic_cast<const Texture3D *>(&img) != DE_NULL)
327*35238bceSAndroid Build Coastguard Worker         return GL_TEXTURE_3D;
328*35238bceSAndroid Build Coastguard Worker     if (dynamic_cast<const Texture2DArray *>(&img) != DE_NULL)
329*35238bceSAndroid Build Coastguard Worker         return GL_TEXTURE_2D_ARRAY;
330*35238bceSAndroid Build Coastguard Worker 
331*35238bceSAndroid Build Coastguard Worker     DE_FATAL("Impossible image type");
332*35238bceSAndroid Build Coastguard Worker     return GL_NONE;
333*35238bceSAndroid Build Coastguard Worker }
334*35238bceSAndroid Build Coastguard Worker 
glInitFlat(const TextureFlat & cfg,GLenum target,const glw::Functions & gl)335*35238bceSAndroid Build Coastguard Worker static void glInitFlat(const TextureFlat &cfg, GLenum target, const glw::Functions &gl)
336*35238bceSAndroid Build Coastguard Worker {
337*35238bceSAndroid Build Coastguard Worker     const TransferFormat format = transferImageFormat(cfg.internalFormat);
338*35238bceSAndroid Build Coastguard Worker     GLint w                     = cfg.width;
339*35238bceSAndroid Build Coastguard Worker     GLint h                     = cfg.height;
340*35238bceSAndroid Build Coastguard Worker     for (GLint level = 0; level < cfg.numLevels; level++)
341*35238bceSAndroid Build Coastguard Worker     {
342*35238bceSAndroid Build Coastguard Worker         gl.texImage2D(target, level, cfg.internalFormat.format, w, h, 0, format.format, format.dataType, DE_NULL);
343*35238bceSAndroid Build Coastguard Worker         w = de::max(1, w / 2);
344*35238bceSAndroid Build Coastguard Worker         h = de::max(1, h / 2);
345*35238bceSAndroid Build Coastguard Worker     }
346*35238bceSAndroid Build Coastguard Worker }
347*35238bceSAndroid Build Coastguard Worker 
glInitLayered(const TextureLayered & cfg,GLint depth_divider,const glw::Functions & gl)348*35238bceSAndroid Build Coastguard Worker static void glInitLayered(const TextureLayered &cfg, GLint depth_divider, const glw::Functions &gl)
349*35238bceSAndroid Build Coastguard Worker {
350*35238bceSAndroid Build Coastguard Worker     const TransferFormat format = transferImageFormat(cfg.internalFormat);
351*35238bceSAndroid Build Coastguard Worker     GLint w                     = cfg.width;
352*35238bceSAndroid Build Coastguard Worker     GLint h                     = cfg.height;
353*35238bceSAndroid Build Coastguard Worker     GLint depth                 = cfg.numLayers;
354*35238bceSAndroid Build Coastguard Worker     for (GLint level = 0; level < cfg.numLevels; level++)
355*35238bceSAndroid Build Coastguard Worker     {
356*35238bceSAndroid Build Coastguard Worker         gl.texImage3D(glTarget(cfg), level, cfg.internalFormat.format, w, h, depth, 0, format.format, format.dataType,
357*35238bceSAndroid Build Coastguard Worker                       DE_NULL);
358*35238bceSAndroid Build Coastguard Worker         w     = de::max(1, w / 2);
359*35238bceSAndroid Build Coastguard Worker         h     = de::max(1, h / 2);
360*35238bceSAndroid Build Coastguard Worker         depth = de::max(1, depth / depth_divider);
361*35238bceSAndroid Build Coastguard Worker     }
362*35238bceSAndroid Build Coastguard Worker }
363*35238bceSAndroid Build Coastguard Worker 
glInit(const Texture & cfg,const glw::Functions & gl)364*35238bceSAndroid Build Coastguard Worker static void glInit(const Texture &cfg, const glw::Functions &gl)
365*35238bceSAndroid Build Coastguard Worker {
366*35238bceSAndroid Build Coastguard Worker     if (const Texture2D *t2d = dynamic_cast<const Texture2D *>(&cfg))
367*35238bceSAndroid Build Coastguard Worker         glInitFlat(*t2d, glTarget(*t2d), gl);
368*35238bceSAndroid Build Coastguard Worker     else if (const TextureCubeMap *tcm = dynamic_cast<const TextureCubeMap *>(&cfg))
369*35238bceSAndroid Build Coastguard Worker     {
370*35238bceSAndroid Build Coastguard Worker         // \todo [2013-12-05 lauri]
371*35238bceSAndroid Build Coastguard Worker         // move this to glu or someplace sensible (this array is already
372*35238bceSAndroid Build Coastguard Worker         // present in duplicates)
373*35238bceSAndroid Build Coastguard Worker         static const GLenum s_cubeMapFaces[] = {
374*35238bceSAndroid Build Coastguard Worker             GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
375*35238bceSAndroid Build Coastguard Worker             GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
376*35238bceSAndroid Build Coastguard Worker         };
377*35238bceSAndroid Build Coastguard Worker         const Range<GLenum> range = GLS_ARRAY_RANGE(s_cubeMapFaces);
378*35238bceSAndroid Build Coastguard Worker         for (const GLenum *it = range.begin(); it != range.end(); it++)
379*35238bceSAndroid Build Coastguard Worker             glInitFlat(*tcm, *it, gl);
380*35238bceSAndroid Build Coastguard Worker     }
381*35238bceSAndroid Build Coastguard Worker     else if (const Texture3D *t3d = dynamic_cast<const Texture3D *>(&cfg))
382*35238bceSAndroid Build Coastguard Worker         glInitLayered(*t3d, 2, gl);
383*35238bceSAndroid Build Coastguard Worker     else if (const Texture2DArray *t2a = dynamic_cast<const Texture2DArray *>(&cfg))
384*35238bceSAndroid Build Coastguard Worker         glInitLayered(*t2a, 1, gl);
385*35238bceSAndroid Build Coastguard Worker }
386*35238bceSAndroid Build Coastguard Worker 
glCreate(const Image & cfg,const glw::Functions & gl)387*35238bceSAndroid Build Coastguard Worker static GLuint glCreate(const Image &cfg, const glw::Functions &gl)
388*35238bceSAndroid Build Coastguard Worker {
389*35238bceSAndroid Build Coastguard Worker     GLuint ret = 0;
390*35238bceSAndroid Build Coastguard Worker     if (const Renderbuffer *const rbo = dynamic_cast<const Renderbuffer *>(&cfg))
391*35238bceSAndroid Build Coastguard Worker     {
392*35238bceSAndroid Build Coastguard Worker         gl.genRenderbuffers(1, &ret);
393*35238bceSAndroid Build Coastguard Worker         gl.bindRenderbuffer(GL_RENDERBUFFER, ret);
394*35238bceSAndroid Build Coastguard Worker 
395*35238bceSAndroid Build Coastguard Worker         if (rbo->numSamples == 0)
396*35238bceSAndroid Build Coastguard Worker             gl.renderbufferStorage(GL_RENDERBUFFER, rbo->internalFormat.format, rbo->width, rbo->height);
397*35238bceSAndroid Build Coastguard Worker         else
398*35238bceSAndroid Build Coastguard Worker             gl.renderbufferStorageMultisample(GL_RENDERBUFFER, rbo->numSamples, rbo->internalFormat.format, rbo->width,
399*35238bceSAndroid Build Coastguard Worker                                               rbo->height);
400*35238bceSAndroid Build Coastguard Worker 
401*35238bceSAndroid Build Coastguard Worker         gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
402*35238bceSAndroid Build Coastguard Worker     }
403*35238bceSAndroid Build Coastguard Worker     else if (const Texture *const tex = dynamic_cast<const Texture *>(&cfg))
404*35238bceSAndroid Build Coastguard Worker     {
405*35238bceSAndroid Build Coastguard Worker         gl.genTextures(1, &ret);
406*35238bceSAndroid Build Coastguard Worker         gl.bindTexture(glTarget(*tex), ret);
407*35238bceSAndroid Build Coastguard Worker         glInit(*tex, gl);
408*35238bceSAndroid Build Coastguard Worker         gl.bindTexture(glTarget(*tex), 0);
409*35238bceSAndroid Build Coastguard Worker     }
410*35238bceSAndroid Build Coastguard Worker     else
411*35238bceSAndroid Build Coastguard Worker         DE_FATAL("Impossible image type");
412*35238bceSAndroid Build Coastguard Worker     return ret;
413*35238bceSAndroid Build Coastguard Worker }
414*35238bceSAndroid Build Coastguard Worker 
glDelete(const Image & cfg,GLuint img,const glw::Functions & gl)415*35238bceSAndroid Build Coastguard Worker static void glDelete(const Image &cfg, GLuint img, const glw::Functions &gl)
416*35238bceSAndroid Build Coastguard Worker {
417*35238bceSAndroid Build Coastguard Worker     if (dynamic_cast<const Renderbuffer *>(&cfg) != DE_NULL)
418*35238bceSAndroid Build Coastguard Worker         gl.deleteRenderbuffers(1, &img);
419*35238bceSAndroid Build Coastguard Worker     else if (dynamic_cast<const Texture *>(&cfg) != DE_NULL)
420*35238bceSAndroid Build Coastguard Worker         gl.deleteTextures(1, &img);
421*35238bceSAndroid Build Coastguard Worker     else
422*35238bceSAndroid Build Coastguard Worker         DE_FATAL("Impossible image type");
423*35238bceSAndroid Build Coastguard Worker }
424*35238bceSAndroid Build Coastguard Worker 
attachAttachment(const Attachment & att,GLenum attPoint,const glw::Functions & gl)425*35238bceSAndroid Build Coastguard Worker static void attachAttachment(const Attachment &att, GLenum attPoint, const glw::Functions &gl)
426*35238bceSAndroid Build Coastguard Worker {
427*35238bceSAndroid Build Coastguard Worker     if (const RenderbufferAttachment *const rAtt = dynamic_cast<const RenderbufferAttachment *>(&att))
428*35238bceSAndroid Build Coastguard Worker         gl.framebufferRenderbuffer(rAtt->target, attPoint, rAtt->renderbufferTarget, rAtt->imageName);
429*35238bceSAndroid Build Coastguard Worker     else if (const TextureFlatAttachment *const fAtt = dynamic_cast<const TextureFlatAttachment *>(&att))
430*35238bceSAndroid Build Coastguard Worker         gl.framebufferTexture2D(fAtt->target, attPoint, fAtt->texTarget, fAtt->imageName, fAtt->level);
431*35238bceSAndroid Build Coastguard Worker     else if (const TextureLayerAttachment *const lAtt = dynamic_cast<const TextureLayerAttachment *>(&att))
432*35238bceSAndroid Build Coastguard Worker         gl.framebufferTextureLayer(lAtt->target, attPoint, lAtt->imageName, lAtt->level, lAtt->layer);
433*35238bceSAndroid Build Coastguard Worker     else
434*35238bceSAndroid Build Coastguard Worker         DE_FATAL("Impossible attachment type");
435*35238bceSAndroid Build Coastguard Worker }
436*35238bceSAndroid Build Coastguard Worker 
attachmentType(const Attachment & att)437*35238bceSAndroid Build Coastguard Worker GLenum attachmentType(const Attachment &att)
438*35238bceSAndroid Build Coastguard Worker {
439*35238bceSAndroid Build Coastguard Worker     if (dynamic_cast<const RenderbufferAttachment *>(&att) != DE_NULL)
440*35238bceSAndroid Build Coastguard Worker         return GL_RENDERBUFFER;
441*35238bceSAndroid Build Coastguard Worker     else if (dynamic_cast<const TextureAttachment *>(&att) != DE_NULL)
442*35238bceSAndroid Build Coastguard Worker         return GL_TEXTURE;
443*35238bceSAndroid Build Coastguard Worker 
444*35238bceSAndroid Build Coastguard Worker     DE_FATAL("Impossible attachment type");
445*35238bceSAndroid Build Coastguard Worker     return GL_NONE;
446*35238bceSAndroid Build Coastguard Worker }
447*35238bceSAndroid Build Coastguard Worker 
textureLayer(const TextureAttachment & tAtt)448*35238bceSAndroid Build Coastguard Worker static GLsizei textureLayer(const TextureAttachment &tAtt)
449*35238bceSAndroid Build Coastguard Worker {
450*35238bceSAndroid Build Coastguard Worker     if (dynamic_cast<const TextureFlatAttachment *>(&tAtt) != DE_NULL)
451*35238bceSAndroid Build Coastguard Worker         return 0;
452*35238bceSAndroid Build Coastguard Worker     else if (const TextureLayerAttachment *const lAtt = dynamic_cast<const TextureLayerAttachment *>(&tAtt))
453*35238bceSAndroid Build Coastguard Worker         return lAtt->layer;
454*35238bceSAndroid Build Coastguard Worker 
455*35238bceSAndroid Build Coastguard Worker     DE_FATAL("Impossible attachment type");
456*35238bceSAndroid Build Coastguard Worker     return 0;
457*35238bceSAndroid Build Coastguard Worker }
458*35238bceSAndroid Build Coastguard Worker 
checkAttachmentCompleteness(Checker & cctx,const Attachment & attachment,GLenum attPoint,const Image * image,const FormatDB & db)459*35238bceSAndroid Build Coastguard Worker static void checkAttachmentCompleteness(Checker &cctx, const Attachment &attachment, GLenum attPoint,
460*35238bceSAndroid Build Coastguard Worker                                         const Image *image, const FormatDB &db)
461*35238bceSAndroid Build Coastguard Worker {
462*35238bceSAndroid Build Coastguard Worker     // GLES2 4.4.5 / GLES3 4.4.4, "Framebuffer attachment completeness"
463*35238bceSAndroid Build Coastguard Worker 
464*35238bceSAndroid Build Coastguard Worker     if (const TextureAttachment *const texAtt = dynamic_cast<const TextureAttachment *>(&attachment))
465*35238bceSAndroid Build Coastguard Worker         if (const TextureLayered *const ltex = dynamic_cast<const TextureLayered *>(image))
466*35238bceSAndroid Build Coastguard Worker         {
467*35238bceSAndroid Build Coastguard Worker             // GLES3: "If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is
468*35238bceSAndroid Build Coastguard Worker             // TEXTURE and the value of FRAMEBUFFER_ATTACHMENT_OBJECT_NAME names a
469*35238bceSAndroid Build Coastguard Worker             // three-dimensional texture, then the value of
470*35238bceSAndroid Build Coastguard Worker             // FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER must be smaller than the depth
471*35238bceSAndroid Build Coastguard Worker             // of the texture.
472*35238bceSAndroid Build Coastguard Worker             //
473*35238bceSAndroid Build Coastguard Worker             // GLES3: "If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is
474*35238bceSAndroid Build Coastguard Worker             // TEXTURE and the value of FRAMEBUFFER_ATTACHMENT_OBJECT_NAME names a
475*35238bceSAndroid Build Coastguard Worker             // two-dimensional array texture, then the value of
476*35238bceSAndroid Build Coastguard Worker             // FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER must be smaller than the
477*35238bceSAndroid Build Coastguard Worker             // number of layers in the texture.
478*35238bceSAndroid Build Coastguard Worker 
479*35238bceSAndroid Build Coastguard Worker             if (textureLayer(*texAtt) >= ltex->numLayers)
480*35238bceSAndroid Build Coastguard Worker                 cctx.addFBOStatus(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, "Attached layer index is larger than present");
481*35238bceSAndroid Build Coastguard Worker         }
482*35238bceSAndroid Build Coastguard Worker 
483*35238bceSAndroid Build Coastguard Worker     // "The width and height of image are non-zero."
484*35238bceSAndroid Build Coastguard Worker     if (image->width == 0 || image->height == 0)
485*35238bceSAndroid Build Coastguard Worker         cctx.addFBOStatus(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, "Width and height of an image are not non-zero");
486*35238bceSAndroid Build Coastguard Worker 
487*35238bceSAndroid Build Coastguard Worker     // Check for renderability
488*35238bceSAndroid Build Coastguard Worker     if (db.isKnownFormat(image->internalFormat))
489*35238bceSAndroid Build Coastguard Worker     {
490*35238bceSAndroid Build Coastguard Worker         const FormatFlags flags = db.getFormatInfo(image->internalFormat);
491*35238bceSAndroid Build Coastguard Worker 
492*35238bceSAndroid Build Coastguard Worker         // If the format does not have the proper renderability flag, the
493*35238bceSAndroid Build Coastguard Worker         // completeness check _must_ fail.
494*35238bceSAndroid Build Coastguard Worker         if ((flags & getAttachmentRenderabilityFlag(attPoint)) == 0)
495*35238bceSAndroid Build Coastguard Worker             cctx.addFBOStatus(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
496*35238bceSAndroid Build Coastguard Worker                               "Attachment format is not renderable in this attachment");
497*35238bceSAndroid Build Coastguard Worker         // If the format is only optionally renderable, the completeness check _can_ fail.
498*35238bceSAndroid Build Coastguard Worker         else if ((flags & REQUIRED_RENDERABLE) == 0)
499*35238bceSAndroid Build Coastguard Worker             cctx.addPotentialFBOStatus(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
500*35238bceSAndroid Build Coastguard Worker                                        "Attachment format is not required renderable");
501*35238bceSAndroid Build Coastguard Worker     }
502*35238bceSAndroid Build Coastguard Worker     else
503*35238bceSAndroid Build Coastguard Worker         cctx.addFBOStatus(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, "Attachment format is not legal");
504*35238bceSAndroid Build Coastguard Worker }
505*35238bceSAndroid Build Coastguard Worker 
506*35238bceSAndroid Build Coastguard Worker } // namespace config
507*35238bceSAndroid Build Coastguard Worker 
508*35238bceSAndroid Build Coastguard Worker using namespace config;
509*35238bceSAndroid Build Coastguard Worker 
Checker(const glu::RenderContext & ctx,const FormatDB & formats)510*35238bceSAndroid Build Coastguard Worker Checker::Checker(const glu::RenderContext &ctx, const FormatDB &formats) : m_renderCtx(ctx), m_formats(formats)
511*35238bceSAndroid Build Coastguard Worker {
512*35238bceSAndroid Build Coastguard Worker     m_statusCodes.setAllowComplete(true);
513*35238bceSAndroid Build Coastguard Worker }
514*35238bceSAndroid Build Coastguard Worker 
addGLError(glw::GLenum error,const char * description)515*35238bceSAndroid Build Coastguard Worker void Checker::addGLError(glw::GLenum error, const char *description)
516*35238bceSAndroid Build Coastguard Worker {
517*35238bceSAndroid Build Coastguard Worker     m_statusCodes.addErrorCode(error, description);
518*35238bceSAndroid Build Coastguard Worker     m_statusCodes.setAllowComplete(false);
519*35238bceSAndroid Build Coastguard Worker }
520*35238bceSAndroid Build Coastguard Worker 
addPotentialGLError(glw::GLenum error,const char * description)521*35238bceSAndroid Build Coastguard Worker void Checker::addPotentialGLError(glw::GLenum error, const char *description)
522*35238bceSAndroid Build Coastguard Worker {
523*35238bceSAndroid Build Coastguard Worker     m_statusCodes.addErrorCode(error, description);
524*35238bceSAndroid Build Coastguard Worker }
525*35238bceSAndroid Build Coastguard Worker 
addFBOStatus(GLenum status,const char * description)526*35238bceSAndroid Build Coastguard Worker void Checker::addFBOStatus(GLenum status, const char *description)
527*35238bceSAndroid Build Coastguard Worker {
528*35238bceSAndroid Build Coastguard Worker     m_statusCodes.addFBOErrorStatus(status, description);
529*35238bceSAndroid Build Coastguard Worker     m_statusCodes.setAllowComplete(false);
530*35238bceSAndroid Build Coastguard Worker }
531*35238bceSAndroid Build Coastguard Worker 
addPotentialFBOStatus(GLenum status,const char * description)532*35238bceSAndroid Build Coastguard Worker void Checker::addPotentialFBOStatus(GLenum status, const char *description)
533*35238bceSAndroid Build Coastguard Worker {
534*35238bceSAndroid Build Coastguard Worker     m_statusCodes.addFBOErrorStatus(status, description);
535*35238bceSAndroid Build Coastguard Worker }
536*35238bceSAndroid Build Coastguard Worker 
FboVerifier(const FormatDB & formats,CheckerFactory & factory,const glu::RenderContext & renderCtx)537*35238bceSAndroid Build Coastguard Worker FboVerifier::FboVerifier(const FormatDB &formats, CheckerFactory &factory, const glu::RenderContext &renderCtx)
538*35238bceSAndroid Build Coastguard Worker     : m_formats(formats)
539*35238bceSAndroid Build Coastguard Worker     , m_factory(factory)
540*35238bceSAndroid Build Coastguard Worker     , m_renderCtx(renderCtx)
541*35238bceSAndroid Build Coastguard Worker {
542*35238bceSAndroid Build Coastguard Worker }
543*35238bceSAndroid Build Coastguard Worker 
544*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
545*35238bceSAndroid Build Coastguard Worker  * \brief Return acceptable framebuffer status codes.
546*35238bceSAndroid Build Coastguard Worker  *
547*35238bceSAndroid Build Coastguard Worker  * This function examines the framebuffer configuration descriptor `fboConfig`
548*35238bceSAndroid Build Coastguard Worker  * and returns the set of status codes that `glCheckFramebufferStatus` is
549*35238bceSAndroid Build Coastguard Worker  * allowed to return on a conforming implementation when given a framebuffer
550*35238bceSAndroid Build Coastguard Worker  * whose configuration adheres to `fboConfig`.
551*35238bceSAndroid Build Coastguard Worker  *
552*35238bceSAndroid Build Coastguard Worker  * The returned set is guaranteed to be non-empty, but it may contain multiple
553*35238bceSAndroid Build Coastguard Worker  * INCOMPLETE statuses (if there are multiple errors in the spec), or or a mix
554*35238bceSAndroid Build Coastguard Worker  * of COMPLETE and INCOMPLETE statuses (if supporting a FBO with this spec is
555*35238bceSAndroid Build Coastguard Worker  * optional). Furthermore, the statuses may contain GL error codes, which
556*35238bceSAndroid Build Coastguard Worker  * indicate that trying to create a framebuffer configuration like this could
557*35238bceSAndroid Build Coastguard Worker  * have failed with an error (if one was checked for) even before
558*35238bceSAndroid Build Coastguard Worker  * `glCheckFramebufferStatus` was ever called.
559*35238bceSAndroid Build Coastguard Worker  *
560*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
validStatusCodes(const Framebuffer & fboConfig) const561*35238bceSAndroid Build Coastguard Worker ValidStatusCodes FboVerifier::validStatusCodes(const Framebuffer &fboConfig) const
562*35238bceSAndroid Build Coastguard Worker {
563*35238bceSAndroid Build Coastguard Worker     const AttachmentMap &atts = fboConfig.attachments;
564*35238bceSAndroid Build Coastguard Worker     const UniquePtr<Checker> cctx(m_factory.createChecker(m_renderCtx, m_formats));
565*35238bceSAndroid Build Coastguard Worker 
566*35238bceSAndroid Build Coastguard Worker     for (TextureMap::const_iterator it = fboConfig.textures.begin(); it != fboConfig.textures.end(); it++)
567*35238bceSAndroid Build Coastguard Worker     {
568*35238bceSAndroid Build Coastguard Worker         std::string errorDescription;
569*35238bceSAndroid Build Coastguard Worker 
570*35238bceSAndroid Build Coastguard Worker         if (m_formats.isKnownFormat(it->second->internalFormat))
571*35238bceSAndroid Build Coastguard Worker         {
572*35238bceSAndroid Build Coastguard Worker             const FormatFlags flags = m_formats.getFormatInfo(it->second->internalFormat);
573*35238bceSAndroid Build Coastguard Worker 
574*35238bceSAndroid Build Coastguard Worker             if ((flags & TEXTURE_VALID) == 0)
575*35238bceSAndroid Build Coastguard Worker                 errorDescription =
576*35238bceSAndroid Build Coastguard Worker                     "Format " + de::toString(it->second->internalFormat) + " is not a valid format for a texture";
577*35238bceSAndroid Build Coastguard Worker         }
578*35238bceSAndroid Build Coastguard Worker         else if (it->second->internalFormat.unsizedType == GL_NONE)
579*35238bceSAndroid Build Coastguard Worker         {
580*35238bceSAndroid Build Coastguard Worker             // sized format
581*35238bceSAndroid Build Coastguard Worker             errorDescription = "Format " + de::toString(it->second->internalFormat) + " does not exist";
582*35238bceSAndroid Build Coastguard Worker         }
583*35238bceSAndroid Build Coastguard Worker         else
584*35238bceSAndroid Build Coastguard Worker         {
585*35238bceSAndroid Build Coastguard Worker             // unsized type-format pair
586*35238bceSAndroid Build Coastguard Worker             errorDescription = "Format " + de::toString(it->second->internalFormat) + " is not a legal format";
587*35238bceSAndroid Build Coastguard Worker         }
588*35238bceSAndroid Build Coastguard Worker 
589*35238bceSAndroid Build Coastguard Worker         if (!errorDescription.empty())
590*35238bceSAndroid Build Coastguard Worker         {
591*35238bceSAndroid Build Coastguard Worker             cctx->addGLError(GL_INVALID_ENUM, errorDescription.c_str());
592*35238bceSAndroid Build Coastguard Worker             cctx->addGLError(GL_INVALID_OPERATION, errorDescription.c_str());
593*35238bceSAndroid Build Coastguard Worker             cctx->addGLError(GL_INVALID_VALUE, errorDescription.c_str());
594*35238bceSAndroid Build Coastguard Worker         }
595*35238bceSAndroid Build Coastguard Worker     }
596*35238bceSAndroid Build Coastguard Worker 
597*35238bceSAndroid Build Coastguard Worker     for (RboMap::const_iterator it = fboConfig.rbos.begin(); it != fboConfig.rbos.end(); it++)
598*35238bceSAndroid Build Coastguard Worker     {
599*35238bceSAndroid Build Coastguard Worker         if (m_formats.isKnownFormat(it->second->internalFormat))
600*35238bceSAndroid Build Coastguard Worker         {
601*35238bceSAndroid Build Coastguard Worker             const FormatFlags flags = m_formats.getFormatInfo(it->second->internalFormat);
602*35238bceSAndroid Build Coastguard Worker             if ((flags & RENDERBUFFER_VALID) == 0)
603*35238bceSAndroid Build Coastguard Worker             {
604*35238bceSAndroid Build Coastguard Worker                 const std::string reason =
605*35238bceSAndroid Build Coastguard Worker                     "Format " + de::toString(it->second->internalFormat) + " is not a valid format for a renderbuffer";
606*35238bceSAndroid Build Coastguard Worker                 cctx->addGLError(GL_INVALID_ENUM, reason.c_str());
607*35238bceSAndroid Build Coastguard Worker             }
608*35238bceSAndroid Build Coastguard Worker         }
609*35238bceSAndroid Build Coastguard Worker         else
610*35238bceSAndroid Build Coastguard Worker         {
611*35238bceSAndroid Build Coastguard Worker             const std::string reason =
612*35238bceSAndroid Build Coastguard Worker                 "Internal format " + de::toString(it->second->internalFormat) + " does not exist";
613*35238bceSAndroid Build Coastguard Worker             cctx->addGLError(GL_INVALID_ENUM, reason.c_str());
614*35238bceSAndroid Build Coastguard Worker         }
615*35238bceSAndroid Build Coastguard Worker     }
616*35238bceSAndroid Build Coastguard Worker 
617*35238bceSAndroid Build Coastguard Worker     // "There is at least one image attached to the framebuffer."
618*35238bceSAndroid Build Coastguard Worker     // \todo support XXX_framebuffer_no_attachments
619*35238bceSAndroid Build Coastguard Worker     if (atts.empty())
620*35238bceSAndroid Build Coastguard Worker         cctx->addFBOStatus(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT, "No images attached to the framebuffer");
621*35238bceSAndroid Build Coastguard Worker 
622*35238bceSAndroid Build Coastguard Worker     for (AttachmentMap::const_iterator it = atts.begin(); it != atts.end(); it++)
623*35238bceSAndroid Build Coastguard Worker     {
624*35238bceSAndroid Build Coastguard Worker         const GLenum attPoint    = it->first;
625*35238bceSAndroid Build Coastguard Worker         const Attachment &att    = *it->second;
626*35238bceSAndroid Build Coastguard Worker         const Image *const image = fboConfig.getImage(attachmentType(att), att.imageName);
627*35238bceSAndroid Build Coastguard Worker 
628*35238bceSAndroid Build Coastguard Worker         checkAttachmentCompleteness(*cctx, att, attPoint, image, m_formats);
629*35238bceSAndroid Build Coastguard Worker         cctx->check(it->first, *it->second, image);
630*35238bceSAndroid Build Coastguard Worker     }
631*35238bceSAndroid Build Coastguard Worker 
632*35238bceSAndroid Build Coastguard Worker     return cctx->getStatusCodes();
633*35238bceSAndroid Build Coastguard Worker }
634*35238bceSAndroid Build Coastguard Worker 
attach(glw::GLenum attPoint,const Attachment * att)635*35238bceSAndroid Build Coastguard Worker void Framebuffer::attach(glw::GLenum attPoint, const Attachment *att)
636*35238bceSAndroid Build Coastguard Worker {
637*35238bceSAndroid Build Coastguard Worker     if (att == DE_NULL)
638*35238bceSAndroid Build Coastguard Worker         attachments.erase(attPoint);
639*35238bceSAndroid Build Coastguard Worker     else
640*35238bceSAndroid Build Coastguard Worker         attachments[attPoint] = att;
641*35238bceSAndroid Build Coastguard Worker }
642*35238bceSAndroid Build Coastguard Worker 
getImage(GLenum type,glw::GLuint imgName) const643*35238bceSAndroid Build Coastguard Worker const Image *Framebuffer::getImage(GLenum type, glw::GLuint imgName) const
644*35238bceSAndroid Build Coastguard Worker {
645*35238bceSAndroid Build Coastguard Worker     switch (type)
646*35238bceSAndroid Build Coastguard Worker     {
647*35238bceSAndroid Build Coastguard Worker     case GL_TEXTURE:
648*35238bceSAndroid Build Coastguard Worker         return de::lookupDefault(textures, imgName, DE_NULL);
649*35238bceSAndroid Build Coastguard Worker     case GL_RENDERBUFFER:
650*35238bceSAndroid Build Coastguard Worker         return de::lookupDefault(rbos, imgName, DE_NULL);
651*35238bceSAndroid Build Coastguard Worker     default:
652*35238bceSAndroid Build Coastguard Worker         DE_FATAL("Bad image type");
653*35238bceSAndroid Build Coastguard Worker     }
654*35238bceSAndroid Build Coastguard Worker     return DE_NULL; // shut up compiler warning
655*35238bceSAndroid Build Coastguard Worker }
656*35238bceSAndroid Build Coastguard Worker 
setTexture(glw::GLuint texName,const Texture & texCfg)657*35238bceSAndroid Build Coastguard Worker void Framebuffer::setTexture(glw::GLuint texName, const Texture &texCfg)
658*35238bceSAndroid Build Coastguard Worker {
659*35238bceSAndroid Build Coastguard Worker     textures[texName] = &texCfg;
660*35238bceSAndroid Build Coastguard Worker }
661*35238bceSAndroid Build Coastguard Worker 
setRbo(glw::GLuint rbName,const Renderbuffer & rbCfg)662*35238bceSAndroid Build Coastguard Worker void Framebuffer::setRbo(glw::GLuint rbName, const Renderbuffer &rbCfg)
663*35238bceSAndroid Build Coastguard Worker {
664*35238bceSAndroid Build Coastguard Worker     rbos[rbName] = &rbCfg;
665*35238bceSAndroid Build Coastguard Worker }
666*35238bceSAndroid Build Coastguard Worker 
logField(TestLog & log,const string & field,const string & value)667*35238bceSAndroid Build Coastguard Worker static void logField(TestLog &log, const string &field, const string &value)
668*35238bceSAndroid Build Coastguard Worker {
669*35238bceSAndroid Build Coastguard Worker     log << TestLog::Message << field << ": " << value << TestLog::EndMessage;
670*35238bceSAndroid Build Coastguard Worker }
671*35238bceSAndroid Build Coastguard Worker 
logImage(const Image & img,TestLog & log,bool useType)672*35238bceSAndroid Build Coastguard Worker static void logImage(const Image &img, TestLog &log, bool useType)
673*35238bceSAndroid Build Coastguard Worker {
674*35238bceSAndroid Build Coastguard Worker     const GLenum type = img.internalFormat.unsizedType;
675*35238bceSAndroid Build Coastguard Worker     logField(log, "Internal format", getTextureFormatName(img.internalFormat.format));
676*35238bceSAndroid Build Coastguard Worker     if (useType && type != GL_NONE)
677*35238bceSAndroid Build Coastguard Worker         logField(log, "Format type", getTypeName(type));
678*35238bceSAndroid Build Coastguard Worker     logField(log, "Width", toString(img.width));
679*35238bceSAndroid Build Coastguard Worker     logField(log, "Height", toString(img.height));
680*35238bceSAndroid Build Coastguard Worker }
681*35238bceSAndroid Build Coastguard Worker 
logRenderbuffer(const Renderbuffer & rbo,TestLog & log)682*35238bceSAndroid Build Coastguard Worker static void logRenderbuffer(const Renderbuffer &rbo, TestLog &log)
683*35238bceSAndroid Build Coastguard Worker {
684*35238bceSAndroid Build Coastguard Worker     logImage(rbo, log, false);
685*35238bceSAndroid Build Coastguard Worker     logField(log, "Samples", toString(rbo.numSamples));
686*35238bceSAndroid Build Coastguard Worker }
687*35238bceSAndroid Build Coastguard Worker 
logTexture(const Texture & tex,TestLog & log)688*35238bceSAndroid Build Coastguard Worker static void logTexture(const Texture &tex, TestLog &log)
689*35238bceSAndroid Build Coastguard Worker {
690*35238bceSAndroid Build Coastguard Worker     logField(log, "Type", glu::getTextureTargetName(glTarget(tex)));
691*35238bceSAndroid Build Coastguard Worker     logImage(tex, log, true);
692*35238bceSAndroid Build Coastguard Worker     logField(log, "Levels", toString(tex.numLevels));
693*35238bceSAndroid Build Coastguard Worker     if (const TextureLayered *const lTex = dynamic_cast<const TextureLayered *>(&tex))
694*35238bceSAndroid Build Coastguard Worker         logField(log, "Layers", toString(lTex->numLayers));
695*35238bceSAndroid Build Coastguard Worker }
696*35238bceSAndroid Build Coastguard Worker 
logAttachment(const Attachment & att,TestLog & log)697*35238bceSAndroid Build Coastguard Worker static void logAttachment(const Attachment &att, TestLog &log)
698*35238bceSAndroid Build Coastguard Worker {
699*35238bceSAndroid Build Coastguard Worker     logField(log, "Target", getFramebufferTargetName(att.target));
700*35238bceSAndroid Build Coastguard Worker     logField(log, "Type", getFramebufferAttachmentTypeName(attachmentType(att)));
701*35238bceSAndroid Build Coastguard Worker     logField(log, "Image Name", toString(att.imageName));
702*35238bceSAndroid Build Coastguard Worker     if (const RenderbufferAttachment *const rAtt = dynamic_cast<const RenderbufferAttachment *>(&att))
703*35238bceSAndroid Build Coastguard Worker     {
704*35238bceSAndroid Build Coastguard Worker         DE_UNREF(rAtt); // To shut up compiler during optimized builds.
705*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(rAtt->renderbufferTarget == GL_RENDERBUFFER);
706*35238bceSAndroid Build Coastguard Worker         logField(log, "Renderbuffer Target", "GL_RENDERBUFFER");
707*35238bceSAndroid Build Coastguard Worker     }
708*35238bceSAndroid Build Coastguard Worker     else if (const TextureAttachment *const tAtt = dynamic_cast<const TextureAttachment *>(&att))
709*35238bceSAndroid Build Coastguard Worker     {
710*35238bceSAndroid Build Coastguard Worker         logField(log, "Mipmap Level", toString(tAtt->level));
711*35238bceSAndroid Build Coastguard Worker         if (const TextureFlatAttachment *const fAtt = dynamic_cast<const TextureFlatAttachment *>(tAtt))
712*35238bceSAndroid Build Coastguard Worker             logField(log, "Texture Target", getTextureTargetName(fAtt->texTarget));
713*35238bceSAndroid Build Coastguard Worker         else if (const TextureLayerAttachment *const lAtt = dynamic_cast<const TextureLayerAttachment *>(tAtt))
714*35238bceSAndroid Build Coastguard Worker             logField(log, "Layer", toString(lAtt->level));
715*35238bceSAndroid Build Coastguard Worker     }
716*35238bceSAndroid Build Coastguard Worker }
717*35238bceSAndroid Build Coastguard Worker 
logFramebufferConfig(const Framebuffer & cfg,TestLog & log)718*35238bceSAndroid Build Coastguard Worker void logFramebufferConfig(const Framebuffer &cfg, TestLog &log)
719*35238bceSAndroid Build Coastguard Worker {
720*35238bceSAndroid Build Coastguard Worker     log << TestLog::Section("Framebuffer", "Framebuffer configuration");
721*35238bceSAndroid Build Coastguard Worker 
722*35238bceSAndroid Build Coastguard Worker     for (RboMap::const_iterator it = cfg.rbos.begin(); it != cfg.rbos.end(); ++it)
723*35238bceSAndroid Build Coastguard Worker     {
724*35238bceSAndroid Build Coastguard Worker         const string num = toString(it->first);
725*35238bceSAndroid Build Coastguard Worker         const tcu::ScopedLogSection subsection(log, num, "Renderbuffer " + num);
726*35238bceSAndroid Build Coastguard Worker 
727*35238bceSAndroid Build Coastguard Worker         logRenderbuffer(*it->second, log);
728*35238bceSAndroid Build Coastguard Worker     }
729*35238bceSAndroid Build Coastguard Worker 
730*35238bceSAndroid Build Coastguard Worker     for (TextureMap::const_iterator it = cfg.textures.begin(); it != cfg.textures.end(); ++it)
731*35238bceSAndroid Build Coastguard Worker     {
732*35238bceSAndroid Build Coastguard Worker         const string num = toString(it->first);
733*35238bceSAndroid Build Coastguard Worker         const tcu::ScopedLogSection subsection(log, num, "Texture " + num);
734*35238bceSAndroid Build Coastguard Worker 
735*35238bceSAndroid Build Coastguard Worker         logTexture(*it->second, log);
736*35238bceSAndroid Build Coastguard Worker     }
737*35238bceSAndroid Build Coastguard Worker 
738*35238bceSAndroid Build Coastguard Worker     const string attDesc = cfg.attachments.empty() ? "Framebuffer has no attachments" : "Framebuffer attachments";
739*35238bceSAndroid Build Coastguard Worker     log << TestLog::Section("Attachments", attDesc);
740*35238bceSAndroid Build Coastguard Worker     for (AttachmentMap::const_iterator it = cfg.attachments.begin(); it != cfg.attachments.end(); it++)
741*35238bceSAndroid Build Coastguard Worker     {
742*35238bceSAndroid Build Coastguard Worker         const string attPointName = getFramebufferAttachmentName(it->first);
743*35238bceSAndroid Build Coastguard Worker         log << TestLog::Section(attPointName, "Attachment point " + attPointName);
744*35238bceSAndroid Build Coastguard Worker         logAttachment(*it->second, log);
745*35238bceSAndroid Build Coastguard Worker         log << TestLog::EndSection;
746*35238bceSAndroid Build Coastguard Worker     }
747*35238bceSAndroid Build Coastguard Worker     log << TestLog::EndSection; // Attachments
748*35238bceSAndroid Build Coastguard Worker 
749*35238bceSAndroid Build Coastguard Worker     log << TestLog::EndSection; // Framebuffer
750*35238bceSAndroid Build Coastguard Worker }
751*35238bceSAndroid Build Coastguard Worker 
ValidStatusCodes(void)752*35238bceSAndroid Build Coastguard Worker ValidStatusCodes::ValidStatusCodes(void) : m_allowComplete(false)
753*35238bceSAndroid Build Coastguard Worker {
754*35238bceSAndroid Build Coastguard Worker }
755*35238bceSAndroid Build Coastguard Worker 
isFBOStatusValid(glw::GLenum fboStatus) const756*35238bceSAndroid Build Coastguard Worker bool ValidStatusCodes::isFBOStatusValid(glw::GLenum fboStatus) const
757*35238bceSAndroid Build Coastguard Worker {
758*35238bceSAndroid Build Coastguard Worker     if (fboStatus == GL_FRAMEBUFFER_COMPLETE)
759*35238bceSAndroid Build Coastguard Worker         return m_allowComplete;
760*35238bceSAndroid Build Coastguard Worker     else
761*35238bceSAndroid Build Coastguard Worker     {
762*35238bceSAndroid Build Coastguard Worker         // rule violation exists?
763*35238bceSAndroid Build Coastguard Worker         for (int ndx = 0; ndx < (int)m_errorStatuses.size(); ++ndx)
764*35238bceSAndroid Build Coastguard Worker         {
765*35238bceSAndroid Build Coastguard Worker             if (m_errorStatuses[ndx].errorCode == fboStatus)
766*35238bceSAndroid Build Coastguard Worker                 return true;
767*35238bceSAndroid Build Coastguard Worker         }
768*35238bceSAndroid Build Coastguard Worker         return false;
769*35238bceSAndroid Build Coastguard Worker     }
770*35238bceSAndroid Build Coastguard Worker }
771*35238bceSAndroid Build Coastguard Worker 
isFBOStatusRequired(glw::GLenum fboStatus) const772*35238bceSAndroid Build Coastguard Worker bool ValidStatusCodes::isFBOStatusRequired(glw::GLenum fboStatus) const
773*35238bceSAndroid Build Coastguard Worker {
774*35238bceSAndroid Build Coastguard Worker     if (fboStatus == GL_FRAMEBUFFER_COMPLETE)
775*35238bceSAndroid Build Coastguard Worker         return m_allowComplete && m_errorStatuses.empty();
776*35238bceSAndroid Build Coastguard Worker     else
777*35238bceSAndroid Build Coastguard Worker         // fboStatus is the only allowed error status and succeeding is forbidden
778*35238bceSAndroid Build Coastguard Worker         return !m_allowComplete && m_errorStatuses.size() == 1 && m_errorStatuses.front().errorCode == fboStatus;
779*35238bceSAndroid Build Coastguard Worker }
780*35238bceSAndroid Build Coastguard Worker 
isErrorCodeValid(glw::GLenum errorCode) const781*35238bceSAndroid Build Coastguard Worker bool ValidStatusCodes::isErrorCodeValid(glw::GLenum errorCode) const
782*35238bceSAndroid Build Coastguard Worker {
783*35238bceSAndroid Build Coastguard Worker     if (errorCode == GL_NO_ERROR)
784*35238bceSAndroid Build Coastguard Worker         return m_errorCodes.empty();
785*35238bceSAndroid Build Coastguard Worker     else
786*35238bceSAndroid Build Coastguard Worker     {
787*35238bceSAndroid Build Coastguard Worker         // rule violation exists?
788*35238bceSAndroid Build Coastguard Worker         for (int ndx = 0; ndx < (int)m_errorCodes.size(); ++ndx)
789*35238bceSAndroid Build Coastguard Worker         {
790*35238bceSAndroid Build Coastguard Worker             if (m_errorCodes[ndx].errorCode == errorCode)
791*35238bceSAndroid Build Coastguard Worker                 return true;
792*35238bceSAndroid Build Coastguard Worker         }
793*35238bceSAndroid Build Coastguard Worker         return false;
794*35238bceSAndroid Build Coastguard Worker     }
795*35238bceSAndroid Build Coastguard Worker }
796*35238bceSAndroid Build Coastguard Worker 
isErrorCodeRequired(glw::GLenum errorCode) const797*35238bceSAndroid Build Coastguard Worker bool ValidStatusCodes::isErrorCodeRequired(glw::GLenum errorCode) const
798*35238bceSAndroid Build Coastguard Worker {
799*35238bceSAndroid Build Coastguard Worker     if (m_errorCodes.empty() && errorCode == GL_NO_ERROR)
800*35238bceSAndroid Build Coastguard Worker         return true;
801*35238bceSAndroid Build Coastguard Worker     else
802*35238bceSAndroid Build Coastguard Worker         // only this error code listed
803*35238bceSAndroid Build Coastguard Worker         return m_errorCodes.size() == 1 && m_errorCodes.front().errorCode == errorCode;
804*35238bceSAndroid Build Coastguard Worker }
805*35238bceSAndroid Build Coastguard Worker 
addErrorCode(glw::GLenum error,const char * description)806*35238bceSAndroid Build Coastguard Worker void ValidStatusCodes::addErrorCode(glw::GLenum error, const char *description)
807*35238bceSAndroid Build Coastguard Worker {
808*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(isErrorCode(error));
809*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(error != GL_NO_ERROR);
810*35238bceSAndroid Build Coastguard Worker     addViolation(m_errorCodes, error, description);
811*35238bceSAndroid Build Coastguard Worker }
812*35238bceSAndroid Build Coastguard Worker 
addFBOErrorStatus(glw::GLenum status,const char * description)813*35238bceSAndroid Build Coastguard Worker void ValidStatusCodes::addFBOErrorStatus(glw::GLenum status, const char *description)
814*35238bceSAndroid Build Coastguard Worker {
815*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(isFramebufferStatus(status));
816*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(status != GL_FRAMEBUFFER_COMPLETE);
817*35238bceSAndroid Build Coastguard Worker     addViolation(m_errorStatuses, status, description);
818*35238bceSAndroid Build Coastguard Worker }
819*35238bceSAndroid Build Coastguard Worker 
setAllowComplete(bool b)820*35238bceSAndroid Build Coastguard Worker void ValidStatusCodes::setAllowComplete(bool b)
821*35238bceSAndroid Build Coastguard Worker {
822*35238bceSAndroid Build Coastguard Worker     m_allowComplete = b;
823*35238bceSAndroid Build Coastguard Worker }
824*35238bceSAndroid Build Coastguard Worker 
logLegalResults(tcu::TestLog & log) const825*35238bceSAndroid Build Coastguard Worker void ValidStatusCodes::logLegalResults(tcu::TestLog &log) const
826*35238bceSAndroid Build Coastguard Worker {
827*35238bceSAndroid Build Coastguard Worker     tcu::MessageBuilder msg(&log);
828*35238bceSAndroid Build Coastguard Worker     std::vector<std::string> validResults;
829*35238bceSAndroid Build Coastguard Worker 
830*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < (int)m_errorCodes.size(); ++ndx)
831*35238bceSAndroid Build Coastguard Worker         validResults.push_back(std::string(glu::getErrorName(m_errorCodes[ndx].errorCode)) +
832*35238bceSAndroid Build Coastguard Worker                                " (during FBO initialization)");
833*35238bceSAndroid Build Coastguard Worker 
834*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < (int)m_errorStatuses.size(); ++ndx)
835*35238bceSAndroid Build Coastguard Worker         validResults.push_back(glu::getFramebufferStatusName(m_errorStatuses[ndx].errorCode));
836*35238bceSAndroid Build Coastguard Worker 
837*35238bceSAndroid Build Coastguard Worker     if (m_allowComplete)
838*35238bceSAndroid Build Coastguard Worker         validResults.push_back("GL_FRAMEBUFFER_COMPLETE");
839*35238bceSAndroid Build Coastguard Worker 
840*35238bceSAndroid Build Coastguard Worker     msg << "Expected ";
841*35238bceSAndroid Build Coastguard Worker     if (validResults.size() > 1)
842*35238bceSAndroid Build Coastguard Worker         msg << "one of ";
843*35238bceSAndroid Build Coastguard Worker 
844*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < (int)validResults.size(); ++ndx)
845*35238bceSAndroid Build Coastguard Worker     {
846*35238bceSAndroid Build Coastguard Worker         const bool last         = ((ndx + 1) == (int)validResults.size());
847*35238bceSAndroid Build Coastguard Worker         const bool secondToLast = ((ndx + 2) == (int)validResults.size());
848*35238bceSAndroid Build Coastguard Worker 
849*35238bceSAndroid Build Coastguard Worker         msg << validResults[ndx];
850*35238bceSAndroid Build Coastguard Worker         if (!last)
851*35238bceSAndroid Build Coastguard Worker             msg << ((secondToLast) ? (" or ") : (", "));
852*35238bceSAndroid Build Coastguard Worker     }
853*35238bceSAndroid Build Coastguard Worker 
854*35238bceSAndroid Build Coastguard Worker     msg << "." << TestLog::EndMessage;
855*35238bceSAndroid Build Coastguard Worker }
856*35238bceSAndroid Build Coastguard Worker 
logRules(tcu::TestLog & log) const857*35238bceSAndroid Build Coastguard Worker void ValidStatusCodes::logRules(tcu::TestLog &log) const
858*35238bceSAndroid Build Coastguard Worker {
859*35238bceSAndroid Build Coastguard Worker     const tcu::ScopedLogSection section(log, "Rules", "Active rules");
860*35238bceSAndroid Build Coastguard Worker 
861*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < (int)m_errorCodes.size(); ++ndx)
862*35238bceSAndroid Build Coastguard Worker         logRule(log, glu::getErrorName(m_errorCodes[ndx].errorCode), m_errorCodes[ndx].rules);
863*35238bceSAndroid Build Coastguard Worker 
864*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < (int)m_errorStatuses.size(); ++ndx)
865*35238bceSAndroid Build Coastguard Worker         logRule(log, glu::getFramebufferStatusName(m_errorStatuses[ndx].errorCode), m_errorStatuses[ndx].rules);
866*35238bceSAndroid Build Coastguard Worker 
867*35238bceSAndroid Build Coastguard Worker     if (m_allowComplete)
868*35238bceSAndroid Build Coastguard Worker     {
869*35238bceSAndroid Build Coastguard Worker         std::set<std::string> defaultRule;
870*35238bceSAndroid Build Coastguard Worker         defaultRule.insert("FBO is complete");
871*35238bceSAndroid Build Coastguard Worker         logRule(log, "GL_FRAMEBUFFER_COMPLETE", defaultRule);
872*35238bceSAndroid Build Coastguard Worker     }
873*35238bceSAndroid Build Coastguard Worker }
874*35238bceSAndroid Build Coastguard Worker 
logRule(tcu::TestLog & log,const std::string & ruleName,const std::set<std::string> & rules) const875*35238bceSAndroid Build Coastguard Worker void ValidStatusCodes::logRule(tcu::TestLog &log, const std::string &ruleName, const std::set<std::string> &rules) const
876*35238bceSAndroid Build Coastguard Worker {
877*35238bceSAndroid Build Coastguard Worker     if (!rules.empty())
878*35238bceSAndroid Build Coastguard Worker     {
879*35238bceSAndroid Build Coastguard Worker         const tcu::ScopedLogSection section(log, ruleName, ruleName);
880*35238bceSAndroid Build Coastguard Worker         tcu::MessageBuilder msg(&log);
881*35238bceSAndroid Build Coastguard Worker 
882*35238bceSAndroid Build Coastguard Worker         msg << "Rules:\n";
883*35238bceSAndroid Build Coastguard Worker         for (std::set<std::string>::const_iterator it = rules.begin(); it != rules.end(); ++it)
884*35238bceSAndroid Build Coastguard Worker             msg << "\t * " << *it << "\n";
885*35238bceSAndroid Build Coastguard Worker         msg << TestLog::EndMessage;
886*35238bceSAndroid Build Coastguard Worker     }
887*35238bceSAndroid Build Coastguard Worker }
888*35238bceSAndroid Build Coastguard Worker 
addViolation(std::vector<RuleViolation> & dst,glw::GLenum code,const char * description) const889*35238bceSAndroid Build Coastguard Worker void ValidStatusCodes::addViolation(std::vector<RuleViolation> &dst, glw::GLenum code, const char *description) const
890*35238bceSAndroid Build Coastguard Worker {
891*35238bceSAndroid Build Coastguard Worker     // rule violation already exists?
892*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < (int)dst.size(); ++ndx)
893*35238bceSAndroid Build Coastguard Worker     {
894*35238bceSAndroid Build Coastguard Worker         if (dst[ndx].errorCode == code)
895*35238bceSAndroid Build Coastguard Worker         {
896*35238bceSAndroid Build Coastguard Worker             dst[ndx].rules.insert(std::string(description));
897*35238bceSAndroid Build Coastguard Worker             return;
898*35238bceSAndroid Build Coastguard Worker         }
899*35238bceSAndroid Build Coastguard Worker     }
900*35238bceSAndroid Build Coastguard Worker 
901*35238bceSAndroid Build Coastguard Worker     // new violation
902*35238bceSAndroid Build Coastguard Worker     {
903*35238bceSAndroid Build Coastguard Worker         RuleViolation violation;
904*35238bceSAndroid Build Coastguard Worker 
905*35238bceSAndroid Build Coastguard Worker         violation.errorCode = code;
906*35238bceSAndroid Build Coastguard Worker         violation.rules.insert(std::string(description));
907*35238bceSAndroid Build Coastguard Worker 
908*35238bceSAndroid Build Coastguard Worker         dst.push_back(violation);
909*35238bceSAndroid Build Coastguard Worker     }
910*35238bceSAndroid Build Coastguard Worker }
911*35238bceSAndroid Build Coastguard Worker 
FboBuilder(GLuint fbo,GLenum target,const glw::Functions & gl)912*35238bceSAndroid Build Coastguard Worker FboBuilder::FboBuilder(GLuint fbo, GLenum target, const glw::Functions &gl)
913*35238bceSAndroid Build Coastguard Worker     : m_error(GL_NO_ERROR)
914*35238bceSAndroid Build Coastguard Worker     , m_target(target)
915*35238bceSAndroid Build Coastguard Worker     , m_gl(gl)
916*35238bceSAndroid Build Coastguard Worker {
917*35238bceSAndroid Build Coastguard Worker     m_gl.bindFramebuffer(m_target, fbo);
918*35238bceSAndroid Build Coastguard Worker }
919*35238bceSAndroid Build Coastguard Worker 
~FboBuilder(void)920*35238bceSAndroid Build Coastguard Worker FboBuilder::~FboBuilder(void)
921*35238bceSAndroid Build Coastguard Worker {
922*35238bceSAndroid Build Coastguard Worker     for (TextureMap::const_iterator it = textures.begin(); it != textures.end(); it++)
923*35238bceSAndroid Build Coastguard Worker     {
924*35238bceSAndroid Build Coastguard Worker         glDelete(*it->second, it->first, m_gl);
925*35238bceSAndroid Build Coastguard Worker     }
926*35238bceSAndroid Build Coastguard Worker     for (RboMap::const_iterator it = rbos.begin(); it != rbos.end(); it++)
927*35238bceSAndroid Build Coastguard Worker     {
928*35238bceSAndroid Build Coastguard Worker         glDelete(*it->second, it->first, m_gl);
929*35238bceSAndroid Build Coastguard Worker     }
930*35238bceSAndroid Build Coastguard Worker     m_gl.bindFramebuffer(m_target, 0);
931*35238bceSAndroid Build Coastguard Worker     for (Configs::const_iterator it = m_configs.begin(); it != m_configs.end(); it++)
932*35238bceSAndroid Build Coastguard Worker     {
933*35238bceSAndroid Build Coastguard Worker         delete *it;
934*35238bceSAndroid Build Coastguard Worker     }
935*35238bceSAndroid Build Coastguard Worker }
936*35238bceSAndroid Build Coastguard Worker 
checkError(void)937*35238bceSAndroid Build Coastguard Worker void FboBuilder::checkError(void)
938*35238bceSAndroid Build Coastguard Worker {
939*35238bceSAndroid Build Coastguard Worker     const GLenum error = m_gl.getError();
940*35238bceSAndroid Build Coastguard Worker     if (error != GL_NO_ERROR && m_error == GL_NO_ERROR)
941*35238bceSAndroid Build Coastguard Worker         m_error = error;
942*35238bceSAndroid Build Coastguard Worker }
943*35238bceSAndroid Build Coastguard Worker 
glAttach(GLenum attPoint,const Attachment * att)944*35238bceSAndroid Build Coastguard Worker void FboBuilder::glAttach(GLenum attPoint, const Attachment *att)
945*35238bceSAndroid Build Coastguard Worker {
946*35238bceSAndroid Build Coastguard Worker     if (att == NULL)
947*35238bceSAndroid Build Coastguard Worker         m_gl.framebufferRenderbuffer(m_target, attPoint, GL_RENDERBUFFER, 0);
948*35238bceSAndroid Build Coastguard Worker     else
949*35238bceSAndroid Build Coastguard Worker         attachAttachment(*att, attPoint, m_gl);
950*35238bceSAndroid Build Coastguard Worker     checkError();
951*35238bceSAndroid Build Coastguard Worker     attach(attPoint, att);
952*35238bceSAndroid Build Coastguard Worker }
953*35238bceSAndroid Build Coastguard Worker 
glCreateTexture(const Texture & texCfg)954*35238bceSAndroid Build Coastguard Worker GLuint FboBuilder::glCreateTexture(const Texture &texCfg)
955*35238bceSAndroid Build Coastguard Worker {
956*35238bceSAndroid Build Coastguard Worker     const GLuint texName = glCreate(texCfg, m_gl);
957*35238bceSAndroid Build Coastguard Worker     checkError();
958*35238bceSAndroid Build Coastguard Worker     setTexture(texName, texCfg);
959*35238bceSAndroid Build Coastguard Worker     return texName;
960*35238bceSAndroid Build Coastguard Worker }
961*35238bceSAndroid Build Coastguard Worker 
glCreateRbo(const Renderbuffer & rbCfg)962*35238bceSAndroid Build Coastguard Worker GLuint FboBuilder::glCreateRbo(const Renderbuffer &rbCfg)
963*35238bceSAndroid Build Coastguard Worker {
964*35238bceSAndroid Build Coastguard Worker     const GLuint rbName = glCreate(rbCfg, m_gl);
965*35238bceSAndroid Build Coastguard Worker     checkError();
966*35238bceSAndroid Build Coastguard Worker     setRbo(rbName, rbCfg);
967*35238bceSAndroid Build Coastguard Worker     return rbName;
968*35238bceSAndroid Build Coastguard Worker }
969*35238bceSAndroid Build Coastguard Worker 
transferImageFormat(const ImageFormat & imgFormat)970*35238bceSAndroid Build Coastguard Worker TransferFormat transferImageFormat(const ImageFormat &imgFormat)
971*35238bceSAndroid Build Coastguard Worker {
972*35238bceSAndroid Build Coastguard Worker     if (imgFormat.unsizedType == GL_NONE)
973*35238bceSAndroid Build Coastguard Worker         return getTransferFormat(mapGLInternalFormat(imgFormat.format));
974*35238bceSAndroid Build Coastguard Worker     else
975*35238bceSAndroid Build Coastguard Worker         return TransferFormat(imgFormat.format, imgFormat.unsizedType);
976*35238bceSAndroid Build Coastguard Worker }
977*35238bceSAndroid Build Coastguard Worker 
978*35238bceSAndroid Build Coastguard Worker } // namespace FboUtil
979*35238bceSAndroid Build Coastguard Worker } // namespace gls
980*35238bceSAndroid Build Coastguard Worker } // namespace deqp
981