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