1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.0 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 Object Tests.
22 *//*--------------------------------------------------------------------*/
23
24 #include "es3fFboRenderTest.hpp"
25 #include "sglrContextUtil.hpp"
26 #include "sglrGLContext.hpp"
27 #include "sglrReferenceContext.hpp"
28 #include "es3fFboTestUtil.hpp"
29 #include "tcuSurface.hpp"
30 #include "tcuImageCompare.hpp"
31 #include "tcuTextureUtil.hpp"
32 #include "tcuVectorUtil.hpp"
33 #include "tcuRenderTarget.hpp"
34 #include "gluPixelTransfer.hpp"
35 #include "gluTextureUtil.hpp"
36 #include "gluStrUtil.hpp"
37 #include "deRandom.h"
38 #include "deString.h"
39 #include "glwDefs.hpp"
40 #include "glwEnums.hpp"
41
42 #include <sstream>
43
44 using std::vector;
45 using std::string;
46 using tcu::TestLog;
47 using tcu::Vec2;
48 using tcu::Vec3;
49 using tcu::Vec4;
50 using tcu::IVec2;
51 using tcu::IVec3;
52 using tcu::IVec4;
53 using tcu::RGBA;
54 using tcu::Surface;
55
56 namespace deqp
57 {
58 namespace gles3
59 {
60 namespace Functional
61 {
62
63 using glw::GLenum;
64 using namespace FboTestUtil;
65
66 class FboConfig
67 {
68 public:
FboConfig(deUint32 buffers_,deUint32 colorType_,deUint32 colorFormat_,deUint32 depthStencilType_,deUint32 depthStencilFormat_,int width_=0,int height_=0,int samples_=0)69 FboConfig (deUint32 buffers_, deUint32 colorType_, deUint32 colorFormat_, deUint32 depthStencilType_, deUint32 depthStencilFormat_, int width_ = 0, int height_ = 0, int samples_ = 0)
70 : buffers (buffers_)
71 , colorType (colorType_)
72 , colorFormat (colorFormat_)
73 , depthStencilType (depthStencilType_)
74 , depthStencilFormat (depthStencilFormat_)
75 , width (width_)
76 , height (height_)
77 , samples (samples_)
78 {
79 }
80
FboConfig(void)81 FboConfig (void)
82 : buffers (0)
83 , colorType (GL_NONE)
84 , colorFormat (GL_NONE)
85 , depthStencilType (GL_NONE)
86 , depthStencilFormat (GL_NONE)
87 , width (0)
88 , height (0)
89 , samples (0)
90 {
91 }
92
93 std::string getName (void) const;
94
95 deUint32 buffers; //!< Buffer bit mask (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|...)
96
97 GLenum colorType; //!< GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP, GL_RENDERBUFFER
98 GLenum colorFormat; //!< Internal format for color buffer texture or renderbuffer
99
100 GLenum depthStencilType;
101 GLenum depthStencilFormat;
102
103 int width;
104 int height;
105 int samples;
106 };
107
getTypeName(GLenum type)108 static const char* getTypeName (GLenum type)
109 {
110 switch (type)
111 {
112 case GL_TEXTURE_2D: return "tex2d";
113 case GL_RENDERBUFFER: return "rbo";
114 default:
115 TCU_FAIL("Unknown type");
116 }
117 }
118
getName(void) const119 std::string FboConfig::getName (void) const
120 {
121 std::ostringstream name;
122
123 DE_ASSERT(buffers & GL_COLOR_BUFFER_BIT);
124 name << getTypeName(colorType) << "_" << getFormatName(colorFormat);
125
126 if (buffers & GL_DEPTH_BUFFER_BIT)
127 name << "_depth";
128 if (buffers & GL_STENCIL_BUFFER_BIT)
129 name << "_stencil";
130
131 if (buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT))
132 name << "_" << getTypeName(depthStencilType) << "_" << getFormatName(depthStencilFormat);
133
134 return name.str();
135 }
136
137 class Framebuffer
138 {
139 public:
140 Framebuffer (sglr::Context& context, const FboConfig& config, int width, int height, deUint32 fbo = 0, deUint32 colorBuffer = 0, deUint32 depthStencilBuffer = 0);
141 ~Framebuffer (void);
142
getConfig(void) const143 const FboConfig& getConfig (void) const { return m_config; }
getFramebuffer(void) const144 deUint32 getFramebuffer (void) const { return m_framebuffer; }
getColorBuffer(void) const145 deUint32 getColorBuffer (void) const { return m_colorBuffer; }
getDepthStencilBuffer(void) const146 deUint32 getDepthStencilBuffer (void) const { return m_depthStencilBuffer; }
147
148 void checkCompleteness (void);
149
150 private:
151 deUint32 createTex2D (deUint32 name, GLenum format, int width, int height);
152 deUint32 createRbo (deUint32 name, GLenum format, int width, int height);
153 void destroyBuffer (deUint32 name, GLenum type);
154
155 FboConfig m_config;
156 sglr::Context& m_context;
157 deUint32 m_framebuffer;
158 deUint32 m_colorBuffer;
159 deUint32 m_depthStencilBuffer;
160 };
161
getEnablingExtensions(deUint32 format)162 static std::vector<std::string> getEnablingExtensions (deUint32 format)
163 {
164 std::vector<std::string> out;
165
166 switch (format)
167 {
168 case GL_RGB16F:
169 out.push_back("GL_EXT_color_buffer_half_float");
170 break;
171
172 case GL_RGBA16F:
173 case GL_RG16F:
174 case GL_R16F:
175 out.push_back("GL_EXT_color_buffer_half_float");
176 // Fallthrough
177
178 case GL_RGBA32F:
179 case GL_RGB32F:
180 case GL_R11F_G11F_B10F:
181 case GL_RG32F:
182 case GL_R32F:
183 out.push_back("GL_EXT_color_buffer_float");
184 break;
185
186 default:
187 break;
188 }
189
190 return out;
191 }
192
isExtensionSupported(sglr::Context & context,const char * name)193 static bool isExtensionSupported (sglr::Context& context, const char* name)
194 {
195 std::istringstream extensions(context.getString(GL_EXTENSIONS));
196 std::string extension;
197
198 while (std::getline(extensions, extension, ' '))
199 {
200 if (extension == name)
201 return true;
202 }
203
204 return false;
205 }
206
isAnyExtensionSupported(sglr::Context & context,const std::vector<std::string> & requiredExts)207 static bool isAnyExtensionSupported (sglr::Context& context, const std::vector<std::string>& requiredExts)
208 {
209 if (requiredExts.empty())
210 return true;
211
212 for (std::vector<std::string>::const_iterator iter = requiredExts.begin(); iter != requiredExts.end(); iter++)
213 {
214 const std::string& extension = *iter;
215
216 if (isExtensionSupported(context, extension.c_str()))
217 return true;
218 }
219
220 return false;
221 }
222
223 template<typename T>
join(const std::vector<T> & list,const std::string & sep)224 static std::string join (const std::vector<T>& list, const std::string& sep)
225 {
226 std::ostringstream out;
227
228 for (typename std::vector<T>::const_iterator iter = list.begin(); iter != list.end(); iter++)
229 {
230 if (iter != list.begin())
231 out << sep;
232 out << *iter;
233 }
234
235 return out.str();
236 }
237
checkColorFormatSupport(sglr::Context & context,deUint32 sizedFormat)238 static void checkColorFormatSupport (sglr::Context& context, deUint32 sizedFormat)
239 {
240 const std::vector<std::string> requiredExts = getEnablingExtensions(sizedFormat);
241
242 if (!isAnyExtensionSupported(context, requiredExts))
243 {
244 std::string errMsg = "Format not supported, requires "
245 + ((requiredExts.size() == 1) ? requiredExts[0] : " one of the following: " + join(requiredExts, ", "));
246
247 throw tcu::NotSupportedError(errMsg);
248 }
249 }
250
Framebuffer(sglr::Context & context,const FboConfig & config,int width,int height,deUint32 fbo,deUint32 colorBufferName,deUint32 depthStencilBufferName)251 Framebuffer::Framebuffer (sglr::Context& context, const FboConfig& config, int width, int height, deUint32 fbo, deUint32 colorBufferName, deUint32 depthStencilBufferName)
252 : m_config (config)
253 , m_context (context)
254 , m_framebuffer (fbo)
255 , m_colorBuffer (0)
256 , m_depthStencilBuffer (0)
257 {
258 // Verify that color format is supported
259 checkColorFormatSupport(context, config.colorFormat);
260
261 if (m_framebuffer == 0)
262 context.genFramebuffers(1, &m_framebuffer);
263 context.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
264
265 if (m_config.buffers & (GL_COLOR_BUFFER_BIT))
266 {
267 switch (m_config.colorType)
268 {
269 case GL_TEXTURE_2D:
270 m_colorBuffer = createTex2D(colorBufferName, m_config.colorFormat, width, height);
271 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorBuffer, 0);
272 break;
273
274 case GL_RENDERBUFFER:
275 m_colorBuffer = createRbo(colorBufferName, m_config.colorFormat, width, height);
276 context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_colorBuffer);
277 break;
278
279 default:
280 TCU_FAIL("Unsupported type");
281 }
282 }
283
284 if (m_config.buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT))
285 {
286 switch (m_config.depthStencilType)
287 {
288 case GL_TEXTURE_2D: m_depthStencilBuffer = createTex2D(depthStencilBufferName, m_config.depthStencilFormat, width, height); break;
289 case GL_RENDERBUFFER: m_depthStencilBuffer = createRbo(depthStencilBufferName, m_config.depthStencilFormat, width, height); break;
290 default:
291 TCU_FAIL("Unsupported type");
292 }
293 }
294
295 for (int ndx = 0; ndx < 2; ndx++)
296 {
297 deUint32 bit = ndx ? GL_STENCIL_BUFFER_BIT : GL_DEPTH_BUFFER_BIT;
298 deUint32 point = ndx ? GL_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT;
299
300 if ((m_config.buffers & bit) == 0)
301 continue; /* Not used. */
302
303 switch (m_config.depthStencilType)
304 {
305 case GL_TEXTURE_2D: context.framebufferTexture2D(GL_FRAMEBUFFER, point, GL_TEXTURE_2D, m_depthStencilBuffer, 0); break;
306 case GL_RENDERBUFFER: context.framebufferRenderbuffer(GL_FRAMEBUFFER, point, GL_RENDERBUFFER, m_depthStencilBuffer); break;
307 default:
308 DE_ASSERT(false);
309 }
310 }
311
312 GLenum err = m_context.getError();
313 if (err != GL_NO_ERROR)
314 throw glu::Error(err, glu::getErrorStr(err).toString().c_str(), "", __FILE__, __LINE__);
315
316 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
317 }
318
~Framebuffer(void)319 Framebuffer::~Framebuffer (void)
320 {
321 m_context.deleteFramebuffers(1, &m_framebuffer);
322 destroyBuffer(m_colorBuffer, m_config.colorType);
323 destroyBuffer(m_depthStencilBuffer, m_config.depthStencilType);
324 }
325
checkCompleteness(void)326 void Framebuffer::checkCompleteness (void)
327 {
328 m_context.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
329 GLenum status = m_context.checkFramebufferStatus(GL_FRAMEBUFFER);
330 m_context.bindFramebuffer(GL_FRAMEBUFFER, 0);
331 if (status != GL_FRAMEBUFFER_COMPLETE)
332 throw FboIncompleteException(status, __FILE__, __LINE__);
333 }
334
createTex2D(deUint32 name,GLenum format,int width,int height)335 deUint32 Framebuffer::createTex2D (deUint32 name, GLenum format, int width, int height)
336 {
337 if (name == 0)
338 m_context.genTextures(1, &name);
339
340 m_context.bindTexture(GL_TEXTURE_2D, name);
341 m_context.texImage2D(GL_TEXTURE_2D, 0, format, width, height);
342
343 if (!deIsPowerOfTwo32(width) || !deIsPowerOfTwo32(height))
344 {
345 // Set wrap mode to clamp for NPOT FBOs
346 m_context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
347 m_context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
348 }
349
350 m_context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
351 m_context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
352
353 return name;
354 }
355
createRbo(deUint32 name,GLenum format,int width,int height)356 deUint32 Framebuffer::createRbo (deUint32 name, GLenum format, int width, int height)
357 {
358 if (name == 0)
359 m_context.genRenderbuffers(1, &name);
360
361 m_context.bindRenderbuffer(GL_RENDERBUFFER, name);
362 m_context.renderbufferStorage(GL_RENDERBUFFER, format, width, height);
363
364 return name;
365 }
366
destroyBuffer(deUint32 name,GLenum type)367 void Framebuffer::destroyBuffer (deUint32 name, GLenum type)
368 {
369 if (type == GL_TEXTURE_2D || type == GL_TEXTURE_CUBE_MAP)
370 m_context.deleteTextures(1, &name);
371 else if (type == GL_RENDERBUFFER)
372 m_context.deleteRenderbuffers(1, &name);
373 else
374 DE_ASSERT(type == GL_NONE);
375 }
376
createMetaballsTex2D(sglr::Context & context,deUint32 name,GLenum format,GLenum dataType,int width,int height)377 static void createMetaballsTex2D (sglr::Context& context, deUint32 name, GLenum format, GLenum dataType, int width, int height)
378 {
379 tcu::TextureFormat texFormat = glu::mapGLTransferFormat(format, dataType);
380 tcu::TextureLevel level (texFormat, width, height);
381
382 tcu::fillWithMetaballs(level.getAccess(), 5, name ^ width ^ height);
383
384 context.bindTexture(GL_TEXTURE_2D, name);
385 context.texImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, dataType, level.getAccess().getDataPtr());
386 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
387 }
388
createQuadsTex2D(sglr::Context & context,deUint32 name,GLenum format,GLenum dataType,int width,int height)389 static void createQuadsTex2D (sglr::Context& context, deUint32 name, GLenum format, GLenum dataType, int width, int height)
390 {
391 tcu::TextureFormat texFormat = glu::mapGLTransferFormat(format, dataType);
392 tcu::TextureLevel level (texFormat, width, height);
393
394 tcu::fillWithRGBAQuads(level.getAccess());
395
396 context.bindTexture(GL_TEXTURE_2D, name);
397 context.texImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, dataType, level.getAccess().getDataPtr());
398 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
399 }
400
401 class FboRenderCase : public TestCase
402 {
403 public:
404 FboRenderCase (Context& context, const char* name, const char* description, const FboConfig& config);
~FboRenderCase(void)405 virtual ~FboRenderCase (void) {}
406
407 virtual IterateResult iterate (void);
408 virtual void render (sglr::Context& fboContext, Surface& dst) = DE_NULL;
409
410 bool compare (const tcu::Surface& reference, const tcu::Surface& result);
411
412 protected:
413 const FboConfig m_config;
414 };
415
FboRenderCase(Context & context,const char * name,const char * description,const FboConfig & config)416 FboRenderCase::FboRenderCase (Context& context, const char* name, const char* description, const FboConfig& config)
417 : TestCase (context, name, description)
418 , m_config (config)
419 {
420 }
421
iterate(void)422 TestCase::IterateResult FboRenderCase::iterate (void)
423 {
424 tcu::Vec4 clearColor = tcu::Vec4(0.125f, 0.25f, 0.5f, 1.0f);
425 glu::RenderContext& renderCtx = m_context.getRenderContext();
426 const tcu::RenderTarget& renderTarget = renderCtx.getRenderTarget();
427 tcu::TestLog& log = m_testCtx.getLog();
428 const char* failReason = DE_NULL;
429
430 // Position & size for context
431 deRandom rnd;
432 deRandom_init(&rnd, deStringHash(getName()));
433
434 int width = deMin32(renderTarget.getWidth(), 128);
435 int height = deMin32(renderTarget.getHeight(), 128);
436 int xMax = renderTarget.getWidth()-width+1;
437 int yMax = renderTarget.getHeight()-height+1;
438 int x = deRandom_getUint32(&rnd) % xMax;
439 int y = deRandom_getUint32(&rnd) % yMax;
440
441 tcu::Surface gles3Frame (width, height);
442 tcu::Surface refFrame (width, height);
443 GLenum gles3Error;
444 GLenum refError;
445
446 // Render using GLES3
447 try
448 {
449 sglr::GLContext context(renderCtx, log, sglr::GLCONTEXT_LOG_CALLS, tcu::IVec4(x, y, width, height));
450
451 context.clearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
452 context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
453
454 render(context, gles3Frame); // Call actual render func
455 gles3Error = context.getError();
456 }
457 catch (const FboIncompleteException& e)
458 {
459 if (e.getReason() == GL_FRAMEBUFFER_UNSUPPORTED)
460 {
461 // Mark test case as unsupported
462 log << e;
463 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported");
464 return STOP;
465 }
466 else
467 throw; // Propagate error
468 }
469
470 // Render reference image
471 {
472 sglr::ReferenceContextBuffers buffers (tcu::PixelFormat(8,8,8,renderTarget.getPixelFormat().alphaBits?8:0), renderTarget.getDepthBits(), renderTarget.getStencilBits(), width, height);
473 sglr::ReferenceContext context (sglr::ReferenceContextLimits(renderCtx), buffers.getColorbuffer(), buffers.getDepthbuffer(), buffers.getStencilbuffer());
474
475 context.clearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
476 context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
477
478 render(context, refFrame);
479 refError = context.getError();
480 }
481
482 // Compare error codes
483 bool errorCodesOk = (gles3Error == refError);
484
485 if (!errorCodesOk)
486 {
487 log << tcu::TestLog::Message << "Error code mismatch: got " << glu::getErrorStr(gles3Error) << ", expected " << glu::getErrorStr(refError) << tcu::TestLog::EndMessage;
488 failReason = "Got unexpected error";
489 }
490
491 // Compare images
492 bool imagesOk = compare(refFrame, gles3Frame);
493
494 if (!imagesOk && !failReason)
495 failReason = "Image comparison failed";
496
497 // Store test result
498 bool isOk = errorCodesOk && imagesOk;
499 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
500 isOk ? "Pass" : failReason);
501
502 return STOP;
503 }
504
compare(const tcu::Surface & reference,const tcu::Surface & result)505 bool FboRenderCase::compare (const tcu::Surface& reference, const tcu::Surface& result)
506 {
507 const tcu::RGBA threshold (tcu::max(getFormatThreshold(m_config.colorFormat), tcu::RGBA(12, 12, 12, 12)));
508
509 return tcu::bilinearCompare(m_testCtx.getLog(), "ComparisonResult", "Image comparison result", reference.getAccess(), result.getAccess(), threshold, tcu::COMPARE_LOG_RESULT);
510 }
511
512 namespace FboCases
513 {
514
515 class StencilClearsTest : public FboRenderCase
516 {
517 public:
518 StencilClearsTest (Context& context, const FboConfig& config);
~StencilClearsTest(void)519 virtual ~StencilClearsTest (void) {}
520
521 void render (sglr::Context& context, Surface& dst);
522 };
523
StencilClearsTest(Context & context,const FboConfig & config)524 StencilClearsTest::StencilClearsTest (Context& context, const FboConfig& config)
525 : FboRenderCase (context, config.getName().c_str(), "Stencil clears", config)
526 {
527 }
528
render(sglr::Context & context,Surface & dst)529 void StencilClearsTest::render (sglr::Context& context, Surface& dst)
530 {
531 tcu::TextureFormat colorFormat = glu::mapGLInternalFormat(m_config.colorFormat);
532 glu::DataType fboSamplerType = glu::getSampler2DType(colorFormat);
533 glu::DataType fboOutputType = getFragmentOutputType(colorFormat);
534 tcu::TextureFormatInfo fboRangeInfo = tcu::getTextureFormatInfo(colorFormat);
535 Vec4 fboOutScale = fboRangeInfo.valueMax - fboRangeInfo.valueMin;
536 Vec4 fboOutBias = fboRangeInfo.valueMin;
537
538 Texture2DShader texToFboShader (DataTypes() << glu::TYPE_SAMPLER_2D, fboOutputType);
539 Texture2DShader texFromFboShader (DataTypes() << fboSamplerType, glu::TYPE_FLOAT_VEC4);
540
541 deUint32 texToFboShaderID = context.createProgram(&texToFboShader);
542 deUint32 texFromFboShaderID = context.createProgram(&texFromFboShader);
543
544 deUint32 metaballsTex = 1;
545 deUint32 quadsTex = 2;
546 int width = 128;
547 int height = 128;
548
549 texToFboShader.setOutScaleBias(fboOutScale, fboOutBias);
550 texFromFboShader.setTexScaleBias(0, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias);
551
552 createQuadsTex2D(context, quadsTex, GL_RGBA, GL_UNSIGNED_BYTE, width, height);
553 createMetaballsTex2D(context, metaballsTex, GL_RGBA, GL_UNSIGNED_BYTE, width, height);
554
555 Framebuffer fbo(context, m_config, width, height);
556 fbo.checkCompleteness();
557
558 // Bind framebuffer and clear
559 context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
560 context.viewport(0, 0, width, height);
561 context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
562 context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
563
564 // Do stencil clears
565 context.enable(GL_SCISSOR_TEST);
566 context.scissor(10, 16, 32, 120);
567 context.clearStencil(1);
568 context.clear(GL_STENCIL_BUFFER_BIT);
569 context.scissor(16, 32, 100, 64);
570 context.clearStencil(2);
571 context.clear(GL_STENCIL_BUFFER_BIT);
572 context.disable(GL_SCISSOR_TEST);
573
574 // Draw 2 textures with stecil tests
575 context.enable(GL_STENCIL_TEST);
576
577 context.bindTexture(GL_TEXTURE_2D, quadsTex);
578 context.stencilFunc(GL_EQUAL, 1, 0xffu);
579
580 texToFboShader.setUniforms(context, texToFboShaderID);
581 sglr::drawQuad(context, texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
582
583 context.bindTexture(GL_TEXTURE_2D, metaballsTex);
584 context.stencilFunc(GL_EQUAL, 2, 0xffu);
585
586 texToFboShader.setUniforms(context, texToFboShaderID);
587 sglr::drawQuad(context, texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
588
589 context.disable(GL_STENCIL_TEST);
590
591 if (fbo.getConfig().colorType == GL_TEXTURE_2D)
592 {
593 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
594 context.bindTexture(GL_TEXTURE_2D, fbo.getColorBuffer());
595 context.viewport(0, 0, context.getWidth(), context.getHeight());
596
597 texFromFboShader.setUniforms(context, texFromFboShaderID);
598 sglr::drawQuad(context, texFromFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
599
600 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
601 }
602 else
603 readPixels(context, dst, 0, 0, width, height, colorFormat, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias);
604 }
605
606 class SharedColorbufferTest : public FboRenderCase
607 {
608 public:
609 SharedColorbufferTest (Context& context, const FboConfig& config);
~SharedColorbufferTest(void)610 virtual ~SharedColorbufferTest (void) {}
611
612 void render (sglr::Context& context, Surface& dst);
613 };
614
SharedColorbufferTest(Context & context,const FboConfig & config)615 SharedColorbufferTest::SharedColorbufferTest (Context& context, const FboConfig& config)
616 : FboRenderCase (context, config.getName().c_str(), "Shared colorbuffer", config)
617 {
618 }
619
render(sglr::Context & context,Surface & dst)620 void SharedColorbufferTest::render (sglr::Context& context, Surface& dst)
621 {
622 Texture2DShader texShader (DataTypes() << glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC4);
623 FlatColorShader flatShader (glu::TYPE_FLOAT_VEC4);
624 deUint32 texShaderID = context.createProgram(&texShader);
625 deUint32 flatShaderID = context.createProgram(&flatShader);
626
627 int width = 128;
628 int height = 128;
629 deUint32 quadsTex = 1;
630 deUint32 metaballsTex = 2;
631 bool stencil = (m_config.buffers & GL_STENCIL_BUFFER_BIT) != 0;
632
633 context.disable(GL_DITHER);
634
635 // Textures
636 createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
637 createMetaballsTex2D(context, metaballsTex, GL_RGBA, GL_UNSIGNED_BYTE, 64, 64);
638
639 context.viewport(0, 0, width, height);
640
641 // Fbo A
642 Framebuffer fboA(context, m_config, width, height);
643 fboA.checkCompleteness();
644
645 // Fbo B - don't create colorbuffer
646 FboConfig cfg = m_config;
647 cfg.buffers &= ~GL_COLOR_BUFFER_BIT;
648 cfg.colorType = GL_NONE;
649 cfg.colorFormat = GL_NONE;
650 Framebuffer fboB(context, cfg, width, height);
651
652 // Attach color buffer from fbo A
653 context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
654 switch (m_config.colorType)
655 {
656 case GL_TEXTURE_2D:
657 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboA.getColorBuffer(), 0);
658 break;
659
660 case GL_RENDERBUFFER:
661 context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, fboA.getColorBuffer());
662 break;
663
664 default:
665 DE_ASSERT(DE_FALSE);
666 }
667
668 // Clear depth and stencil in fbo B
669 context.clear(GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
670
671 // Render quads to fbo 1, with depth 0.0
672 context.bindFramebuffer(GL_FRAMEBUFFER, fboA.getFramebuffer());
673 context.bindTexture(GL_TEXTURE_2D, quadsTex);
674 context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
675 context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
676
677 if (stencil)
678 {
679 // Stencil to 1 in fbo A
680 context.clearStencil(1);
681 context.clear(GL_STENCIL_BUFFER_BIT);
682 }
683
684 texShader.setUniforms(context, texShaderID);
685
686 context.enable(GL_DEPTH_TEST);
687 sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
688 context.disable(GL_DEPTH_TEST);
689
690 // Blend metaballs to fbo 2
691 context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
692 context.bindTexture(GL_TEXTURE_2D, metaballsTex);
693 context.enable(GL_BLEND);
694 context.blendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
695 sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
696
697 // Render small quad that is only visible if depth buffer is not shared with fbo A - or there is no depth bits
698 context.bindTexture(GL_TEXTURE_2D, quadsTex);
699 context.enable(GL_DEPTH_TEST);
700 sglr::drawQuad(context, texShaderID, Vec3(0.5f, 0.5f, 0.5f), Vec3(1.0f, 1.0f, 0.5f));
701 context.disable(GL_DEPTH_TEST);
702
703 if (stencil)
704 {
705 flatShader.setColor(context, flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
706
707 // Clear subset of stencil buffer to 1
708 context.enable(GL_SCISSOR_TEST);
709 context.scissor(10, 10, 12, 25);
710 context.clearStencil(1);
711 context.clear(GL_STENCIL_BUFFER_BIT);
712 context.disable(GL_SCISSOR_TEST);
713
714 // Render quad with stencil mask == 1
715 context.enable(GL_STENCIL_TEST);
716 context.stencilFunc(GL_EQUAL, 1, 0xffu);
717 sglr::drawQuad(context, flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
718 context.disable(GL_STENCIL_TEST);
719 }
720
721 // Get results
722 if (fboA.getConfig().colorType == GL_TEXTURE_2D)
723 {
724 texShader.setUniforms(context, texShaderID);
725
726 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
727 context.bindTexture(GL_TEXTURE_2D, fboA.getColorBuffer());
728 context.viewport(0, 0, context.getWidth(), context.getHeight());
729 sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
730 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
731 }
732 else
733 readPixels(context, dst, 0, 0, width, height, glu::mapGLInternalFormat(fboA.getConfig().colorFormat), Vec4(1.0f), Vec4(0.0f));
734 }
735
736 class SharedColorbufferClearsTest : public FboRenderCase
737 {
738 public:
739 SharedColorbufferClearsTest (Context& context, const FboConfig& config);
~SharedColorbufferClearsTest(void)740 virtual ~SharedColorbufferClearsTest (void) {}
741
742 void render (sglr::Context& context, Surface& dst);
743 };
744
SharedColorbufferClearsTest(Context & context,const FboConfig & config)745 SharedColorbufferClearsTest::SharedColorbufferClearsTest (Context& context, const FboConfig& config)
746 : FboRenderCase (context, config.getName().c_str(), "Shared colorbuffer clears", config)
747 {
748 }
749
render(sglr::Context & context,Surface & dst)750 void SharedColorbufferClearsTest::render (sglr::Context& context, Surface& dst)
751 {
752 tcu::TextureFormat colorFormat = glu::mapGLInternalFormat(m_config.colorFormat);
753 glu::DataType fboSamplerType = glu::getSampler2DType(colorFormat);
754 int width = 128;
755 int height = 128;
756 deUint32 colorbuffer = 1;
757
758 // Check for format support.
759 checkColorFormatSupport(context, m_config.colorFormat);
760
761 // Single colorbuffer
762 if (m_config.colorType == GL_TEXTURE_2D)
763 {
764 context.bindTexture(GL_TEXTURE_2D, colorbuffer);
765 context.texImage2D(GL_TEXTURE_2D, 0, m_config.colorFormat, width, height);
766 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
767 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
768 }
769 else
770 {
771 DE_ASSERT(m_config.colorType == GL_RENDERBUFFER);
772 context.bindRenderbuffer(GL_RENDERBUFFER, colorbuffer);
773 context.renderbufferStorage(GL_RENDERBUFFER, m_config.colorFormat, width, height);
774 }
775
776 // Multiple framebuffers sharing the colorbuffer
777 for (int fbo = 1; fbo <= 3; fbo++)
778 {
779 context.bindFramebuffer(GL_FRAMEBUFFER, fbo);
780
781 if (m_config.colorType == GL_TEXTURE_2D)
782 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer, 0);
783 else
784 context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuffer);
785 }
786
787 context.bindFramebuffer(GL_FRAMEBUFFER, 1);
788
789 // Check completeness
790 {
791 GLenum status = context.checkFramebufferStatus(GL_FRAMEBUFFER);
792 if (status != GL_FRAMEBUFFER_COMPLETE)
793 throw FboIncompleteException(status, __FILE__, __LINE__);
794 }
795
796 // Render to them
797 context.viewport(0, 0, width, height);
798 context.clearColor(0.0f, 0.0f, 1.0f, 1.0f);
799 context.clear(GL_COLOR_BUFFER_BIT);
800
801 context.enable(GL_SCISSOR_TEST);
802
803 context.bindFramebuffer(GL_FRAMEBUFFER, 2);
804 context.clearColor(0.6f, 0.0f, 0.0f, 1.0f);
805 context.scissor(10, 10, 64, 64);
806 context.clear(GL_COLOR_BUFFER_BIT);
807 context.clearColor(0.0f, 0.6f, 0.0f, 1.0f);
808 context.scissor(60, 60, 40, 20);
809 context.clear(GL_COLOR_BUFFER_BIT);
810
811 context.bindFramebuffer(GL_FRAMEBUFFER, 3);
812 context.clearColor(0.0f, 0.0f, 0.6f, 1.0f);
813 context.scissor(20, 20, 100, 10);
814 context.clear(GL_COLOR_BUFFER_BIT);
815
816 context.bindFramebuffer(GL_FRAMEBUFFER, 1);
817 context.clearColor(0.6f, 0.0f, 0.6f, 1.0f);
818 context.scissor(20, 20, 5, 100);
819 context.clear(GL_COLOR_BUFFER_BIT);
820
821 context.disable(GL_SCISSOR_TEST);
822
823 if (m_config.colorType == GL_TEXTURE_2D)
824 {
825 Texture2DShader shader(DataTypes() << fboSamplerType, glu::TYPE_FLOAT_VEC4);
826 deUint32 shaderID = context.createProgram(&shader);
827
828 shader.setUniforms(context, shaderID);
829
830 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
831 context.viewport(0, 0, context.getWidth(), context.getHeight());
832 sglr::drawQuad(context, shaderID, Vec3(-0.9f, -0.9f, 0.0f), Vec3(0.9f, 0.9f, 0.0f));
833 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
834 }
835 else
836 readPixels(context, dst, 0, 0, width, height, colorFormat, Vec4(1.0f), Vec4(0.0f));
837 }
838
839 class SharedDepthStencilTest : public FboRenderCase
840 {
841 public:
842 SharedDepthStencilTest (Context& context, const FboConfig& config);
~SharedDepthStencilTest(void)843 virtual ~SharedDepthStencilTest (void) {}
844
845 static bool isConfigSupported (const FboConfig& config);
846 void render (sglr::Context& context, Surface& dst);
847 };
848
SharedDepthStencilTest(Context & context,const FboConfig & config)849 SharedDepthStencilTest::SharedDepthStencilTest (Context& context, const FboConfig& config)
850 : FboRenderCase (context, config.getName().c_str(), "Shared depth/stencilbuffer", config)
851 {
852 }
853
isConfigSupported(const FboConfig & config)854 bool SharedDepthStencilTest::isConfigSupported (const FboConfig& config)
855 {
856 return (config.buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)) != 0;
857 }
858
render(sglr::Context & context,Surface & dst)859 void SharedDepthStencilTest::render (sglr::Context& context, Surface& dst)
860 {
861 Texture2DShader texShader (DataTypes() << glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC4);
862 FlatColorShader flatShader (glu::TYPE_FLOAT_VEC4);
863 deUint32 texShaderID = context.createProgram(&texShader);
864 deUint32 flatShaderID = context.createProgram(&flatShader);
865 int width = 128;
866 int height = 128;
867 // bool depth = (m_config.buffers & GL_DEPTH_BUFFER_BIT) != 0;
868 bool stencil = (m_config.buffers & GL_STENCIL_BUFFER_BIT) != 0;
869
870 // Textures
871 deUint32 metaballsTex = 5;
872 deUint32 quadsTex = 6;
873 createMetaballsTex2D(context, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
874 createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
875
876 context.viewport(0, 0, width, height);
877
878 // Fbo A
879 Framebuffer fboA(context, m_config, width, height);
880 fboA.checkCompleteness();
881
882 // Fbo B
883 FboConfig cfg = m_config;
884 cfg.buffers &= ~(GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
885 cfg.depthStencilType = GL_NONE;
886 cfg.depthStencilFormat = GL_NONE;
887 Framebuffer fboB(context, cfg, width, height);
888
889 // Bind depth/stencil buffers from fbo A to fbo B
890 context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
891 for (int ndx = 0; ndx < 2; ndx++)
892 {
893 deUint32 bit = ndx ? GL_STENCIL_BUFFER_BIT : GL_DEPTH_BUFFER_BIT;
894 deUint32 point = ndx ? GL_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT;
895
896 if ((m_config.buffers & bit) == 0)
897 continue;
898
899 switch (m_config.depthStencilType)
900 {
901 case GL_TEXTURE_2D: context.framebufferTexture2D(GL_FRAMEBUFFER, point, GL_TEXTURE_2D, fboA.getDepthStencilBuffer(), 0); break;
902 case GL_RENDERBUFFER: context.framebufferRenderbuffer(GL_FRAMEBUFFER, point, GL_RENDERBUFFER, fboA.getDepthStencilBuffer()); break;
903 default:
904 TCU_FAIL("Not implemented");
905 }
906 }
907
908 // Setup uniforms
909 texShader.setUniforms(context, texShaderID);
910
911 // Clear color to red and stencil to 1 in fbo B.
912 context.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
913 context.clearStencil(1);
914 context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
915
916 context.enable(GL_DEPTH_TEST);
917
918 // Render quad to fbo A
919 context.bindFramebuffer(GL_FRAMEBUFFER, fboA.getFramebuffer());
920 context.bindTexture(GL_TEXTURE_2D, quadsTex);
921 sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
922
923 if (stencil)
924 {
925 // Clear subset of stencil buffer to 0 in fbo A
926 context.enable(GL_SCISSOR_TEST);
927 context.scissor(10, 10, 12, 25);
928 context.clearStencil(0);
929 context.clear(GL_STENCIL_BUFFER_BIT);
930 context.disable(GL_SCISSOR_TEST);
931 }
932
933 // Render metaballs to fbo B
934 context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
935 context.bindTexture(GL_TEXTURE_2D, metaballsTex);
936 sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));
937
938 context.disable(GL_DEPTH_TEST);
939
940 if (stencil)
941 {
942 // Render quad with stencil mask == 0
943 context.enable(GL_STENCIL_TEST);
944 context.stencilFunc(GL_EQUAL, 0, 0xffu);
945 context.useProgram(flatShaderID);
946 flatShader.setColor(context, flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
947 sglr::drawQuad(context, flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
948 context.disable(GL_STENCIL_TEST);
949 }
950
951 if (m_config.colorType == GL_TEXTURE_2D)
952 {
953 // Render both to screen
954 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
955 context.viewport(0, 0, context.getWidth(), context.getHeight());
956 context.bindTexture(GL_TEXTURE_2D, fboA.getColorBuffer());
957 sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(0.0f, 1.0f, 0.0f));
958 context.bindTexture(GL_TEXTURE_2D, fboB.getColorBuffer());
959 sglr::drawQuad(context, texShaderID, Vec3(0.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
960
961 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
962 }
963 else
964 {
965 // Read results from fbo B
966 readPixels(context, dst, 0, 0, width, height, glu::mapGLInternalFormat(m_config.colorFormat), Vec4(1.0f), Vec4(0.0f));
967 }
968 }
969
970 #if 0
971 class TexSubImageAfterRenderTest : public FboRenderCase
972 {
973 public:
974 TexSubImageAfterRenderTest (Context& context, const FboConfig& config);
975 virtual ~TexSubImageAfterRenderTest (void) {}
976
977 void render (sglr::Context& context, Surface& dst);
978 };
979
980 TexSubImageAfterRenderTest::TexSubImageAfterRenderTest (Context& context, const FboConfig& config)
981 : FboRenderCase(context, (string("after_render_") + config.getName()).c_str(), "TexSubImage after rendering to texture", config)
982 {
983 }
984
985 void TexSubImageAfterRenderTest::render (sglr::Context& context, Surface& dst)
986 {
987 using sglr::TexturedQuadOp;
988
989 bool isRGBA = true;
990
991 Surface fourQuads(Surface::PIXELFORMAT_RGB, 64, 64);
992 tcu::SurfaceUtil::fillWithFourQuads(fourQuads);
993
994 Surface metaballs(isRGBA ? Surface::PIXELFORMAT_RGBA : Surface::PIXELFORMAT_RGB, 64, 64);
995 tcu::SurfaceUtil::fillWithMetaballs(metaballs, 5, 3);
996
997 deUint32 fourQuadsTex = 1;
998 context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
999 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1000 context.texImage2D(GL_TEXTURE_2D, 0, GL_RGB, fourQuads);
1001
1002 context.bindFramebuffer(GL_FRAMEBUFFER, 1);
1003
1004 deUint32 fboTex = 2;
1005 context.bindTexture(GL_TEXTURE_2D, fboTex);
1006 context.texImage2D(GL_TEXTURE_2D, 0, isRGBA ? GL_RGBA : GL_RGB, 128, 128);
1007 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1008 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0);
1009
1010 // Render to fbo
1011 context.viewport(0, 0, 128, 128);
1012 context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
1013 context.draw(TexturedQuadOp(-1.0f, -1.0f, 1.0f, 1.0f, 0));
1014
1015 // Update texture using TexSubImage2D
1016 context.bindTexture(GL_TEXTURE_2D, fboTex);
1017 context.texSubImage2D(GL_TEXTURE_2D, 0, 32, 32, metaballs);
1018
1019 // Draw to screen
1020 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1021 context.viewport(0, 0, context.getWidth(), context.getHeight());
1022 context.draw(TexturedQuadOp(-1.0f, -1.0f, 1.0f, 1.0f, 0));
1023 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
1024 }
1025
1026 class TexSubImageBetweenRenderTest : public FboRenderCase
1027 {
1028 public:
1029 TexSubImageBetweenRenderTest (Context& context, const FboConfig& config);
1030 virtual ~TexSubImageBetweenRenderTest (void) {}
1031
1032 void render (sglr::Context& context, Surface& dst);
1033 };
1034
1035 TexSubImageBetweenRenderTest::TexSubImageBetweenRenderTest (Context& context, const FboConfig& config)
1036 : FboRenderCase(context, (string("between_render_") + config.getName()).c_str(), "TexSubImage between rendering calls", config)
1037 {
1038 }
1039
1040 void TexSubImageBetweenRenderTest::render (sglr::Context& context, Surface& dst)
1041 {
1042 using sglr::TexturedQuadOp;
1043 using sglr::BlendTextureOp;
1044
1045 bool isRGBA = true;
1046
1047 Surface fourQuads(Surface::PIXELFORMAT_RGB, 64, 64);
1048 tcu::SurfaceUtil::fillWithFourQuads(fourQuads);
1049
1050 Surface metaballs(isRGBA ? Surface::PIXELFORMAT_RGBA : Surface::PIXELFORMAT_RGB, 64, 64);
1051 tcu::SurfaceUtil::fillWithMetaballs(metaballs, 5, 3);
1052
1053 Surface metaballs2(Surface::PIXELFORMAT_RGBA, 64, 64);
1054 tcu::SurfaceUtil::fillWithMetaballs(metaballs2, 5, 4);
1055
1056 deUint32 metaballsTex = 3;
1057 context.bindTexture(GL_TEXTURE_2D, metaballsTex);
1058 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1059 context.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, metaballs2);
1060
1061 deUint32 fourQuadsTex = 1;
1062 context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
1063 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1064 context.texImage2D(GL_TEXTURE_2D, 0, GL_RGB, fourQuads);
1065
1066 context.bindFramebuffer(GL_FRAMEBUFFER, 1);
1067
1068 deUint32 fboTex = 2;
1069 context.bindTexture(GL_TEXTURE_2D, fboTex);
1070 context.texImage2D(GL_TEXTURE_2D, 0, isRGBA ? GL_RGBA : GL_RGB, 128, 128);
1071 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1072 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0);
1073
1074 // Render to fbo
1075 context.viewport(0, 0, 128, 128);
1076 context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
1077 context.draw(TexturedQuadOp(-1.0f, -1.0f, 1.0f, 1.0f, 0));
1078
1079 // Update texture using TexSubImage2D
1080 context.bindTexture(GL_TEXTURE_2D, fboTex);
1081 context.texSubImage2D(GL_TEXTURE_2D, 0, 32, 32, metaballs);
1082
1083 // Render again to fbo
1084 context.bindTexture(GL_TEXTURE_2D, metaballsTex);
1085 context.draw(BlendTextureOp(0));
1086
1087 // Draw to screen
1088 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1089 context.viewport(0, 0, context.getWidth(), context.getHeight());
1090 context.bindTexture(GL_TEXTURE_2D, fboTex);
1091 context.draw(TexturedQuadOp(-1.0f, -1.0f, 1.0f, 1.0f, 0));
1092
1093 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
1094 }
1095 #endif
1096
1097 class ResizeTest : public FboRenderCase
1098 {
1099 public:
1100 ResizeTest (Context& context, const FboConfig& config);
~ResizeTest(void)1101 virtual ~ResizeTest (void) {}
1102
1103 void render (sglr::Context& context, Surface& dst);
1104 };
1105
ResizeTest(Context & context,const FboConfig & config)1106 ResizeTest::ResizeTest (Context& context, const FboConfig& config)
1107 : FboRenderCase (context, config.getName().c_str(), "Resize framebuffer", config)
1108 {
1109 }
1110
render(sglr::Context & context,Surface & dst)1111 void ResizeTest::render (sglr::Context& context, Surface& dst)
1112 {
1113 tcu::TextureFormat colorFormat = glu::mapGLInternalFormat(m_config.colorFormat);
1114 glu::DataType fboSamplerType = glu::getSampler2DType(colorFormat);
1115 glu::DataType fboOutputType = getFragmentOutputType(colorFormat);
1116 tcu::TextureFormatInfo fboRangeInfo = tcu::getTextureFormatInfo(colorFormat);
1117 Vec4 fboOutScale = fboRangeInfo.valueMax - fboRangeInfo.valueMin;
1118 Vec4 fboOutBias = fboRangeInfo.valueMin;
1119
1120 Texture2DShader texToFboShader (DataTypes() << glu::TYPE_SAMPLER_2D, fboOutputType);
1121 Texture2DShader texFromFboShader (DataTypes() << fboSamplerType, glu::TYPE_FLOAT_VEC4);
1122 FlatColorShader flatShader (fboOutputType);
1123 deUint32 texToFboShaderID = context.createProgram(&texToFboShader);
1124 deUint32 texFromFboShaderID = context.createProgram(&texFromFboShader);
1125 deUint32 flatShaderID = context.createProgram(&flatShader);
1126
1127 deUint32 quadsTex = 1;
1128 deUint32 metaballsTex = 2;
1129 bool depth = (m_config.buffers & GL_DEPTH_BUFFER_BIT) != 0;
1130 bool stencil = (m_config.buffers & GL_STENCIL_BUFFER_BIT) != 0;
1131 int initialWidth = 128;
1132 int initialHeight = 128;
1133 int newWidth = 64;
1134 int newHeight = 32;
1135
1136 texToFboShader.setOutScaleBias(fboOutScale, fboOutBias);
1137 texFromFboShader.setTexScaleBias(0, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias);
1138
1139 createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
1140 createMetaballsTex2D(context, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 32, 32);
1141
1142 Framebuffer fbo(context, m_config, initialWidth, initialHeight);
1143 fbo.checkCompleteness();
1144
1145 // Setup shaders
1146 texToFboShader.setUniforms (context, texToFboShaderID);
1147 texFromFboShader.setUniforms(context, texFromFboShaderID);
1148 flatShader.setColor (context, flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f) * fboOutScale + fboOutBias);
1149
1150 // Render quads
1151 context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
1152 context.viewport(0, 0, initialWidth, initialHeight);
1153 clearColorBuffer(context, colorFormat, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
1154 context.clear(GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
1155 context.bindTexture(GL_TEXTURE_2D, quadsTex);
1156 sglr::drawQuad(context, texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1157
1158 if (fbo.getConfig().colorType == GL_TEXTURE_2D)
1159 {
1160 // Render fbo to screen
1161 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1162 context.viewport(0, 0, context.getWidth(), context.getHeight());
1163 context.bindTexture(GL_TEXTURE_2D, fbo.getColorBuffer());
1164 sglr::drawQuad(context, texFromFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1165
1166 // Restore binding
1167 context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
1168 }
1169
1170 // Resize buffers
1171 switch (fbo.getConfig().colorType)
1172 {
1173 case GL_TEXTURE_2D:
1174 context.bindTexture(GL_TEXTURE_2D, fbo.getColorBuffer());
1175 context.texImage2D(GL_TEXTURE_2D, 0, fbo.getConfig().colorFormat, newWidth, newHeight);
1176 break;
1177
1178 case GL_RENDERBUFFER:
1179 context.bindRenderbuffer(GL_RENDERBUFFER, fbo.getColorBuffer());
1180 context.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().colorFormat, newWidth, newHeight);
1181 break;
1182
1183 default:
1184 DE_ASSERT(DE_FALSE);
1185 }
1186
1187 if (depth || stencil)
1188 {
1189 switch (fbo.getConfig().depthStencilType)
1190 {
1191 case GL_TEXTURE_2D:
1192 context.bindTexture(GL_TEXTURE_2D, fbo.getDepthStencilBuffer());
1193 context.texImage2D(GL_TEXTURE_2D, 0, fbo.getConfig().depthStencilFormat, newWidth, newHeight);
1194 break;
1195
1196 case GL_RENDERBUFFER:
1197 context.bindRenderbuffer(GL_RENDERBUFFER, fbo.getDepthStencilBuffer());
1198 context.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().depthStencilFormat, newWidth, newHeight);
1199 break;
1200
1201 default:
1202 DE_ASSERT(false);
1203 }
1204 }
1205
1206 // Render to resized fbo
1207 context.viewport(0, 0, newWidth, newHeight);
1208 clearColorBuffer(context, colorFormat, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
1209 context.clear(GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
1210
1211 context.enable(GL_DEPTH_TEST);
1212
1213 context.bindTexture(GL_TEXTURE_2D, metaballsTex);
1214 sglr::drawQuad(context, texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
1215
1216 context.bindTexture(GL_TEXTURE_2D, quadsTex);
1217 sglr::drawQuad(context, texToFboShaderID, Vec3(0.0f, 0.0f, -1.0f), Vec3(+1.0f, +1.0f, 1.0f));
1218
1219 context.disable(GL_DEPTH_TEST);
1220
1221 if (stencil)
1222 {
1223 context.enable(GL_SCISSOR_TEST);
1224 context.clearStencil(1);
1225 context.scissor(10, 10, 5, 15);
1226 context.clear(GL_STENCIL_BUFFER_BIT);
1227 context.disable(GL_SCISSOR_TEST);
1228
1229 context.enable(GL_STENCIL_TEST);
1230 context.stencilFunc(GL_EQUAL, 1, 0xffu);
1231 sglr::drawQuad(context, flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
1232 context.disable(GL_STENCIL_TEST);
1233 }
1234
1235 if (m_config.colorType == GL_TEXTURE_2D)
1236 {
1237 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1238 context.viewport(0, 0, context.getWidth(), context.getHeight());
1239 context.bindTexture(GL_TEXTURE_2D, fbo.getColorBuffer());
1240 sglr::drawQuad(context, texFromFboShaderID, Vec3(-0.5f, -0.5f, 0.0f), Vec3(0.5f, 0.5f, 0.0f));
1241 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
1242 }
1243 else
1244 readPixels(context, dst, 0, 0, newWidth, newHeight, colorFormat, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias);
1245 }
1246
1247 class RecreateBuffersTest : public FboRenderCase
1248 {
1249 public:
1250 RecreateBuffersTest (Context& context, const FboConfig& config, deUint32 buffers, bool rebind);
~RecreateBuffersTest(void)1251 virtual ~RecreateBuffersTest (void) {}
1252
1253 void render (sglr::Context& context, Surface& dst);
1254
1255 private:
1256 deUint32 m_buffers;
1257 bool m_rebind;
1258 };
1259
RecreateBuffersTest(Context & context,const FboConfig & config,deUint32 buffers,bool rebind)1260 RecreateBuffersTest::RecreateBuffersTest (Context& context, const FboConfig& config, deUint32 buffers, bool rebind)
1261 : FboRenderCase (context, (string(config.getName()) + (rebind ? "" : "_no_rebind")).c_str(), "Recreate buffers", config)
1262 , m_buffers (buffers)
1263 , m_rebind (rebind)
1264 {
1265 }
1266
render(sglr::Context & ctx,Surface & dst)1267 void RecreateBuffersTest::render (sglr::Context& ctx, Surface& dst)
1268 {
1269 tcu::TextureFormat colorFormat = glu::mapGLInternalFormat(m_config.colorFormat);
1270 glu::DataType fboSamplerType = glu::getSampler2DType(colorFormat);
1271 glu::DataType fboOutputType = getFragmentOutputType(colorFormat);
1272 tcu::TextureFormatInfo fboRangeInfo = tcu::getTextureFormatInfo(colorFormat);
1273 Vec4 fboOutScale = fboRangeInfo.valueMax - fboRangeInfo.valueMin;
1274 Vec4 fboOutBias = fboRangeInfo.valueMin;
1275
1276 Texture2DShader texToFboShader (DataTypes() << glu::TYPE_SAMPLER_2D, fboOutputType);
1277 Texture2DShader texFromFboShader (DataTypes() << fboSamplerType, glu::TYPE_FLOAT_VEC4);
1278 FlatColorShader flatShader (fboOutputType);
1279 deUint32 texToFboShaderID = ctx.createProgram(&texToFboShader);
1280 deUint32 texFromFboShaderID = ctx.createProgram(&texFromFboShader);
1281 deUint32 flatShaderID = ctx.createProgram(&flatShader);
1282
1283 int width = 128;
1284 int height = 128;
1285 deUint32 metaballsTex = 1;
1286 deUint32 quadsTex = 2;
1287 bool stencil = (m_config.buffers & GL_STENCIL_BUFFER_BIT) != 0;
1288
1289 createQuadsTex2D(ctx, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
1290 createMetaballsTex2D(ctx, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
1291
1292 Framebuffer fbo(ctx, m_config, width, height);
1293 fbo.checkCompleteness();
1294
1295 // Setup shaders
1296 texToFboShader.setOutScaleBias(fboOutScale, fboOutBias);
1297 texFromFboShader.setTexScaleBias(0, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias);
1298 texToFboShader.setUniforms (ctx, texToFboShaderID);
1299 texFromFboShader.setUniforms(ctx, texFromFboShaderID);
1300 flatShader.setColor (ctx, flatShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f) * fboOutScale + fboOutBias);
1301
1302 // Draw scene
1303 ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
1304 ctx.viewport(0, 0, width, height);
1305 clearColorBuffer(ctx, colorFormat, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
1306 ctx.clear(GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
1307
1308 ctx.enable(GL_DEPTH_TEST);
1309
1310 ctx.bindTexture(GL_TEXTURE_2D, quadsTex);
1311 sglr::drawQuad(ctx, texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1312
1313 ctx.disable(GL_DEPTH_TEST);
1314
1315 if (stencil)
1316 {
1317 ctx.enable(GL_SCISSOR_TEST);
1318 ctx.scissor(width/4, height/4, width/2, height/2);
1319 ctx.clearStencil(1);
1320 ctx.clear(GL_STENCIL_BUFFER_BIT);
1321 ctx.disable(GL_SCISSOR_TEST);
1322 }
1323
1324 // Recreate buffers
1325 if (!m_rebind)
1326 ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);
1327
1328 DE_ASSERT((m_buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)) == 0 ||
1329 (m_buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)) == (m_config.buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)));
1330
1331 // Recreate.
1332 for (int ndx = 0; ndx < 2; ndx++)
1333 {
1334 deUint32 bit = ndx == 0 ? GL_COLOR_BUFFER_BIT
1335 : (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
1336 deUint32 type = ndx == 0 ? fbo.getConfig().colorType
1337 : fbo.getConfig().depthStencilType;
1338 deUint32 format = ndx == 0 ? fbo.getConfig().colorFormat
1339 : fbo.getConfig().depthStencilFormat;
1340 deUint32 buf = ndx == 0 ? fbo.getColorBuffer()
1341 : fbo.getDepthStencilBuffer();
1342
1343 if ((m_buffers & bit) == 0)
1344 continue;
1345
1346 switch (type)
1347 {
1348 case GL_TEXTURE_2D:
1349 ctx.deleteTextures(1, &buf);
1350 ctx.bindTexture(GL_TEXTURE_2D, buf);
1351 ctx.texImage2D(GL_TEXTURE_2D, 0, format, width, height);
1352 ctx.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1353 ctx.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1354 break;
1355
1356 case GL_RENDERBUFFER:
1357 ctx.deleteRenderbuffers(1, &buf);
1358 ctx.bindRenderbuffer(GL_RENDERBUFFER, buf);
1359 ctx.renderbufferStorage(GL_RENDERBUFFER, format, width, height);
1360 break;
1361
1362 default:
1363 DE_ASSERT(false);
1364 }
1365 }
1366
1367 // Rebind.
1368 if (m_rebind)
1369 {
1370 for (int ndx = 0; ndx < 3; ndx++)
1371 {
1372 deUint32 bit = ndx == 0 ? GL_COLOR_BUFFER_BIT :
1373 ndx == 1 ? GL_DEPTH_BUFFER_BIT :
1374 ndx == 2 ? GL_STENCIL_BUFFER_BIT : 0;
1375 deUint32 point = ndx == 0 ? GL_COLOR_ATTACHMENT0 :
1376 ndx == 1 ? GL_DEPTH_ATTACHMENT :
1377 ndx == 2 ? GL_STENCIL_ATTACHMENT : 0;
1378 deUint32 type = ndx == 0 ? fbo.getConfig().colorType
1379 : fbo.getConfig().depthStencilType;
1380 deUint32 buf = ndx == 0 ? fbo.getColorBuffer()
1381 : fbo.getDepthStencilBuffer();
1382
1383 if ((m_buffers & bit) == 0)
1384 continue;
1385
1386 switch (type)
1387 {
1388 case GL_TEXTURE_2D:
1389 ctx.framebufferTexture2D(GL_FRAMEBUFFER, point, GL_TEXTURE_2D, buf, 0);
1390 break;
1391
1392 case GL_RENDERBUFFER:
1393 ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, point, GL_RENDERBUFFER, buf);
1394 break;
1395
1396 default:
1397 DE_ASSERT(false);
1398 }
1399 }
1400 }
1401
1402 if (!m_rebind)
1403 ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
1404
1405 ctx.clearStencil(0);
1406 ctx.clear(m_buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)); // \note Clear only buffers that were re-created
1407 if (m_buffers & GL_COLOR_BUFFER_BIT)
1408 {
1409 // Clearing of integer buffers is undefined so do clearing by rendering flat color.
1410 sglr::drawQuad(ctx, flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1411 }
1412
1413 ctx.enable(GL_DEPTH_TEST);
1414
1415 if (stencil)
1416 {
1417 // \note Stencil test enabled only if we have stencil buffer
1418 ctx.enable(GL_STENCIL_TEST);
1419 ctx.stencilFunc(GL_EQUAL, 0, 0xffu);
1420 }
1421 ctx.bindTexture(GL_TEXTURE_2D, metaballsTex);
1422 sglr::drawQuad(ctx, texToFboShaderID, Vec3(-1.0f, -1.0f, 1.0f), Vec3(1.0f, 1.0f, -1.0f));
1423 if (stencil)
1424 ctx.disable(GL_STENCIL_TEST);
1425
1426 ctx.disable(GL_DEPTH_TEST);
1427
1428 if (fbo.getConfig().colorType == GL_TEXTURE_2D)
1429 {
1430 // Unbind fbo
1431 ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);
1432
1433 // Draw to screen
1434 ctx.bindTexture(GL_TEXTURE_2D, fbo.getColorBuffer());
1435 ctx.viewport(0, 0, ctx.getWidth(), ctx.getHeight());
1436 sglr::drawQuad(ctx, texFromFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1437
1438 // Read from screen
1439 ctx.readPixels(dst, 0, 0, ctx.getWidth(), ctx.getHeight());
1440 }
1441 else
1442 {
1443 // Read from fbo
1444 readPixels(ctx, dst, 0, 0, width, height, colorFormat, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias);
1445 }
1446 }
1447
1448 } // FboCases
1449
FboRenderTestGroup(Context & context)1450 FboRenderTestGroup::FboRenderTestGroup (Context& context)
1451 : TestCaseGroup(context, "render", "Rendering Tests")
1452 {
1453 }
1454
~FboRenderTestGroup(void)1455 FboRenderTestGroup::~FboRenderTestGroup (void)
1456 {
1457 }
1458
init(void)1459 void FboRenderTestGroup::init (void)
1460 {
1461 static const deUint32 objectTypes[] =
1462 {
1463 GL_TEXTURE_2D,
1464 GL_RENDERBUFFER
1465 };
1466
1467 enum FormatType
1468 {
1469 FORMATTYPE_FLOAT = 0,
1470 FORMATTYPE_FIXED,
1471 FORMATTYPE_INT,
1472 FORMATTYPE_UINT,
1473
1474 FORMATTYPE_LAST
1475 };
1476
1477 // Required by specification.
1478 static const struct
1479 {
1480 deUint32 format;
1481 FormatType type;
1482 } colorFormats[] =
1483 {
1484 { GL_RGBA32F, FORMATTYPE_FLOAT },
1485 { GL_RGBA32I, FORMATTYPE_INT },
1486 { GL_RGBA32UI, FORMATTYPE_UINT },
1487 { GL_RGBA16F, FORMATTYPE_FLOAT },
1488 { GL_RGBA16I, FORMATTYPE_INT },
1489 { GL_RGBA16UI, FORMATTYPE_UINT },
1490 { GL_RGB16F, FORMATTYPE_FLOAT },
1491 { GL_RGBA8, FORMATTYPE_FIXED },
1492 { GL_RGBA8I, FORMATTYPE_INT },
1493 { GL_RGBA8UI, FORMATTYPE_UINT },
1494 { GL_SRGB8_ALPHA8, FORMATTYPE_FIXED },
1495 { GL_RGB10_A2, FORMATTYPE_FIXED },
1496 { GL_RGB10_A2UI, FORMATTYPE_UINT },
1497 { GL_RGBA4, FORMATTYPE_FIXED },
1498 { GL_RGB5_A1, FORMATTYPE_FIXED },
1499 { GL_RGB8, FORMATTYPE_FIXED },
1500 { GL_RGB565, FORMATTYPE_FIXED },
1501 { GL_R11F_G11F_B10F, FORMATTYPE_FLOAT },
1502 { GL_RG32F, FORMATTYPE_FLOAT },
1503 { GL_RG32I, FORMATTYPE_INT },
1504 { GL_RG32UI, FORMATTYPE_UINT },
1505 { GL_RG16F, FORMATTYPE_FLOAT },
1506 { GL_RG16I, FORMATTYPE_INT },
1507 { GL_RG16UI, FORMATTYPE_UINT },
1508 { GL_RG8, FORMATTYPE_FLOAT },
1509 { GL_RG8I, FORMATTYPE_INT },
1510 { GL_RG8UI, FORMATTYPE_UINT },
1511 { GL_R32F, FORMATTYPE_FLOAT },
1512 { GL_R32I, FORMATTYPE_INT },
1513 { GL_R32UI, FORMATTYPE_UINT },
1514 { GL_R16F, FORMATTYPE_FLOAT },
1515 { GL_R16I, FORMATTYPE_INT },
1516 { GL_R16UI, FORMATTYPE_UINT },
1517 { GL_R8, FORMATTYPE_FLOAT },
1518 { GL_R8I, FORMATTYPE_INT },
1519 { GL_R8UI, FORMATTYPE_UINT }
1520 };
1521
1522 static const struct
1523 {
1524 deUint32 format;
1525 bool depth;
1526 bool stencil;
1527 } depthStencilFormats[] =
1528 {
1529 { GL_DEPTH_COMPONENT32F, true, false },
1530 { GL_DEPTH_COMPONENT24, true, false },
1531 { GL_DEPTH_COMPONENT16, true, false },
1532 { GL_DEPTH32F_STENCIL8, true, true },
1533 { GL_DEPTH24_STENCIL8, true, true },
1534 { GL_STENCIL_INDEX8, false, true }
1535 };
1536
1537 using namespace FboCases;
1538
1539 // .stencil_clear
1540 tcu::TestCaseGroup* stencilClearGroup = new tcu::TestCaseGroup(m_testCtx, "stencil_clear", "Stencil buffer clears");
1541 addChild(stencilClearGroup);
1542 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats); fmtNdx++)
1543 {
1544 deUint32 colorType = GL_TEXTURE_2D;
1545 deUint32 stencilType = GL_RENDERBUFFER;
1546 deUint32 colorFmt = GL_RGBA8;
1547
1548 if (!depthStencilFormats[fmtNdx].stencil)
1549 continue;
1550
1551 FboConfig config(GL_COLOR_BUFFER_BIT|GL_STENCIL_BUFFER_BIT, colorType, colorFmt, stencilType, depthStencilFormats[fmtNdx].format);
1552 stencilClearGroup->addChild(new StencilClearsTest(m_context, config));
1553 }
1554
1555 // .shared_colorbuffer_clear
1556 tcu::TestCaseGroup* sharedColorbufferClearGroup = new tcu::TestCaseGroup(m_testCtx, "shared_colorbuffer_clear", "Shader colorbuffer clears");
1557 addChild(sharedColorbufferClearGroup);
1558 for (int colorFmtNdx = 0; colorFmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); colorFmtNdx++)
1559 {
1560 // Clearing of integer buffers is undefined.
1561 if (colorFormats[colorFmtNdx].type == FORMATTYPE_INT || colorFormats[colorFmtNdx].type == FORMATTYPE_UINT)
1562 continue;
1563
1564 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++)
1565 {
1566 FboConfig config(GL_COLOR_BUFFER_BIT, objectTypes[typeNdx], colorFormats[colorFmtNdx].format, GL_NONE, GL_NONE);
1567 sharedColorbufferClearGroup->addChild(new SharedColorbufferClearsTest(m_context, config));
1568 }
1569 }
1570
1571 // .shared_colorbuffer
1572 tcu::TestCaseGroup* sharedColorbufferGroup = new tcu::TestCaseGroup(m_testCtx, "shared_colorbuffer", "Shared colorbuffer tests");
1573 addChild(sharedColorbufferGroup);
1574 for (int colorFmtNdx = 0; colorFmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); colorFmtNdx++)
1575 {
1576 deUint32 depthStencilType = GL_RENDERBUFFER;
1577 deUint32 depthStencilFormat = GL_DEPTH24_STENCIL8;
1578
1579 // Blending with integer buffers and fp32 targets is not supported.
1580 if (colorFormats[colorFmtNdx].type == FORMATTYPE_INT ||
1581 colorFormats[colorFmtNdx].type == FORMATTYPE_UINT ||
1582 colorFormats[colorFmtNdx].format == GL_RGBA32F ||
1583 colorFormats[colorFmtNdx].format == GL_RGB32F ||
1584 colorFormats[colorFmtNdx].format == GL_RG32F ||
1585 colorFormats[colorFmtNdx].format == GL_R32F)
1586 continue;
1587
1588 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++)
1589 {
1590 FboConfig colorOnlyConfig (GL_COLOR_BUFFER_BIT, objectTypes[typeNdx], colorFormats[colorFmtNdx].format, GL_NONE, GL_NONE);
1591 FboConfig colorDepthConfig (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT, objectTypes[typeNdx], colorFormats[colorFmtNdx].format, depthStencilType, depthStencilFormat);
1592 FboConfig colorDepthStencilConfig (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT, objectTypes[typeNdx], colorFormats[colorFmtNdx].format, depthStencilType, depthStencilFormat);
1593
1594 sharedColorbufferGroup->addChild(new SharedColorbufferTest(m_context, colorOnlyConfig));
1595 sharedColorbufferGroup->addChild(new SharedColorbufferTest(m_context, colorDepthConfig));
1596 sharedColorbufferGroup->addChild(new SharedColorbufferTest(m_context, colorDepthStencilConfig));
1597 }
1598 }
1599
1600 // .shared_depth_stencil
1601 tcu::TestCaseGroup* sharedDepthStencilGroup = new tcu::TestCaseGroup(m_testCtx, "shared_depth_stencil", "Shared depth and stencil buffers");
1602 addChild(sharedDepthStencilGroup);
1603 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats); fmtNdx++)
1604 {
1605 deUint32 colorType = GL_TEXTURE_2D;
1606 deUint32 colorFmt = GL_RGBA8;
1607 bool depth = depthStencilFormats[fmtNdx].depth;
1608 bool stencil = depthStencilFormats[fmtNdx].stencil;
1609
1610 if (!depth)
1611 continue; // Not verified.
1612
1613 // Depth and stencil: both rbo and textures
1614 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++)
1615 {
1616 FboConfig config(GL_COLOR_BUFFER_BIT|(depth ? GL_DEPTH_BUFFER_BIT : 0)|(stencil ? GL_STENCIL_BUFFER_BIT : 0), colorType, colorFmt, objectTypes[typeNdx], depthStencilFormats[fmtNdx].format);
1617 sharedDepthStencilGroup->addChild(new SharedDepthStencilTest(m_context, config));
1618 }
1619 }
1620
1621 // .resize
1622 tcu::TestCaseGroup* resizeGroup = new tcu::TestCaseGroup(m_testCtx, "resize", "FBO resize tests");
1623 addChild(resizeGroup);
1624 for (int colorFmtNdx = 0; colorFmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); colorFmtNdx++)
1625 {
1626 deUint32 colorFormat = colorFormats[colorFmtNdx].format;
1627
1628 // Color-only.
1629 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++)
1630 {
1631 FboConfig config(GL_COLOR_BUFFER_BIT, objectTypes[typeNdx], colorFormat, GL_NONE, GL_NONE);
1632 resizeGroup->addChild(new ResizeTest(m_context, config));
1633 }
1634
1635 // For selected color formats tests depth & stencil variants.
1636 if (colorFormat == GL_RGBA8 || colorFormat == GL_RGBA16F)
1637 {
1638 for (int depthStencilFmtNdx = 0; depthStencilFmtNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats); depthStencilFmtNdx++)
1639 {
1640 deUint32 colorType = GL_TEXTURE_2D;
1641 bool depth = depthStencilFormats[depthStencilFmtNdx].depth;
1642 bool stencil = depthStencilFormats[depthStencilFmtNdx].stencil;
1643
1644 // Depth and stencil: both rbo and textures
1645 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++)
1646 {
1647 if (!depth && objectTypes[typeNdx] != GL_RENDERBUFFER)
1648 continue; // Not supported.
1649
1650 FboConfig config(GL_COLOR_BUFFER_BIT|(depth ? GL_DEPTH_BUFFER_BIT : 0)|(stencil ? GL_STENCIL_BUFFER_BIT : 0),
1651 colorType, colorFormat,
1652 objectTypes[typeNdx], depthStencilFormats[depthStencilFmtNdx].format);
1653 resizeGroup->addChild(new ResizeTest(m_context, config));
1654 }
1655 }
1656 }
1657 }
1658
1659 // .recreate_color
1660 tcu::TestCaseGroup* recreateColorGroup = new tcu::TestCaseGroup(m_testCtx, "recreate_color", "Recreate colorbuffer tests");
1661 addChild(recreateColorGroup);
1662 for (int colorFmtNdx = 0; colorFmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); colorFmtNdx++)
1663 {
1664 deUint32 colorFormat = colorFormats[colorFmtNdx].format;
1665 deUint32 depthStencilFormat = GL_DEPTH24_STENCIL8;
1666 deUint32 depthStencilType = GL_RENDERBUFFER;
1667
1668 // Color-only.
1669 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++)
1670 {
1671 FboConfig config(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT, objectTypes[typeNdx], colorFormat, depthStencilType, depthStencilFormat);
1672 recreateColorGroup->addChild(new RecreateBuffersTest(m_context, config, GL_COLOR_BUFFER_BIT, true /* rebind */));
1673 }
1674 }
1675
1676 // .recreate_depth_stencil
1677 tcu::TestCaseGroup* recreateDepthStencilGroup = new tcu::TestCaseGroup(m_testCtx, "recreate_depth_stencil", "Recreate depth and stencil buffers");
1678 addChild(recreateDepthStencilGroup);
1679 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats); fmtNdx++)
1680 {
1681 deUint32 colorType = GL_TEXTURE_2D;
1682 deUint32 colorFmt = GL_RGBA8;
1683 bool depth = depthStencilFormats[fmtNdx].depth;
1684 bool stencil = depthStencilFormats[fmtNdx].stencil;
1685
1686 // Depth and stencil: both rbo and textures
1687 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++)
1688 {
1689 if (!depth && objectTypes[typeNdx] != GL_RENDERBUFFER)
1690 continue;
1691
1692 FboConfig config(GL_COLOR_BUFFER_BIT|(depth ? GL_DEPTH_BUFFER_BIT : 0)|(stencil ? GL_STENCIL_BUFFER_BIT : 0), colorType, colorFmt, objectTypes[typeNdx], depthStencilFormats[fmtNdx].format);
1693 recreateDepthStencilGroup->addChild(new RecreateBuffersTest(m_context, config, (depth ? GL_DEPTH_BUFFER_BIT : 0)|(stencil ? GL_STENCIL_BUFFER_BIT : 0), true /* rebind */));
1694 }
1695 }
1696 }
1697
1698 } // Functional
1699 } // gles3
1700 } // deqp
1701