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