1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL (ES) Module
3 * -----------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Framebuffer completeness tests.
22 *//*--------------------------------------------------------------------*/
23
24 #include "es2fFboCompletenessTests.hpp"
25
26 #include "glsFboCompletenessTests.hpp"
27 #include "gluObjectWrapper.hpp"
28
29 using namespace glw;
30 using deqp::gls::Range;
31 using namespace deqp::gls::FboUtil;
32 using namespace deqp::gls::FboUtil::config;
33 namespace fboc = deqp::gls::fboc;
34 typedef tcu::TestCase::IterateResult IterateResult;
35
36 namespace deqp
37 {
38 namespace gles2
39 {
40 namespace Functional
41 {
42
43 static const FormatKey s_es2ColorRenderables[] = {
44 GL_RGBA4,
45 GL_RGB5_A1,
46 GL_RGB565,
47 };
48
49 // GLES2 does not strictly allow these, but this seems to be a bug in the
50 // specification. For now, let's assume the unsized formats corresponding to
51 // the color-renderable sized formats are allowed.
52 // See https://cvs.khronos.org/bugzilla/show_bug.cgi?id=7333
53
54 static const FormatKey s_es2UnsizedColorRenderables[] = {GLS_UNSIZED_FORMATKEY(GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4),
55 GLS_UNSIZED_FORMATKEY(GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1),
56 GLS_UNSIZED_FORMATKEY(GL_RGB, GL_UNSIGNED_SHORT_5_6_5)};
57
58 static const FormatKey s_es2DepthRenderables[] = {
59 GL_DEPTH_COMPONENT16,
60 };
61
62 static const FormatKey s_es2StencilRenderables[] = {
63 GL_STENCIL_INDEX8,
64 };
65
66 static const FormatEntry s_es2Formats[] = {
67 {COLOR_RENDERABLE | TEXTURE_VALID, GLS_ARRAY_RANGE(s_es2UnsizedColorRenderables)},
68 {REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID, GLS_ARRAY_RANGE(s_es2ColorRenderables)},
69 {REQUIRED_RENDERABLE | DEPTH_RENDERABLE | RENDERBUFFER_VALID, GLS_ARRAY_RANGE(s_es2DepthRenderables)},
70 {REQUIRED_RENDERABLE | STENCIL_RENDERABLE | RENDERBUFFER_VALID, GLS_ARRAY_RANGE(s_es2StencilRenderables)},
71 };
72
73 // We have here only the extensions that are redundant in vanilla GLES3. Those
74 // that are applicable both to GLES2 and GLES3 are in glsFboCompletenessTests.cpp.
75
76 // GL_OES_texture_float
77 static const FormatKey s_oesTextureFloatFormats[] = {
78 GLS_UNSIZED_FORMATKEY(GL_RGBA, GL_FLOAT),
79 GLS_UNSIZED_FORMATKEY(GL_RGB, GL_FLOAT),
80 };
81
82 // GL_OES_texture_half_float
83 static const FormatKey s_oesTextureHalfFloatFormats[] = {
84 GLS_UNSIZED_FORMATKEY(GL_RGBA, GL_HALF_FLOAT_OES),
85 GLS_UNSIZED_FORMATKEY(GL_RGB, GL_HALF_FLOAT_OES),
86 };
87
88 // GL_EXT_color_buffer_half_float
89 static const FormatKey s_extColorBufferHalfFloatUnsized[] = {
90 GLS_UNSIZED_FORMATKEY(GL_RGBA, GL_HALF_FLOAT_OES),
91 };
92
93 // GL_EXT_sRGB_write_control
94 static const FormatKey s_extSrgbWriteControlFormats[] = {GL_SRGB8_ALPHA8};
95
96 // DEQP_gles3_core_no_extension_features
97 static const FormatKey s_es3NoExtRboFormats[] = {
98 GL_RGB10_A2,
99 GL_SRGB8_ALPHA8,
100 };
101 static const FormatKey s_es3NoExtTextureFormats[] = {
102 GL_R16F, GL_RG16F, GL_RGB16F, GL_RGBA16F, GL_R11F_G11F_B10F,
103 };
104 static const FormatKey s_es3NoExtTextureColorRenderableFormats[] = {
105 GL_R8, GL_RG8, GL_RGB8, GL_RGBA4, GL_RGB5_A1, GL_RGBA8, GL_RGB10_A2, GL_RGB565, GL_SRGB8_ALPHA8,
106 };
107
108 // with ES3 core and GL_EXT_color_buffer_float
109 static const FormatKey s_es3NoExtExtColorBufferFloatFormats[] = {
110 // \note Only the GLES2+exts subset of formats
111 GL_R11F_G11F_B10F,
112 GL_RGBA16F,
113 GL_RG16F,
114 GL_R16F,
115 };
116
117 // with ES3 core with OES_texture_stencil8
118 static const FormatKey s_es3NoExtOesTextureStencil8Formats[] = {
119 GL_STENCIL_INDEX8,
120 };
121
122 // DEQP_gles3_core_changed_features
123 static const FormatKey s_es3NoExtDepthRenderable[] = {
124 GL_DEPTH_COMPONENT16,
125 GL_DEPTH_COMPONENT24,
126 GL_DEPTH24_STENCIL8,
127 };
128
129 static const FormatKey s_es3NoExtStencilRenderable[] = {
130 GL_DEPTH24_STENCIL8,
131 };
132
133 static const FormatExtEntry s_es2ExtFormats[] = {
134 // The extension does not specify these to be color-renderable.
135 {"GL_OES_texture_float", (uint32_t)TEXTURE_VALID, GLS_ARRAY_RANGE(s_oesTextureFloatFormats)},
136 {"GL_OES_texture_half_float", (uint32_t)TEXTURE_VALID, GLS_ARRAY_RANGE(s_oesTextureHalfFloatFormats)},
137 // However GL_EXT_color_buffer_half_float does say explicitly
138 // that the RGBA variant should be renderable.
139 {"GL_OES_texture_half_float GL_EXT_color_buffer_half_float", (uint32_t)(REQUIRED_RENDERABLE | COLOR_RENDERABLE),
140 GLS_ARRAY_RANGE(s_extColorBufferHalfFloatUnsized)},
141
142 // GL_EXT_sRGB_write_control makes SRGB8_ALPHA8 color-renderable
143 {"GL_EXT_sRGB_write_control",
144 (uint32_t)(REQUIRED_RENDERABLE | TEXTURE_VALID | COLOR_RENDERABLE | RENDERBUFFER_VALID),
145 GLS_ARRAY_RANGE(s_extSrgbWriteControlFormats)},
146
147 // Since GLES3 is "backwards compatible" to GLES2, we might actually be running on a GLES3
148 // context. Since GLES3 added some features to core with no corresponding GLES2 extension,
149 // some tests might produce wrong results (since they are using rules of GLES2 & extensions)
150 //
151 // To avoid this, require new features of GLES3 that have no matching GLES2 extension if
152 // context is GLES3. This can be done with a DEQP_* extensions.
153 //
154 // \note Not all feature changes are listed here but only those that alter GLES2 subset of
155 // the formats
156 {"DEQP_gles3_core_compatible", (uint32_t)(REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID),
157 GLS_ARRAY_RANGE(s_es3NoExtRboFormats)},
158 {"DEQP_gles3_core_compatible", (uint32_t)TEXTURE_VALID, GLS_ARRAY_RANGE(s_es3NoExtTextureFormats)},
159 {"DEQP_gles3_core_compatible",
160 (uint32_t)(REQUIRED_RENDERABLE | TEXTURE_VALID | COLOR_RENDERABLE | RENDERBUFFER_VALID),
161 GLS_ARRAY_RANGE(s_es3NoExtTextureColorRenderableFormats)},
162 {"DEQP_gles3_core_compatible GL_EXT_color_buffer_float",
163 (uint32_t)(REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID),
164 GLS_ARRAY_RANGE(s_es3NoExtExtColorBufferFloatFormats)},
165 {"DEQP_gles3_core_compatible GL_OES_texture_stencil8",
166 (uint32_t)(REQUIRED_RENDERABLE | STENCIL_RENDERABLE | TEXTURE_VALID),
167 GLS_ARRAY_RANGE(s_es3NoExtOesTextureStencil8Formats)},
168 {"DEQP_gles3_core_compatible GL_OES_texture_half_float GL_EXT_color_buffer_half_float",
169 (uint32_t)(REQUIRED_RENDERABLE | COLOR_RENDERABLE), GLS_ARRAY_RANGE(s_oesTextureHalfFloatFormats)},
170 {"DEQP_gles3_core_compatible",
171 (uint32_t)(REQUIRED_RENDERABLE | DEPTH_RENDERABLE | RENDERBUFFER_VALID | TEXTURE_VALID),
172 GLS_ARRAY_RANGE(s_es3NoExtDepthRenderable)},
173 {"DEQP_gles3_core_compatible",
174 (uint32_t)(REQUIRED_RENDERABLE | STENCIL_RENDERABLE | RENDERBUFFER_VALID | TEXTURE_VALID),
175 GLS_ARRAY_RANGE(s_es3NoExtStencilRenderable)},
176 };
177
178 class ES2Checker : public Checker
179 {
180 public:
181 ES2Checker(const glu::RenderContext &ctx, const FormatDB &formats);
182 void check(GLenum attPoint, const Attachment &att, const Image *image);
183
184 private:
185 GLsizei m_width; //< The common width of images
186 GLsizei m_height; //< The common height of images
187 };
188
ES2Checker(const glu::RenderContext & ctx,const FormatDB & formats)189 ES2Checker::ES2Checker(const glu::RenderContext &ctx, const FormatDB &formats)
190 : Checker(ctx, formats)
191 , m_width(-1)
192 , m_height(-1)
193 {
194 }
195
check(GLenum attPoint,const Attachment & att,const Image * image)196 void ES2Checker::check(GLenum attPoint, const Attachment &att, const Image *image)
197 {
198 DE_UNREF(attPoint);
199 DE_UNREF(att);
200 // GLES2: "All attached images have the same width and height."
201 if (m_width == -1)
202 {
203 m_width = image->width;
204 m_height = image->height;
205 }
206 else if (image->width != m_width || image->height != m_height)
207 {
208 // Since GLES3 is "backwards compatible" to GLES2, we might actually be running
209 // on a GLES3 context. On GLES3, FRAMEBUFFER_INCOMPLETE_DIMENSIONS is not generated
210 // if attachments have different sizes.
211 if (!gls::FboUtil::checkExtensionSupport(m_renderCtx, "DEQP_gles3_core_compatible"))
212 {
213 // running on GLES2
214 addFBOStatus(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS, "Sizes of attachments differ");
215 }
216 }
217 // GLES2, 4.4.5: "some implementations may not support rendering to
218 // particular combinations of internal formats. If the combination of
219 // formats of the images attached to a framebuffer object are not
220 // supported by the implementation, then the framebuffer is not complete
221 // under the clause labeled FRAMEBUFFER_UNSUPPORTED."
222 //
223 // Hence it is _always_ allowed to report FRAMEBUFFER_UNSUPPORTED.
224 addPotentialFBOStatus(GL_FRAMEBUFFER_UNSUPPORTED, "Particular format combinations need not to be supported");
225 }
226
227 struct FormatCombination
228 {
229 GLenum colorKind;
230 ImageFormat colorFmt;
231 GLenum depthKind;
232 ImageFormat depthFmt;
233 GLenum stencilKind;
234 ImageFormat stencilFmt;
235 };
236
237 class SupportedCombinationTest : public fboc::TestBase
238 {
239 public:
SupportedCombinationTest(fboc::Context & ctx,const char * name,const char * desc)240 SupportedCombinationTest(fboc::Context &ctx, const char *name, const char *desc) : TestBase(ctx, name, desc)
241 {
242 }
243
244 IterateResult iterate(void);
245 bool tryCombination(const FormatCombination &comb);
246 GLenum formatKind(ImageFormat fmt);
247 };
248
tryCombination(const FormatCombination & comb)249 bool SupportedCombinationTest::tryCombination(const FormatCombination &comb)
250 {
251 glu::Framebuffer fbo(m_ctx.getRenderContext());
252 FboBuilder builder(*fbo, GL_FRAMEBUFFER, fboc::gl(*this));
253
254 attachTargetToNew(GL_COLOR_ATTACHMENT0, comb.colorKind, comb.colorFmt, 64, 64, builder);
255 attachTargetToNew(GL_DEPTH_ATTACHMENT, comb.depthKind, comb.depthFmt, 64, 64, builder);
256 attachTargetToNew(GL_STENCIL_ATTACHMENT, comb.stencilKind, comb.stencilFmt, 64, 64, builder);
257
258 const GLenum glStatus = fboc::gl(*this).checkFramebufferStatus(GL_FRAMEBUFFER);
259
260 return (glStatus == GL_FRAMEBUFFER_COMPLETE);
261 }
262
formatKind(ImageFormat fmt)263 GLenum SupportedCombinationTest::formatKind(ImageFormat fmt)
264 {
265 if (fmt.format == GL_NONE)
266 return GL_NONE;
267
268 const FormatFlags flags = m_ctx.getCoreFormats().getFormatInfo(fmt);
269 const bool rbo = (flags & RENDERBUFFER_VALID) != 0;
270 // exactly one of renderbuffer and texture is supported by vanilla GLES2 formats
271 DE_ASSERT(rbo != ((flags & TEXTURE_VALID) != 0));
272
273 return rbo ? GL_RENDERBUFFER : GL_TEXTURE;
274 }
275
iterate(void)276 IterateResult SupportedCombinationTest::iterate(void)
277 {
278 const FormatDB &db = m_ctx.getCoreFormats();
279 const ImageFormat none = ImageFormat::none();
280 Formats colorFmts = db.getFormats(COLOR_RENDERABLE);
281 Formats depthFmts = db.getFormats(DEPTH_RENDERABLE);
282 Formats stencilFmts = db.getFormats(STENCIL_RENDERABLE);
283 FormatCombination comb;
284 bool succ = false;
285
286 colorFmts.insert(none);
287 depthFmts.insert(none);
288 stencilFmts.insert(none);
289
290 for (Formats::const_iterator col = colorFmts.begin(); col != colorFmts.end(); col++)
291 {
292 comb.colorFmt = *col;
293 comb.colorKind = formatKind(*col);
294 for (Formats::const_iterator dep = depthFmts.begin(); dep != depthFmts.end(); dep++)
295 {
296 comb.depthFmt = *dep;
297 comb.depthKind = formatKind(*dep);
298 for (Formats::const_iterator stc = stencilFmts.begin(); stc != stencilFmts.end(); stc++)
299 {
300 comb.stencilFmt = *stc;
301 comb.stencilKind = formatKind(*stc);
302 succ = tryCombination(comb);
303 if (succ)
304 break;
305 }
306 }
307 }
308
309 if (succ)
310 pass();
311 else
312 fail("No supported format combination found");
313
314 return STOP;
315 }
316
317 class ES2CheckerFactory : public CheckerFactory
318 {
319 public:
createChecker(const glu::RenderContext & ctx,const FormatDB & formats)320 Checker *createChecker(const glu::RenderContext &ctx, const FormatDB &formats)
321 {
322 return new ES2Checker(ctx, formats);
323 }
324 };
325
326 class TestGroup : public TestCaseGroup
327 {
328 public:
329 TestGroup(Context &ctx);
330 void init(void);
331
332 private:
333 ES2CheckerFactory m_checkerFactory;
334 fboc::Context m_fboc;
335 };
336
TestGroup(Context & ctx)337 TestGroup::TestGroup(Context &ctx)
338 : TestCaseGroup(ctx, "completeness", "Completeness tests")
339 , m_checkerFactory()
340 , m_fboc(ctx.getTestContext(), ctx.getRenderContext(), m_checkerFactory)
341 {
342 const FormatEntries stdRange = GLS_ARRAY_RANGE(s_es2Formats);
343 const FormatExtEntries extRange = GLS_ARRAY_RANGE(s_es2ExtFormats);
344
345 m_fboc.addFormats(stdRange);
346 m_fboc.addExtFormats(extRange);
347 m_fboc.setHaveMulticolorAtts(ctx.getContextInfo().isExtensionSupported("GL_NV_fbo_color_attachments"));
348 }
349
init(void)350 void TestGroup::init(void)
351 {
352 tcu::TestCaseGroup *attCombTests = m_fboc.createAttachmentTests();
353 addChild(m_fboc.createRenderableTests());
354 attCombTests->addChild(new SupportedCombinationTest(m_fboc, "exists_supported",
355 "Test for existence of a supported combination of formats"));
356 addChild(attCombTests);
357 addChild(m_fboc.createSizeTests());
358 }
359
createFboCompletenessTests(Context & context)360 tcu::TestCaseGroup *createFboCompletenessTests(Context &context)
361 {
362 return new TestGroup(context);
363 }
364
365 } // namespace Functional
366 } // namespace gles2
367 } // namespace deqp
368