1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 2.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 * Notes:
24 * + Like in API tests, tcu::sgl2s::Context class is used.
25 * + ReferenceContext is used to generate reference images.
26 * + API calls can be logged \todo [pyry] Implement.
27 *//*--------------------------------------------------------------------*/
28
29 #include "es2fFboRenderTest.hpp"
30 #include "sglrContextUtil.hpp"
31 #include "sglrGLContext.hpp"
32 #include "sglrReferenceContext.hpp"
33 #include "tcuSurface.hpp"
34 #include "tcuTextureUtil.hpp"
35 #include "tcuImageCompare.hpp"
36 #include "tcuRenderTarget.hpp"
37 #include "gluPixelTransfer.hpp"
38 #include "gluTextureUtil.hpp"
39 #include "gluStrUtil.hpp"
40 #include "deRandom.hpp"
41 #include "deString.h"
42
43 #include "glwFunctions.hpp"
44 #include "glwEnums.hpp"
45
46 using std::string;
47 using std::vector;
48 using tcu::RGBA;
49 using tcu::Surface;
50 using tcu::Vec2;
51 using tcu::Vec3;
52 using tcu::Vec4;
53 using namespace glw; // GL types
54
55 namespace deqp
56 {
57 namespace gles2
58 {
59 namespace Functional
60 {
61
62 // Shaders.
63
64 class FlatColorShader : public sglr::ShaderProgram
65 {
66 public:
FlatColorShader(void)67 FlatColorShader(void)
68 : sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
69 << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
70 << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT)
71 << sglr::pdec::Uniform("u_color", glu::TYPE_FLOAT_VEC4)
72 << sglr::pdec::VertexSource("attribute highp vec4 a_position;\n"
73 "void main (void)\n"
74 "{\n"
75 " gl_Position = a_position;\n"
76 "}\n")
77 << sglr::pdec::FragmentSource("uniform mediump vec4 u_color;\n"
78 "void main (void)\n"
79 "{\n"
80 " gl_FragColor = u_color;\n"
81 "}\n"))
82 {
83 }
84
setColor(sglr::Context & gl,uint32_t program,const tcu::Vec4 & color)85 void setColor(sglr::Context &gl, uint32_t program, const tcu::Vec4 &color)
86 {
87 gl.useProgram(program);
88 gl.uniform4fv(gl.getUniformLocation(program, "u_color"), 1, color.getPtr());
89 }
90
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const91 void shadeVertices(const rr::VertexAttrib *inputs, rr::VertexPacket *const *packets, const int numPackets) const
92 {
93 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
94 packets[packetNdx]->position =
95 rr::readVertexAttribFloat(inputs[0], packets[packetNdx]->instanceNdx, packets[packetNdx]->vertexNdx);
96 }
97
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const98 void shadeFragments(rr::FragmentPacket *packets, const int numPackets,
99 const rr::FragmentShadingContext &context) const
100 {
101 const tcu::Vec4 color(m_uniforms[0].value.f4);
102
103 DE_UNREF(packets);
104
105 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
106 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
107 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
108 }
109 };
110
111 class SingleTex2DShader : public sglr::ShaderProgram
112 {
113 public:
SingleTex2DShader(void)114 SingleTex2DShader(void)
115 : sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
116 << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
117 << sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT)
118 << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
119 << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT)
120 << sglr::pdec::Uniform("u_sampler0", glu::TYPE_SAMPLER_2D)
121 << sglr::pdec::VertexSource("attribute highp vec4 a_position;\n"
122 "attribute mediump vec2 a_coord;\n"
123 "varying mediump vec2 v_coord;\n"
124 "void main (void)\n"
125 "{\n"
126 " gl_Position = a_position;\n"
127 " v_coord = a_coord;\n"
128 "}\n")
129 << sglr::pdec::FragmentSource("uniform sampler2D u_sampler0;\n"
130 "varying mediump vec2 v_coord;\n"
131 "void main (void)\n"
132 "{\n"
133 " gl_FragColor = texture2D(u_sampler0, v_coord);\n"
134 "}\n"))
135 {
136 }
137
setUnit(sglr::Context & gl,uint32_t program,int unitNdx)138 void setUnit(sglr::Context &gl, uint32_t program, int unitNdx)
139 {
140 gl.useProgram(program);
141 gl.uniform1i(gl.getUniformLocation(program, "u_sampler0"), unitNdx);
142 }
143
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const144 void shadeVertices(const rr::VertexAttrib *inputs, rr::VertexPacket *const *packets, const int numPackets) const
145 {
146 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
147 {
148 rr::VertexPacket &packet = *packets[packetNdx];
149
150 packet.position = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
151 packet.outputs[0] = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
152 }
153 }
154
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const155 void shadeFragments(rr::FragmentPacket *packets, const int numPackets,
156 const rr::FragmentShadingContext &context) const
157 {
158 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
159 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
160 {
161 const tcu::Vec4 v_coord = rr::readVarying<float>(packets[packetNdx], context, 0, fragNdx);
162 const float lod = 0.0f;
163
164 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0,
165 this->m_uniforms[0].sampler.tex2D->sample(v_coord.x(), v_coord.y(), lod));
166 }
167 }
168 };
169
170 class MixTexturesShader : public sglr::ShaderProgram
171 {
172 public:
MixTexturesShader(void)173 MixTexturesShader(void)
174 : sglr::ShaderProgram(
175 sglr::pdec::ShaderProgramDeclaration()
176 << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
177 << sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT)
178 << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
179 << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT)
180 << sglr::pdec::Uniform("u_sampler0", glu::TYPE_SAMPLER_2D)
181 << sglr::pdec::Uniform("u_sampler1", glu::TYPE_SAMPLER_2D)
182 << sglr::pdec::VertexSource("attribute highp vec4 a_position;\n"
183 "attribute mediump vec2 a_coord;\n"
184 "varying mediump vec2 v_coord;\n"
185 "void main (void)\n"
186 "{\n"
187 " gl_Position = a_position;\n"
188 " v_coord = a_coord;\n"
189 "}\n")
190 << sglr::pdec::FragmentSource(
191 "uniform sampler2D u_sampler0;\n"
192 "uniform sampler2D u_sampler1;\n"
193 "varying mediump vec2 v_coord;\n"
194 "void main (void)\n"
195 "{\n"
196 " gl_FragColor = texture2D(u_sampler0, v_coord)*0.5 + texture2D(u_sampler1, v_coord)*0.5;\n"
197 "}\n"))
198 {
199 }
200
setUnits(sglr::Context & gl,uint32_t program,int unit0,int unit1)201 void setUnits(sglr::Context &gl, uint32_t program, int unit0, int unit1)
202 {
203 gl.useProgram(program);
204 gl.uniform1i(gl.getUniformLocation(program, "u_sampler0"), unit0);
205 gl.uniform1i(gl.getUniformLocation(program, "u_sampler1"), unit1);
206 }
207
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const208 void shadeVertices(const rr::VertexAttrib *inputs, rr::VertexPacket *const *packets, const int numPackets) const
209 {
210 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
211 {
212 rr::VertexPacket &packet = *packets[packetNdx];
213
214 packet.position = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
215 packet.outputs[0] = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
216 }
217 }
218
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const219 void shadeFragments(rr::FragmentPacket *packets, const int numPackets,
220 const rr::FragmentShadingContext &context) const
221 {
222 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
223 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
224 {
225 const tcu::Vec4 v_coord = rr::readVarying<float>(packets[packetNdx], context, 0, fragNdx);
226 const float lod = 0.0f;
227
228 rr::writeFragmentOutput(
229 context, packetNdx, fragNdx, 0,
230 this->m_uniforms[0].sampler.tex2D->sample(v_coord.x(), v_coord.y(), lod) * 0.5f +
231 this->m_uniforms[1].sampler.tex2D->sample(v_coord.x(), v_coord.y(), lod) * 0.5f);
232 }
233 }
234 };
235
236 // Framebuffer config.
237
238 class FboConfig
239 {
240 public:
FboConfig(void)241 FboConfig(void)
242 : colorbufferType(GL_NONE)
243 , colorbufferFormat(GL_NONE)
244 , depthbufferType(GL_NONE)
245 , depthbufferFormat(GL_NONE)
246 , stencilbufferType(GL_NONE)
247 , stencilbufferFormat(GL_NONE)
248 {
249 }
250
251 std::string getName(void) const;
252
253 GLenum colorbufferType; //!< GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP, GL_RENDERBUFFER
254 GLenum colorbufferFormat; //!< Internal format for color buffer texture or renderbuffer
255
256 GLenum depthbufferType; //!< GL_RENDERBUFFER
257 GLenum depthbufferFormat;
258
259 GLenum stencilbufferType; //!< GL_RENDERBUFFER
260 GLenum stencilbufferFormat;
261
262 private:
263 static const char *getFormatName(GLenum format);
264 };
265
getFormatName(GLenum format)266 const char *FboConfig::getFormatName(GLenum format)
267 {
268 switch (format)
269 {
270 case GL_RGB:
271 return "rgb";
272 case GL_RGBA:
273 return "rgba";
274 case GL_BGRA:
275 return "bgra";
276 case GL_ALPHA:
277 return "alpha";
278 case GL_LUMINANCE:
279 return "luminance";
280 case GL_LUMINANCE_ALPHA:
281 return "luminance_alpha";
282 case GL_RGB565:
283 return "rgb565";
284 case GL_RGB5_A1:
285 return "rgb5_a1";
286 case GL_RGBA4:
287 return "rgba4";
288 case GL_RGBA16F:
289 return "rgba16f";
290 case GL_RGB16F:
291 return "rgb16f";
292 case GL_DEPTH_COMPONENT16:
293 return "depth_component16";
294 case GL_STENCIL_INDEX8:
295 return "stencil_index8";
296 default:
297 DE_ASSERT(false);
298 return nullptr;
299 }
300 }
301
getName(void) const302 std::string FboConfig::getName(void) const
303 {
304 std::string name = "";
305
306 if (colorbufferType != GL_NONE)
307 {
308 switch (colorbufferType)
309 {
310 case GL_TEXTURE_2D:
311 name += "tex2d_";
312 break;
313 case GL_TEXTURE_CUBE_MAP:
314 name += "texcube_";
315 break;
316 case GL_RENDERBUFFER:
317 name += "rbo_";
318 break;
319 default:
320 DE_ASSERT(false);
321 break;
322 }
323 name += getFormatName(colorbufferFormat);
324 }
325
326 if (depthbufferType != GL_NONE)
327 {
328 DE_ASSERT(depthbufferType == GL_RENDERBUFFER);
329 if (name.length() > 0)
330 name += "_";
331 name += getFormatName(depthbufferFormat);
332 }
333
334 if (stencilbufferType != GL_NONE)
335 {
336 DE_ASSERT(stencilbufferType == GL_RENDERBUFFER);
337 if (name.length() > 0)
338 name += "_";
339 name += getFormatName(stencilbufferFormat);
340 }
341
342 return name;
343 }
344
345 class FboIncompleteException : public tcu::TestError
346 {
347 public:
348 FboIncompleteException(const FboConfig &config, GLenum reason, const char *file, int line);
~FboIncompleteException(void)349 virtual ~FboIncompleteException(void) throw()
350 {
351 }
352
getConfig(void) const353 const FboConfig &getConfig(void) const
354 {
355 return m_config;
356 }
getReason(void) const357 GLenum getReason(void) const
358 {
359 return m_reason;
360 }
361
362 private:
363 FboConfig m_config;
364 GLenum m_reason;
365 };
366
getFboIncompleteReasonName(GLenum reason)367 static const char *getFboIncompleteReasonName(GLenum reason)
368 {
369 switch (reason)
370 {
371 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
372 return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
373 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
374 return "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
375 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
376 return "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS";
377 case GL_FRAMEBUFFER_UNSUPPORTED:
378 return "GL_FRAMEBUFFER_UNSUPPORTED";
379 case GL_FRAMEBUFFER_COMPLETE:
380 return "GL_FRAMEBUFFER_COMPLETE";
381 default:
382 return "UNKNOWN";
383 }
384 }
385
FboIncompleteException(const FboConfig & config,GLenum reason,const char * file,int line)386 FboIncompleteException::FboIncompleteException(const FboConfig &config, GLenum reason, const char *file, int line)
387 : TestError("Framebuffer is not complete", getFboIncompleteReasonName(reason), file, line)
388 , m_config(config)
389 , m_reason(reason)
390 {
391 }
392
393 class Framebuffer
394 {
395 public:
396 Framebuffer(sglr::Context &context, const FboConfig &config, int width, int height, uint32_t fbo = 0,
397 uint32_t colorbuffer = 0, uint32_t depthbuffer = 0, uint32_t stencilbuffer = 0);
398 ~Framebuffer(void);
399
getConfig(void) const400 const FboConfig &getConfig(void) const
401 {
402 return m_config;
403 }
getFramebuffer(void) const404 uint32_t getFramebuffer(void) const
405 {
406 return m_framebuffer;
407 }
getColorbuffer(void) const408 uint32_t getColorbuffer(void) const
409 {
410 return m_colorbuffer;
411 }
getDepthbuffer(void) const412 uint32_t getDepthbuffer(void) const
413 {
414 return m_depthbuffer;
415 }
getStencilbuffer(void) const416 uint32_t getStencilbuffer(void) const
417 {
418 return m_stencilbuffer;
419 }
420
421 void checkCompleteness(void);
422
423 private:
424 void createRbo(uint32_t &name, GLenum format, int width, int height);
425 void destroyBuffer(uint32_t name, GLenum type);
426
427 FboConfig m_config;
428 sglr::Context &m_context;
429 uint32_t m_framebuffer;
430 uint32_t m_colorbuffer;
431 uint32_t m_depthbuffer;
432 uint32_t m_stencilbuffer;
433 };
434
isExtensionSupported(sglr::Context & context,const char * name)435 static bool isExtensionSupported(sglr::Context &context, const char *name)
436 {
437 std::istringstream extensions(context.getString(GL_EXTENSIONS));
438 std::string extension;
439
440 while (std::getline(extensions, extension, ' '))
441 {
442 if (extension == name)
443 return true;
444 }
445
446 return false;
447 }
448
checkColorFormatSupport(sglr::Context & context,uint32_t sizedFormat)449 static void checkColorFormatSupport(sglr::Context &context, uint32_t sizedFormat)
450 {
451 switch (sizedFormat)
452 {
453 case GL_RGBA16F:
454 case GL_RGB16F:
455 case GL_RG16F:
456 case GL_R16F:
457 if (!isExtensionSupported(context, "GL_EXT_color_buffer_half_float"))
458 throw tcu::NotSupportedError("GL_EXT_color_buffer_half_float is not supported");
459 break;
460
461 case GL_BGRA:
462 case GL_BGRA8_EXT:
463 if (!isExtensionSupported(context, "GL_EXT_texture_format_BGRA8888"))
464 throw tcu::NotSupportedError("GL_EXT_texture_format_BGRA8888 is not supported");
465 break;
466
467 default:
468 break;
469 }
470 }
471
Framebuffer(sglr::Context & context,const FboConfig & config,int width,int height,uint32_t fbo,uint32_t colorbuffer,uint32_t depthbuffer,uint32_t stencilbuffer)472 Framebuffer::Framebuffer(sglr::Context &context, const FboConfig &config, int width, int height, uint32_t fbo,
473 uint32_t colorbuffer, uint32_t depthbuffer, uint32_t stencilbuffer)
474 : m_config(config)
475 , m_context(context)
476 , m_framebuffer(fbo)
477 , m_colorbuffer(colorbuffer)
478 , m_depthbuffer(depthbuffer)
479 , m_stencilbuffer(stencilbuffer)
480 {
481 // Verify that color format is supported
482 checkColorFormatSupport(context, config.colorbufferFormat);
483
484 if (m_framebuffer == 0)
485 context.genFramebuffers(1, &m_framebuffer);
486 context.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
487
488 switch (m_config.colorbufferType)
489 {
490 case GL_TEXTURE_2D:
491 if (m_colorbuffer == 0)
492 context.genTextures(1, &m_colorbuffer);
493 context.bindTexture(GL_TEXTURE_2D, m_colorbuffer);
494 context.texImage2D(GL_TEXTURE_2D, 0, m_config.colorbufferFormat, width, height);
495 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
496
497 if (!deIsPowerOfTwo32(width) || !deIsPowerOfTwo32(height))
498 {
499 // Set wrap mode to clamp for NPOT FBOs
500 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
501 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
502 }
503
504 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorbuffer, 0);
505 break;
506
507 case GL_TEXTURE_CUBE_MAP:
508 DE_FATAL("TODO");
509 break;
510
511 case GL_RENDERBUFFER:
512 createRbo(m_colorbuffer, m_config.colorbufferFormat, width, height);
513 context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_colorbuffer);
514 break;
515
516 default:
517 DE_ASSERT(m_config.colorbufferType == GL_NONE);
518 break;
519 }
520
521 if (m_config.depthbufferType == GL_RENDERBUFFER)
522 {
523 createRbo(m_depthbuffer, m_config.depthbufferFormat, width, height);
524 context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthbuffer);
525 }
526 else
527 DE_ASSERT(m_config.depthbufferType == GL_NONE);
528
529 if (m_config.stencilbufferType == GL_RENDERBUFFER)
530 {
531 createRbo(m_stencilbuffer, m_config.stencilbufferFormat, width, height);
532 context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_stencilbuffer);
533 }
534 else
535 DE_ASSERT(m_config.stencilbufferType == GL_NONE);
536
537 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
538 }
539
~Framebuffer(void)540 Framebuffer::~Framebuffer(void)
541 {
542 m_context.deleteFramebuffers(1, &m_framebuffer);
543 destroyBuffer(m_colorbuffer, m_config.colorbufferType);
544 destroyBuffer(m_depthbuffer, m_config.depthbufferType);
545 destroyBuffer(m_stencilbuffer, m_config.stencilbufferType);
546 }
547
checkCompleteness(void)548 void Framebuffer::checkCompleteness(void)
549 {
550 m_context.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
551 GLenum status = m_context.checkFramebufferStatus(GL_FRAMEBUFFER);
552 m_context.bindFramebuffer(GL_FRAMEBUFFER, 0);
553 if (status != GL_FRAMEBUFFER_COMPLETE)
554 throw FboIncompleteException(m_config, status, __FILE__, __LINE__);
555 }
556
createRbo(uint32_t & name,GLenum format,int width,int height)557 void Framebuffer::createRbo(uint32_t &name, GLenum format, int width, int height)
558 {
559 if (name == 0)
560 m_context.genRenderbuffers(1, &name);
561 m_context.bindRenderbuffer(GL_RENDERBUFFER, name);
562 m_context.renderbufferStorage(GL_RENDERBUFFER, format, width, height);
563 }
564
destroyBuffer(uint32_t name,GLenum type)565 void Framebuffer::destroyBuffer(uint32_t name, GLenum type)
566 {
567 if (type == GL_TEXTURE_2D || type == GL_TEXTURE_CUBE_MAP)
568 m_context.deleteTextures(1, &name);
569 else if (type == GL_RENDERBUFFER)
570 m_context.deleteRenderbuffers(1, &name);
571 else
572 DE_ASSERT(type == GL_NONE);
573 }
574
createMetaballsTex2D(sglr::Context & context,uint32_t name,GLenum format,GLenum dataType,int width,int height)575 static void createMetaballsTex2D(sglr::Context &context, uint32_t name, GLenum format, GLenum dataType, int width,
576 int height)
577 {
578 tcu::TextureFormat texFormat = glu::mapGLTransferFormat(format, dataType);
579 tcu::TextureLevel level(texFormat, width, height);
580
581 tcu::fillWithMetaballs(level.getAccess(), 5, name ^ width ^ height);
582
583 context.bindTexture(GL_TEXTURE_2D, name);
584 context.texImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, dataType, level.getAccess().getDataPtr());
585 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
586 }
587
createQuadsTex2D(sglr::Context & context,uint32_t name,GLenum format,GLenum dataType,int width,int height)588 static void createQuadsTex2D(sglr::Context &context, uint32_t name, GLenum format, GLenum dataType, int width,
589 int height)
590 {
591 tcu::TextureFormat texFormat = glu::mapGLTransferFormat(format, dataType);
592 tcu::TextureLevel level(texFormat, width, height);
593
594 tcu::fillWithRGBAQuads(level.getAccess());
595
596 context.bindTexture(GL_TEXTURE_2D, name);
597 context.texImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, dataType, level.getAccess().getDataPtr());
598 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
599 }
600
601 class FboRenderCase : public TestCase
602 {
603 public:
604 FboRenderCase(Context &context, const char *name, const char *description, const FboConfig &config);
~FboRenderCase(void)605 virtual ~FboRenderCase(void)
606 {
607 }
608
609 virtual IterateResult iterate(void);
610 virtual void render(sglr::Context &fboContext, Surface &dst) = 0;
611
getConfig(void) const612 const FboConfig &getConfig(void) const
613 {
614 return m_config;
615 }
616
isConfigSupported(const FboConfig & config)617 static bool isConfigSupported(const FboConfig &config)
618 {
619 DE_UNREF(config);
620 return true;
621 }
622
623 private:
624 FboConfig m_config;
625 };
626
FboRenderCase(Context & context,const char * name,const char * description,const FboConfig & config)627 FboRenderCase::FboRenderCase(Context &context, const char *name, const char *description, const FboConfig &config)
628 : TestCase(context, name, description)
629 , m_config(config)
630 {
631 }
632
iterate(void)633 TestCase::IterateResult FboRenderCase::iterate(void)
634 {
635 Vec4 clearColor(0.125f, 0.25f, 0.5f, 1.0f);
636 glu::RenderContext &renderCtx = m_context.getRenderContext();
637 const tcu::RenderTarget &renderTarget = m_context.getRenderTarget();
638 tcu::TestLog &log = m_testCtx.getLog();
639 const char *failReason = nullptr;
640
641 // Position & size for context
642 deRandom rnd;
643 deRandom_init(&rnd, deStringHash(getName()));
644
645 int width = deMin32(renderTarget.getWidth(), 128);
646 int height = deMin32(renderTarget.getHeight(), 128);
647 int xMax = renderTarget.getWidth() - width + 1;
648 int yMax = renderTarget.getHeight() - height + 1;
649 int x = deRandom_getUint32(&rnd) % xMax;
650 int y = deRandom_getUint32(&rnd) % yMax;
651
652 tcu::Surface gles2Frame(width, height);
653 tcu::Surface refFrame(width, height);
654 GLenum gles2Error;
655 GLenum refError;
656
657 // Render using GLES2
658 try
659 {
660 sglr::GLContext context(renderCtx, log, sglr::GLCONTEXT_LOG_CALLS, tcu::IVec4(x, y, width, height));
661
662 context.clearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
663 context.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
664
665 render(context, gles2Frame); // Call actual render func
666 gles2Error = context.getError();
667 }
668 catch (const FboIncompleteException &e)
669 {
670 if (e.getReason() == GL_FRAMEBUFFER_UNSUPPORTED)
671 {
672 // Mark test case as unsupported
673 log << e;
674 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported");
675 return STOP;
676 }
677 else
678 throw; // Propagate error
679 }
680
681 // Render reference image
682 {
683 sglr::ReferenceContextBuffers buffers(
684 tcu::PixelFormat(8, 8, 8, renderTarget.getPixelFormat().alphaBits ? 8 : 0), renderTarget.getDepthBits(),
685 renderTarget.getStencilBits(), width, height);
686 sglr::ReferenceContext context(sglr::ReferenceContextLimits(renderCtx), buffers.getColorbuffer(),
687 buffers.getDepthbuffer(), buffers.getStencilbuffer());
688
689 context.clearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
690 context.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
691
692 render(context, refFrame);
693 refError = context.getError();
694 }
695
696 // Compare error codes
697 bool errorCodesOk = (gles2Error == refError);
698
699 if (!errorCodesOk)
700 {
701 log << tcu::TestLog::Message << "Error code mismatch: got " << glu::getErrorStr(gles2Error) << ", expected "
702 << glu::getErrorStr(refError) << tcu::TestLog::EndMessage;
703 failReason = "Got unexpected error";
704 }
705
706 // Compare images
707 const float threshold = 0.05f;
708 bool imagesOk = tcu::fuzzyCompare(log, "ComparisonResult", "Image comparison result", refFrame, gles2Frame,
709 threshold, tcu::COMPARE_LOG_RESULT);
710
711 if (!imagesOk && !failReason)
712 failReason = "Image comparison failed";
713
714 // Store test result
715 bool isOk = errorCodesOk && imagesOk;
716 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, isOk ? "Pass" : failReason);
717
718 return STOP;
719 }
720
721 namespace FboCases
722 {
723
724 class ColorClearsTest : public FboRenderCase
725 {
726 public:
727 ColorClearsTest(Context &context, const FboConfig &config);
~ColorClearsTest(void)728 ~ColorClearsTest(void)
729 {
730 }
731
732 void render(sglr::Context &context, Surface &dst);
733 };
734
ColorClearsTest(Context & context,const FboConfig & config)735 ColorClearsTest::ColorClearsTest(Context &context, const FboConfig &config)
736 : FboRenderCase(context, config.getName().c_str(), "Color buffer clears", config)
737 {
738 }
739
render(sglr::Context & context,Surface & dst)740 void ColorClearsTest::render(sglr::Context &context, Surface &dst)
741 {
742 int width = 128;
743 int height = 128;
744 deRandom rnd;
745
746 deRandom_init(&rnd, 0);
747
748 // Create framebuffer
749 Framebuffer fbo(context, getConfig(), width, height);
750 fbo.checkCompleteness();
751
752 // Clear fbo
753 context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
754 context.viewport(0, 0, width, height);
755 context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
756 context.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
757
758 // Enable scissor test.
759 context.enable(GL_SCISSOR_TEST);
760
761 // Do 10 random color clears
762 for (int i = 0; i < 15; i++)
763 {
764 int cX = (int)(deRandom_getUint32(&rnd) & 0x7fffffff) % width;
765 int cY = (int)(deRandom_getUint32(&rnd) & 0x7fffffff) % height;
766 int cWidth = (int)(deRandom_getUint32(&rnd) & 0x7fffffff) % (width - cX);
767 int cHeight = (int)(deRandom_getUint32(&rnd) & 0x7fffffff) % (height - cY);
768 Vec4 color = RGBA(deRandom_getUint32(&rnd)).toVec();
769
770 context.scissor(cX, cY, cWidth, cHeight);
771 context.clearColor(color.x(), color.y(), color.z(), color.w());
772 context.clear(GL_COLOR_BUFFER_BIT);
773 }
774
775 // Disable scissor.
776 context.disable(GL_SCISSOR_TEST);
777
778 if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
779 {
780 // Unbind fbo
781 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
782
783 // Draw to screen
784 SingleTex2DShader shader;
785 uint32_t shaderID = context.createProgram(&shader);
786
787 shader.setUnit(context, shaderID, 0);
788
789 context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
790 context.viewport(0, 0, context.getWidth(), context.getHeight());
791 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
792
793 // Read from screen
794 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
795 }
796 else
797 {
798 // clear alpha channel for GL_RGB5_A1 format because test
799 // thresholds for the alpha channel do not account for dithering
800 if (getConfig().colorbufferFormat == GL_RGB5_A1)
801 {
802 context.colorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
803 context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
804 context.clear(GL_COLOR_BUFFER_BIT);
805 context.colorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
806 }
807
808 // Read from fbo
809 context.readPixels(dst, 0, 0, width, height);
810 }
811 }
812
813 class IntersectingQuadsTest : public FboRenderCase
814 {
815 public:
816 IntersectingQuadsTest(Context &context, const FboConfig &config, bool npot = false);
~IntersectingQuadsTest(void)817 virtual ~IntersectingQuadsTest(void)
818 {
819 }
820
821 virtual void render(sglr::Context &context, Surface &dst);
822
823 static bool isConfigSupported(const FboConfig &config);
824
825 private:
826 int m_fboWidth;
827 int m_fboHeight;
828 };
829
830 class IntersectingQuadsNpotTest : public IntersectingQuadsTest
831 {
832 public:
IntersectingQuadsNpotTest(Context & context,const FboConfig & config)833 IntersectingQuadsNpotTest(Context &context, const FboConfig &config) : IntersectingQuadsTest(context, config, true)
834 {
835 }
836 };
837
IntersectingQuadsTest(Context & context,const FboConfig & config,bool npot)838 IntersectingQuadsTest::IntersectingQuadsTest(Context &context, const FboConfig &config, bool npot)
839 : FboRenderCase(context, (string(npot ? "npot_" : "") + config.getName()).c_str(), "Intersecting textured quads",
840 config)
841 , m_fboWidth(npot ? 127 : 128)
842 , m_fboHeight(npot ? 95 : 128)
843 {
844 }
845
isConfigSupported(const FboConfig & config)846 bool IntersectingQuadsTest::isConfigSupported(const FboConfig &config)
847 {
848 // \note Disabled for stencil configurations since doesn't exercise stencil buffer
849 return config.depthbufferType != GL_NONE && config.stencilbufferType == GL_NONE;
850 }
851
render(sglr::Context & ctx,Surface & dst)852 void IntersectingQuadsTest::render(sglr::Context &ctx, Surface &dst)
853 {
854 SingleTex2DShader texShader;
855 uint32_t texShaderID = ctx.createProgram(&texShader);
856
857 uint32_t metaballsTex = 1;
858 uint32_t quadsTex = 2;
859
860 createMetaballsTex2D(ctx, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
861 createQuadsTex2D(ctx, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
862
863 int width = m_fboWidth;
864 int height = m_fboHeight;
865 Framebuffer fbo(ctx, getConfig(), width, height);
866 fbo.checkCompleteness();
867
868 // Setup shaders
869 texShader.setUnit(ctx, texShaderID, 0);
870
871 // Draw scene
872 ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
873 ctx.viewport(0, 0, width, height);
874 ctx.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
875 ctx.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
876
877 ctx.enable(GL_DEPTH_TEST);
878
879 ctx.bindTexture(GL_TEXTURE_2D, metaballsTex);
880 sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));
881
882 ctx.bindTexture(GL_TEXTURE_2D, quadsTex);
883 sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 1.0f), Vec3(1.0f, 1.0f, -1.0f));
884
885 ctx.disable(GL_DEPTH_TEST);
886
887 if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
888 {
889 // Unbind fbo
890 ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);
891
892 // Draw to screen
893 ctx.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
894 ctx.viewport(0, 0, ctx.getWidth(), ctx.getHeight());
895 sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
896
897 // Read from screen
898 ctx.readPixels(dst, 0, 0, ctx.getWidth(), ctx.getHeight());
899 }
900 else
901 {
902 // Read from fbo
903 ctx.readPixels(dst, 0, 0, width, height);
904 }
905 }
906
907 class MixTest : public FboRenderCase
908 {
909 public:
910 MixTest(Context &context, const FboConfig &config, bool npot = false);
~MixTest(void)911 virtual ~MixTest(void)
912 {
913 }
914
915 void render(sglr::Context &context, Surface &dst);
916
917 static bool isConfigSupported(const FboConfig &config);
918
919 private:
920 int m_fboAWidth;
921 int m_fboAHeight;
922 int m_fboBWidth;
923 int m_fboBHeight;
924 };
925
926 class MixNpotTest : public MixTest
927 {
928 public:
MixNpotTest(Context & context,const FboConfig & config)929 MixNpotTest(Context &context, const FboConfig &config) : MixTest(context, config, true)
930 {
931 }
932 };
933
MixTest(Context & context,const FboConfig & config,bool npot)934 MixTest::MixTest(Context &context, const FboConfig &config, bool npot)
935 : FboRenderCase(context, (string(npot ? "mix_npot_" : "mix_") + config.getName()).c_str(),
936 "Use two fbos as sources in draw operation", config)
937 , m_fboAWidth(npot ? 127 : 128)
938 , m_fboAHeight(npot ? 95 : 128)
939 , m_fboBWidth(npot ? 55 : 64)
940 , m_fboBHeight(npot ? 63 : 64)
941 {
942 }
943
isConfigSupported(const FboConfig & config)944 bool MixTest::isConfigSupported(const FboConfig &config)
945 {
946 // \note Disabled for stencil configurations since doesn't exercise stencil buffer
947 return config.colorbufferType == GL_TEXTURE_2D && config.stencilbufferType == GL_NONE;
948 }
949
render(sglr::Context & context,Surface & dst)950 void MixTest::render(sglr::Context &context, Surface &dst)
951 {
952 SingleTex2DShader singleTexShader;
953 MixTexturesShader mixShader;
954
955 uint32_t singleTexShaderID = context.createProgram(&singleTexShader);
956 uint32_t mixShaderID = context.createProgram(&mixShader);
957
958 // Texture with metaballs
959 uint32_t metaballsTex = 1;
960 context.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
961 createMetaballsTex2D(context, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
962
963 // Setup shaders
964 singleTexShader.setUnit(context, singleTexShaderID, 0);
965 mixShader.setUnits(context, mixShaderID, 0, 1);
966
967 // Fbo, quad with metaballs texture
968 Framebuffer fboA(context, getConfig(), m_fboAWidth, m_fboAHeight);
969 fboA.checkCompleteness();
970 context.bindFramebuffer(GL_FRAMEBUFFER, fboA.getFramebuffer());
971 context.viewport(0, 0, m_fboAWidth, m_fboAHeight);
972 context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
973 context.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
974 context.bindTexture(GL_TEXTURE_2D, metaballsTex);
975 sglr::drawQuad(context, singleTexShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
976
977 // Fbo, color clears
978 Framebuffer fboB(context, getConfig(), m_fboBWidth, m_fboBHeight);
979 fboB.checkCompleteness();
980 context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
981 context.viewport(0, 0, m_fboBWidth, m_fboBHeight);
982 context.enable(GL_SCISSOR_TEST);
983 context.scissor(0, 0, 32, 64);
984 context.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
985 context.clear(GL_COLOR_BUFFER_BIT);
986 context.scissor(32, 0, 32, 64);
987 context.clearColor(0.0f, 1.0f, 0.0f, 1.0f);
988 context.clear(GL_COLOR_BUFFER_BIT);
989 context.disable(GL_SCISSOR_TEST);
990
991 // Final mix op
992 context.activeTexture(GL_TEXTURE0);
993 context.bindTexture(GL_TEXTURE_2D, fboA.getColorbuffer());
994 context.activeTexture(GL_TEXTURE1);
995 context.bindTexture(GL_TEXTURE_2D, fboB.getColorbuffer());
996 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
997 context.viewport(0, 0, context.getWidth(), context.getHeight());
998 sglr::drawQuad(context, mixShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
999
1000 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
1001 }
1002
1003 class BlendTest : public FboRenderCase
1004 {
1005 public:
1006 BlendTest(Context &context, const FboConfig &config, bool npot = false);
~BlendTest(void)1007 virtual ~BlendTest(void)
1008 {
1009 }
1010
1011 void render(sglr::Context &context, Surface &dst);
1012
1013 static bool isConfigSupported(const FboConfig &config);
1014
1015 private:
1016 int m_fboWidth;
1017 int m_fboHeight;
1018 };
1019
1020 class BlendNpotTest : public BlendTest
1021 {
1022 public:
BlendNpotTest(Context & context,const FboConfig & config)1023 BlendNpotTest(Context &context, const FboConfig &config) : BlendTest(context, config, true)
1024 {
1025 }
1026 };
1027
BlendTest(Context & context,const FboConfig & config,bool npot)1028 BlendTest::BlendTest(Context &context, const FboConfig &config, bool npot)
1029 : FboRenderCase(context, (string(npot ? "blend_npot_" : "blend_") + config.getName()).c_str(), "Blend to fbo",
1030 config)
1031 , m_fboWidth(npot ? 111 : 128)
1032 , m_fboHeight(npot ? 122 : 128)
1033 {
1034 }
1035
isConfigSupported(const FboConfig & config)1036 bool BlendTest::isConfigSupported(const FboConfig &config)
1037 {
1038 // \note Disabled for stencil configurations since doesn't exercise stencil buffer
1039 return config.stencilbufferType == GL_NONE;
1040 }
1041
render(sglr::Context & context,Surface & dst)1042 void BlendTest::render(sglr::Context &context, Surface &dst)
1043 {
1044 SingleTex2DShader shader;
1045 uint32_t shaderID = context.createProgram(&shader);
1046 int width = m_fboWidth;
1047 int height = m_fboHeight;
1048 uint32_t metaballsTex = 1;
1049
1050 createMetaballsTex2D(context, metaballsTex, GL_RGBA, GL_UNSIGNED_BYTE, 64, 64);
1051
1052 Framebuffer fbo(context, getConfig(), width, height);
1053 fbo.checkCompleteness();
1054
1055 shader.setUnit(context, shaderID, 0);
1056
1057 context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
1058 context.viewport(0, 0, width, height);
1059 context.bindTexture(GL_TEXTURE_2D, metaballsTex);
1060 context.clearColor(0.6f, 0.0f, 0.6f, 1.0f);
1061 context.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1062
1063 context.enable(GL_BLEND);
1064 context.blendEquation(GL_FUNC_ADD);
1065 context.blendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
1066 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1067 context.disable(GL_BLEND);
1068
1069 if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
1070 {
1071 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1072 context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
1073 context.viewport(0, 0, context.getWidth(), context.getHeight());
1074 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1075 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
1076 }
1077 else
1078 context.readPixels(dst, 0, 0, width, height);
1079 }
1080
1081 class StencilClearsTest : public FboRenderCase
1082 {
1083 public:
1084 StencilClearsTest(Context &context, const FboConfig &config);
~StencilClearsTest(void)1085 virtual ~StencilClearsTest(void)
1086 {
1087 }
1088
1089 void render(sglr::Context &context, Surface &dst);
1090
1091 static bool isConfigSupported(const FboConfig &config);
1092 };
1093
StencilClearsTest(Context & context,const FboConfig & config)1094 StencilClearsTest::StencilClearsTest(Context &context, const FboConfig &config)
1095 : FboRenderCase(context, config.getName().c_str(), "Stencil clears", config)
1096 {
1097 }
1098
render(sglr::Context & context,Surface & dst)1099 void StencilClearsTest::render(sglr::Context &context, Surface &dst)
1100 {
1101 SingleTex2DShader shader;
1102 uint32_t shaderID = context.createProgram(&shader);
1103 int width = 128;
1104 int height = 128;
1105 uint32_t quadsTex = 1;
1106 uint32_t metaballsTex = 2;
1107
1108 createQuadsTex2D(context, quadsTex, GL_RGBA, GL_UNSIGNED_BYTE, width, height);
1109 createMetaballsTex2D(context, metaballsTex, GL_RGBA, GL_UNSIGNED_BYTE, width, height);
1110
1111 Framebuffer fbo(context, getConfig(), width, height);
1112 fbo.checkCompleteness();
1113
1114 // Bind framebuffer and clear
1115 context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
1116 context.viewport(0, 0, width, height);
1117 context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
1118 context.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1119
1120 // Do stencil clears
1121 context.enable(GL_SCISSOR_TEST);
1122 context.scissor(10, 16, 32, 120);
1123 context.clearStencil(1);
1124 context.clear(GL_STENCIL_BUFFER_BIT);
1125 context.scissor(16, 32, 100, 64);
1126 context.clearStencil(2);
1127 context.clear(GL_STENCIL_BUFFER_BIT);
1128 context.disable(GL_SCISSOR_TEST);
1129
1130 // Draw 2 textures with stecil tests
1131 context.activeTexture(GL_TEXTURE0);
1132 context.bindTexture(GL_TEXTURE_2D, quadsTex);
1133 context.activeTexture(GL_TEXTURE1);
1134 context.bindTexture(GL_TEXTURE_2D, metaballsTex);
1135
1136 context.enable(GL_STENCIL_TEST);
1137 context.stencilFunc(GL_EQUAL, 1, 0xffffffffu);
1138 shader.setUnit(context, shaderID, 0);
1139 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1140
1141 context.stencilFunc(GL_EQUAL, 2, 0xffffffffu);
1142 shader.setUnit(context, shaderID, 1);
1143 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1144
1145 context.disable(GL_STENCIL_TEST);
1146
1147 if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
1148 {
1149 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1150 context.activeTexture(GL_TEXTURE0);
1151 context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
1152 context.viewport(0, 0, context.getWidth(), context.getHeight());
1153 shader.setUnit(context, shaderID, 0);
1154 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1155 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
1156 }
1157 else
1158 {
1159 // clear alpha channel for GL_RGB5_A1 format because test
1160 // thresholds for the alpha channel do not account for dithering
1161 if (getConfig().colorbufferFormat == GL_RGB5_A1)
1162 {
1163 context.colorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
1164 context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
1165 context.clear(GL_COLOR_BUFFER_BIT);
1166 context.colorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1167 }
1168
1169 context.readPixels(dst, 0, 0, width, height);
1170 }
1171 }
1172
isConfigSupported(const FboConfig & config)1173 bool StencilClearsTest::isConfigSupported(const FboConfig &config)
1174 {
1175 return config.stencilbufferType != GL_NONE;
1176 }
1177
1178 class StencilTest : public FboRenderCase
1179 {
1180 public:
1181 StencilTest(Context &context, const FboConfig &config, bool npot = false);
~StencilTest(void)1182 virtual ~StencilTest(void)
1183 {
1184 }
1185
1186 void render(sglr::Context &context, Surface &dst);
1187
1188 static bool isConfigSupported(const FboConfig &config);
1189
1190 private:
1191 int m_fboWidth;
1192 int m_fboHeight;
1193 };
1194
1195 class StencilNpotTest : public StencilTest
1196 {
1197 public:
StencilNpotTest(Context & context,const FboConfig & config)1198 StencilNpotTest(Context &context, const FboConfig &config) : StencilTest(context, config, true)
1199 {
1200 }
1201 };
1202
StencilTest(Context & context,const FboConfig & config,bool npot)1203 StencilTest::StencilTest(Context &context, const FboConfig &config, bool npot)
1204 : FboRenderCase(context, (string(npot ? "npot_" : "") + config.getName()).c_str(), "Stencil ops", config)
1205 , m_fboWidth(npot ? 99 : 128)
1206 , m_fboHeight(npot ? 110 : 128)
1207 {
1208 }
1209
isConfigSupported(const FboConfig & config)1210 bool StencilTest::isConfigSupported(const FboConfig &config)
1211 {
1212 return config.stencilbufferType != GL_NONE;
1213 }
1214
render(sglr::Context & ctx,Surface & dst)1215 void StencilTest::render(sglr::Context &ctx, Surface &dst)
1216 {
1217 FlatColorShader colorShader;
1218 SingleTex2DShader texShader;
1219 uint32_t colorShaderID = ctx.createProgram(&colorShader);
1220 uint32_t texShaderID = ctx.createProgram(&texShader);
1221 int width = m_fboWidth;
1222 int height = m_fboHeight;
1223 int texWidth = 64;
1224 int texHeight = 64;
1225 uint32_t quadsTex = 1;
1226 uint32_t metaballsTex = 2;
1227 bool depth = getConfig().depthbufferType != GL_NONE;
1228
1229 createQuadsTex2D(ctx, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, texWidth, texHeight);
1230 createMetaballsTex2D(ctx, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, texWidth, texHeight);
1231
1232 Framebuffer fbo(ctx, getConfig(), width, height);
1233 fbo.checkCompleteness();
1234
1235 // Bind framebuffer and clear
1236 ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
1237 ctx.viewport(0, 0, width, height);
1238 ctx.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
1239 ctx.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1240
1241 // Render intersecting quads - increment stencil on depth pass
1242 ctx.enable(GL_DEPTH_TEST);
1243 ctx.enable(GL_STENCIL_TEST);
1244 ctx.stencilFunc(GL_ALWAYS, 0, 0xffu);
1245 ctx.stencilOp(GL_KEEP, GL_KEEP, GL_INCR);
1246
1247 colorShader.setColor(ctx, colorShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f));
1248 sglr::drawQuad(ctx, colorShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
1249
1250 ctx.bindTexture(GL_TEXTURE_2D, quadsTex);
1251 texShader.setUnit(ctx, texShaderID, 0);
1252 sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(+1.0f, +1.0f, +1.0f));
1253
1254 // Draw quad with stencil test (stencil == 1 or 2 depending on depth) - decrement on stencil failure
1255 ctx.disable(GL_DEPTH_TEST);
1256 ctx.stencilFunc(GL_EQUAL, depth ? 2 : 1, 0xffu);
1257 ctx.stencilOp(GL_DECR, GL_KEEP, GL_KEEP);
1258 colorShader.setColor(ctx, colorShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
1259 sglr::drawQuad(ctx, colorShaderID, Vec3(-0.5f, -0.5f, 0.0f), Vec3(+0.5f, +0.5f, 0.0f));
1260
1261 // Draw metaballs with stencil test where stencil > 1 or 2 depending on depth buffer
1262 ctx.bindTexture(GL_TEXTURE_2D, metaballsTex);
1263 ctx.stencilFunc(GL_GREATER, depth ? 1 : 2, 0xffu);
1264 ctx.stencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
1265 sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
1266
1267 ctx.disable(GL_STENCIL_TEST);
1268
1269 if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
1270 {
1271 ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);
1272 ctx.activeTexture(GL_TEXTURE0);
1273 ctx.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
1274 ctx.viewport(0, 0, ctx.getWidth(), ctx.getHeight());
1275 sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1276 ctx.readPixels(dst, 0, 0, ctx.getWidth(), ctx.getHeight());
1277 }
1278 else
1279 ctx.readPixels(dst, 0, 0, width, height);
1280 }
1281
1282 class SharedColorbufferTest : public FboRenderCase
1283 {
1284 public:
1285 SharedColorbufferTest(Context &context, const FboConfig &config);
~SharedColorbufferTest(void)1286 virtual ~SharedColorbufferTest(void)
1287 {
1288 }
1289
1290 void render(sglr::Context &context, Surface &dst);
1291 };
1292
SharedColorbufferTest(Context & context,const FboConfig & config)1293 SharedColorbufferTest::SharedColorbufferTest(Context &context, const FboConfig &config)
1294 : FboRenderCase(context, config.getName().c_str(), "Shared colorbuffer", config)
1295 {
1296 }
1297
render(sglr::Context & context,Surface & dst)1298 void SharedColorbufferTest::render(sglr::Context &context, Surface &dst)
1299 {
1300 SingleTex2DShader shader;
1301 uint32_t shaderID = context.createProgram(&shader);
1302 int width = 128;
1303 int height = 128;
1304 // bool depth = getConfig().depthbufferFormat != GL_NONE;
1305 bool stencil = getConfig().stencilbufferFormat != GL_NONE;
1306
1307 // Textures
1308 uint32_t quadsTex = 1;
1309 uint32_t metaballsTex = 2;
1310 createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
1311 createMetaballsTex2D(context, metaballsTex, GL_RGBA, GL_UNSIGNED_BYTE, 64, 64);
1312
1313 context.viewport(0, 0, width, height);
1314
1315 shader.setUnit(context, shaderID, 0);
1316
1317 // Fbo A
1318 Framebuffer fboA(context, getConfig(), width, height);
1319 fboA.checkCompleteness();
1320
1321 // Fbo B - don't create colorbuffer
1322 FboConfig cfg = getConfig();
1323 cfg.colorbufferType = GL_NONE;
1324 cfg.colorbufferFormat = GL_NONE;
1325 Framebuffer fboB(context, cfg, width, height);
1326
1327 // Attach color buffer from fbo A
1328 context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
1329 switch (getConfig().colorbufferType)
1330 {
1331 case GL_TEXTURE_2D:
1332 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboA.getColorbuffer(), 0);
1333 break;
1334
1335 case GL_RENDERBUFFER:
1336 context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, fboA.getColorbuffer());
1337 break;
1338
1339 default:
1340 DE_ASSERT(false);
1341 }
1342
1343 // Clear depth and stencil in fbo B
1344 context.clear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1345
1346 // Render quads to fbo 1, with depth 0.0
1347 context.bindFramebuffer(GL_FRAMEBUFFER, fboA.getFramebuffer());
1348 context.bindTexture(GL_TEXTURE_2D, quadsTex);
1349 context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
1350 context.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1351
1352 if (stencil)
1353 {
1354 // Stencil to 1 in fbo A
1355 context.clearStencil(1);
1356 context.clear(GL_STENCIL_BUFFER_BIT);
1357 }
1358
1359 context.enable(GL_DEPTH_TEST);
1360 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1361 context.disable(GL_DEPTH_TEST);
1362
1363 // Blend metaballs to fbo 2
1364 context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
1365 context.bindTexture(GL_TEXTURE_2D, metaballsTex);
1366 context.enable(GL_BLEND);
1367 context.blendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
1368 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1369
1370 // Render small quad that is only visible if depth buffer is not shared with fbo A - or there is no depth bits
1371 context.bindTexture(GL_TEXTURE_2D, quadsTex);
1372 context.enable(GL_DEPTH_TEST);
1373 sglr::drawQuad(context, shaderID, Vec3(0.5f, 0.5f, 0.5f), Vec3(1.0f, 1.0f, 0.5f));
1374 context.disable(GL_DEPTH_TEST);
1375
1376 if (stencil)
1377 {
1378 FlatColorShader flatShader;
1379 uint32_t flatShaderID = context.createProgram(&flatShader);
1380
1381 flatShader.setColor(context, flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
1382
1383 // Clear subset of stencil buffer to 1
1384 context.enable(GL_SCISSOR_TEST);
1385 context.scissor(10, 10, 12, 25);
1386 context.clearStencil(1);
1387 context.clear(GL_STENCIL_BUFFER_BIT);
1388 context.disable(GL_SCISSOR_TEST);
1389
1390 // Render quad with stencil mask == 1
1391 context.enable(GL_STENCIL_TEST);
1392 context.stencilFunc(GL_EQUAL, 1, 0xffu);
1393 sglr::drawQuad(context, flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1394 context.disable(GL_STENCIL_TEST);
1395 }
1396
1397 // Get results
1398 if (fboA.getConfig().colorbufferType == GL_TEXTURE_2D)
1399 {
1400 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1401 context.bindTexture(GL_TEXTURE_2D, fboA.getColorbuffer());
1402 context.viewport(0, 0, context.getWidth(), context.getHeight());
1403 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1404 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
1405 }
1406 else
1407 context.readPixels(dst, 0, 0, width, height);
1408 }
1409
1410 class SharedColorbufferClearsTest : public FboRenderCase
1411 {
1412 public:
1413 SharedColorbufferClearsTest(Context &context, const FboConfig &config);
~SharedColorbufferClearsTest(void)1414 virtual ~SharedColorbufferClearsTest(void)
1415 {
1416 }
1417
1418 static bool isConfigSupported(const FboConfig &config);
1419 void render(sglr::Context &context, Surface &dst);
1420 };
1421
SharedColorbufferClearsTest(Context & context,const FboConfig & config)1422 SharedColorbufferClearsTest::SharedColorbufferClearsTest(Context &context, const FboConfig &config)
1423 : FboRenderCase(context, config.getName().c_str(), "Shared colorbuffer clears", config)
1424 {
1425 }
1426
isConfigSupported(const FboConfig & config)1427 bool SharedColorbufferClearsTest::isConfigSupported(const FboConfig &config)
1428 {
1429 return config.colorbufferType != GL_NONE && config.depthbufferType == GL_NONE &&
1430 config.stencilbufferType == GL_NONE;
1431 }
1432
render(sglr::Context & context,Surface & dst)1433 void SharedColorbufferClearsTest::render(sglr::Context &context, Surface &dst)
1434 {
1435 int width = 128;
1436 int height = 128;
1437 uint32_t colorbuffer = 1;
1438
1439 checkColorFormatSupport(context, getConfig().colorbufferFormat);
1440
1441 // Single colorbuffer
1442 if (getConfig().colorbufferType == GL_TEXTURE_2D)
1443 {
1444 context.bindTexture(GL_TEXTURE_2D, colorbuffer);
1445 context.texImage2D(GL_TEXTURE_2D, 0, getConfig().colorbufferFormat, width, height);
1446 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1447 }
1448 else
1449 {
1450 DE_ASSERT(getConfig().colorbufferType == GL_RENDERBUFFER);
1451 context.bindRenderbuffer(GL_RENDERBUFFER, colorbuffer);
1452 context.renderbufferStorage(GL_RENDERBUFFER, getConfig().colorbufferFormat, width, height);
1453 }
1454
1455 // Multiple framebuffers sharing the colorbuffer
1456 for (int fbo = 1; fbo <= 3; fbo++)
1457 {
1458 context.bindFramebuffer(GL_FRAMEBUFFER, fbo);
1459
1460 if (getConfig().colorbufferType == GL_TEXTURE_2D)
1461 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer, 0);
1462 else
1463 context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuffer);
1464 }
1465
1466 context.bindFramebuffer(GL_FRAMEBUFFER, 1);
1467
1468 // Check completeness
1469 {
1470 GLenum status = context.checkFramebufferStatus(GL_FRAMEBUFFER);
1471 if (status != GL_FRAMEBUFFER_COMPLETE)
1472 throw FboIncompleteException(getConfig(), status, __FILE__, __LINE__);
1473 }
1474
1475 // Render to them
1476 context.viewport(0, 0, width, height);
1477 context.clearColor(0.0f, 0.0f, 1.0f, 1.0f);
1478 context.clear(GL_COLOR_BUFFER_BIT);
1479
1480 context.enable(GL_SCISSOR_TEST);
1481
1482 context.bindFramebuffer(GL_FRAMEBUFFER, 2);
1483 context.clearColor(0.6f, 0.0f, 0.0f, 1.0f);
1484 context.scissor(10, 10, 64, 64);
1485 context.clear(GL_COLOR_BUFFER_BIT);
1486 context.clearColor(0.0f, 0.6f, 0.0f, 1.0f);
1487 context.scissor(60, 60, 40, 20);
1488 context.clear(GL_COLOR_BUFFER_BIT);
1489
1490 context.bindFramebuffer(GL_FRAMEBUFFER, 3);
1491 context.clearColor(0.0f, 0.0f, 0.6f, 1.0f);
1492 context.scissor(20, 20, 100, 10);
1493 context.clear(GL_COLOR_BUFFER_BIT);
1494
1495 context.bindFramebuffer(GL_FRAMEBUFFER, 1);
1496 context.clearColor(0.6f, 0.0f, 0.6f, 1.0f);
1497 context.scissor(20, 20, 5, 100);
1498 context.clear(GL_COLOR_BUFFER_BIT);
1499
1500 context.disable(GL_SCISSOR_TEST);
1501
1502 if (getConfig().colorbufferType == GL_TEXTURE_2D)
1503 {
1504 SingleTex2DShader shader;
1505 uint32_t shaderID = context.createProgram(&shader);
1506
1507 shader.setUnit(context, shaderID, 0);
1508
1509 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1510 context.viewport(0, 0, context.getWidth(), context.getHeight());
1511 sglr::drawQuad(context, shaderID, Vec3(-0.9f, -0.9f, 0.0f), Vec3(0.9f, 0.9f, 0.0f));
1512 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
1513 }
1514 else
1515 context.readPixels(dst, 0, 0, width, height);
1516 }
1517
1518 class SharedDepthbufferTest : public FboRenderCase
1519 {
1520 public:
1521 SharedDepthbufferTest(Context &context, const FboConfig &config);
~SharedDepthbufferTest(void)1522 virtual ~SharedDepthbufferTest(void)
1523 {
1524 }
1525
1526 static bool isConfigSupported(const FboConfig &config);
1527 void render(sglr::Context &context, Surface &dst);
1528 };
1529
SharedDepthbufferTest(Context & context,const FboConfig & config)1530 SharedDepthbufferTest::SharedDepthbufferTest(Context &context, const FboConfig &config)
1531 : FboRenderCase(context, config.getName().c_str(), "Shared depthbuffer", config)
1532 {
1533 }
1534
isConfigSupported(const FboConfig & config)1535 bool SharedDepthbufferTest::isConfigSupported(const FboConfig &config)
1536 {
1537 return config.depthbufferType == GL_RENDERBUFFER;
1538 }
1539
render(sglr::Context & context,Surface & dst)1540 void SharedDepthbufferTest::render(sglr::Context &context, Surface &dst)
1541 {
1542 SingleTex2DShader texShader;
1543 FlatColorShader colorShader;
1544 uint32_t texShaderID = context.createProgram(&texShader);
1545 uint32_t colorShaderID = context.createProgram(&colorShader);
1546 int width = 128;
1547 int height = 128;
1548 bool stencil = getConfig().stencilbufferType != GL_NONE;
1549
1550 // Setup shaders
1551 texShader.setUnit(context, texShaderID, 0);
1552 colorShader.setColor(context, colorShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
1553
1554 // Textures
1555 uint32_t metaballsTex = 5;
1556 uint32_t quadsTex = 6;
1557 createMetaballsTex2D(context, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
1558 createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
1559
1560 context.viewport(0, 0, width, height);
1561
1562 // Fbo A
1563 Framebuffer fboA(context, getConfig(), width, height);
1564 fboA.checkCompleteness();
1565
1566 // Fbo B
1567 FboConfig cfg = getConfig();
1568 cfg.depthbufferType = GL_NONE;
1569 cfg.depthbufferFormat = GL_NONE;
1570 Framebuffer fboB(context, cfg, width, height);
1571
1572 // Bind depth buffer from fbo A to fbo B
1573 DE_ASSERT(fboA.getConfig().depthbufferType == GL_RENDERBUFFER);
1574 context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
1575 context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fboA.getDepthbuffer());
1576
1577 // Clear fbo B color to red and stencil to 1
1578 context.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
1579 context.clearStencil(1);
1580 context.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1581
1582 // Enable depth test.
1583 context.enable(GL_DEPTH_TEST);
1584
1585 // Render quad to fbo A
1586 context.bindFramebuffer(GL_FRAMEBUFFER, fboA.getFramebuffer());
1587 context.bindTexture(GL_TEXTURE_2D, quadsTex);
1588 context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
1589 context.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1590 sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1591
1592 // Render metaballs to fbo B
1593 context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
1594 context.bindTexture(GL_TEXTURE_2D, metaballsTex);
1595 sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));
1596
1597 context.disable(GL_DEPTH_TEST);
1598
1599 if (stencil)
1600 {
1601 // Clear subset of stencil buffer to 0
1602 context.enable(GL_SCISSOR_TEST);
1603 context.scissor(10, 10, 12, 25);
1604 context.clearStencil(0);
1605 context.clear(GL_STENCIL_BUFFER_BIT);
1606 context.disable(GL_SCISSOR_TEST);
1607
1608 // Render quad with stencil mask == 0
1609 context.enable(GL_STENCIL_TEST);
1610 context.stencilFunc(GL_EQUAL, 0, 0xffu);
1611 sglr::drawQuad(context, colorShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1612 context.disable(GL_STENCIL_TEST);
1613 }
1614
1615 if (getConfig().colorbufferType == GL_TEXTURE_2D)
1616 {
1617 // Render both to screen
1618 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1619 context.viewport(0, 0, context.getWidth(), context.getHeight());
1620 context.bindTexture(GL_TEXTURE_2D, fboA.getColorbuffer());
1621 sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(0.0f, 1.0f, 0.0f));
1622 context.bindTexture(GL_TEXTURE_2D, fboB.getColorbuffer());
1623 sglr::drawQuad(context, texShaderID, Vec3(0.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1624
1625 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
1626 }
1627 else
1628 {
1629 // Read results from fbo B
1630 context.readPixels(dst, 0, 0, width, height);
1631 }
1632 }
1633
1634 class TexSubImageAfterRenderTest : public FboRenderCase
1635 {
1636 public:
1637 TexSubImageAfterRenderTest(Context &context, const FboConfig &config);
~TexSubImageAfterRenderTest(void)1638 virtual ~TexSubImageAfterRenderTest(void)
1639 {
1640 }
1641
1642 static bool isConfigSupported(const FboConfig &config);
1643 void render(sglr::Context &context, Surface &dst);
1644 };
1645
TexSubImageAfterRenderTest(Context & context,const FboConfig & config)1646 TexSubImageAfterRenderTest::TexSubImageAfterRenderTest(Context &context, const FboConfig &config)
1647 : FboRenderCase(context, (string("after_render_") + config.getName()).c_str(),
1648 "TexSubImage after rendering to texture", config)
1649 {
1650 }
1651
isConfigSupported(const FboConfig & config)1652 bool TexSubImageAfterRenderTest::isConfigSupported(const FboConfig &config)
1653 {
1654 return config.colorbufferType == GL_TEXTURE_2D &&
1655 (config.colorbufferFormat == GL_RGB || config.colorbufferFormat == GL_RGBA) &&
1656 config.depthbufferType == GL_NONE && config.stencilbufferType == GL_NONE;
1657 }
1658
render(sglr::Context & context,Surface & dst)1659 void TexSubImageAfterRenderTest::render(sglr::Context &context, Surface &dst)
1660 {
1661 SingleTex2DShader shader;
1662 uint32_t shaderID = context.createProgram(&shader);
1663 bool isRGBA = getConfig().colorbufferFormat == GL_RGBA;
1664
1665 tcu::TextureLevel fourQuads(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), 64, 64);
1666 tcu::fillWithRGBAQuads(fourQuads.getAccess());
1667
1668 tcu::TextureLevel metaballs(
1669 tcu::TextureFormat(isRGBA ? tcu::TextureFormat::RGBA : tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8),
1670 64, 64);
1671 tcu::fillWithMetaballs(metaballs.getAccess(), 5, 3);
1672
1673 shader.setUnit(context, shaderID, 0);
1674
1675 uint32_t fourQuadsTex = 1;
1676 context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
1677 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1678 context.texImage2D(GL_TEXTURE_2D, 0, GL_RGB, 64, 64, 0, GL_RGB, GL_UNSIGNED_BYTE,
1679 fourQuads.getAccess().getDataPtr());
1680
1681 context.bindFramebuffer(GL_FRAMEBUFFER, 1);
1682
1683 uint32_t fboTex = 2;
1684 context.bindTexture(GL_TEXTURE_2D, fboTex);
1685 context.texImage2D(GL_TEXTURE_2D, 0, isRGBA ? GL_RGBA : GL_RGB, 128, 128);
1686 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1687 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0);
1688
1689 // Render to fbo
1690 context.viewport(0, 0, 128, 128);
1691 context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
1692 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1693
1694 // Update texture using TexSubImage2D
1695 context.bindTexture(GL_TEXTURE_2D, fboTex);
1696 context.texSubImage2D(GL_TEXTURE_2D, 0, 32, 32, 64, 64, isRGBA ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE,
1697 metaballs.getAccess().getDataPtr());
1698
1699 // Draw to screen
1700 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1701 context.viewport(0, 0, context.getWidth(), context.getHeight());
1702 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1703 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
1704 }
1705
1706 class TexSubImageBetweenRenderTest : public FboRenderCase
1707 {
1708 public:
1709 TexSubImageBetweenRenderTest(Context &context, const FboConfig &config);
~TexSubImageBetweenRenderTest(void)1710 virtual ~TexSubImageBetweenRenderTest(void)
1711 {
1712 }
1713
1714 static bool isConfigSupported(const FboConfig &config);
1715 void render(sglr::Context &context, Surface &dst);
1716 };
1717
TexSubImageBetweenRenderTest(Context & context,const FboConfig & config)1718 TexSubImageBetweenRenderTest::TexSubImageBetweenRenderTest(Context &context, const FboConfig &config)
1719 : FboRenderCase(context, (string("between_render_") + config.getName()).c_str(),
1720 "TexSubImage between rendering calls", config)
1721 {
1722 }
1723
isConfigSupported(const FboConfig & config)1724 bool TexSubImageBetweenRenderTest::isConfigSupported(const FboConfig &config)
1725 {
1726 return config.colorbufferType == GL_TEXTURE_2D &&
1727 (config.colorbufferFormat == GL_RGB || config.colorbufferFormat == GL_RGBA) &&
1728 config.depthbufferType == GL_NONE && config.stencilbufferType == GL_NONE;
1729 }
1730
render(sglr::Context & context,Surface & dst)1731 void TexSubImageBetweenRenderTest::render(sglr::Context &context, Surface &dst)
1732 {
1733 SingleTex2DShader shader;
1734 uint32_t shaderID = context.createProgram(&shader);
1735 bool isRGBA = getConfig().colorbufferFormat == GL_RGBA;
1736
1737 tcu::TextureLevel fourQuads(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), 64, 64);
1738 tcu::fillWithRGBAQuads(fourQuads.getAccess());
1739
1740 tcu::TextureLevel metaballs(
1741 tcu::TextureFormat(isRGBA ? tcu::TextureFormat::RGBA : tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8),
1742 64, 64);
1743 tcu::fillWithMetaballs(metaballs.getAccess(), 5, 3);
1744
1745 tcu::TextureLevel metaballs2(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 64, 64);
1746 tcu::fillWithMetaballs(metaballs2.getAccess(), 5, 4);
1747
1748 uint32_t metaballsTex = 3;
1749 context.bindTexture(GL_TEXTURE_2D, metaballsTex);
1750 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1751 context.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1752 metaballs2.getAccess().getDataPtr());
1753
1754 uint32_t fourQuadsTex = 1;
1755 context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
1756 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1757 context.texImage2D(GL_TEXTURE_2D, 0, GL_RGB, 64, 64, 0, GL_RGB, GL_UNSIGNED_BYTE,
1758 fourQuads.getAccess().getDataPtr());
1759
1760 context.bindFramebuffer(GL_FRAMEBUFFER, 1);
1761
1762 uint32_t fboTex = 2;
1763 context.bindTexture(GL_TEXTURE_2D, fboTex);
1764 context.texImage2D(GL_TEXTURE_2D, 0, isRGBA ? GL_RGBA : GL_RGB, 128, 128);
1765 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1766 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0);
1767
1768 shader.setUnit(context, shaderID, 0);
1769
1770 // Render to fbo
1771 context.viewport(0, 0, 128, 128);
1772 context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
1773 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1774
1775 // Update texture using TexSubImage2D
1776 context.bindTexture(GL_TEXTURE_2D, fboTex);
1777 context.texSubImage2D(GL_TEXTURE_2D, 0, 32, 32, 64, 64, isRGBA ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE,
1778 metaballs.getAccess().getDataPtr());
1779
1780 // Render again to fbo
1781 context.bindTexture(GL_TEXTURE_2D, metaballsTex);
1782 context.enable(GL_BLEND);
1783 context.blendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
1784 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1785 context.disable(GL_BLEND);
1786
1787 // Draw to screen
1788 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1789 context.viewport(0, 0, context.getWidth(), context.getHeight());
1790 context.bindTexture(GL_TEXTURE_2D, fboTex);
1791 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1792
1793 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
1794 }
1795
1796 class ResizeTest : public FboRenderCase
1797 {
1798 public:
1799 ResizeTest(Context &context, const FboConfig &config);
~ResizeTest(void)1800 virtual ~ResizeTest(void)
1801 {
1802 }
1803
1804 void render(sglr::Context &context, Surface &dst);
1805 };
1806
ResizeTest(Context & context,const FboConfig & config)1807 ResizeTest::ResizeTest(Context &context, const FboConfig &config)
1808 : FboRenderCase(context, config.getName().c_str(), "Resize framebuffer", config)
1809 {
1810 }
1811
render(sglr::Context & context,Surface & dst)1812 void ResizeTest::render(sglr::Context &context, Surface &dst)
1813 {
1814 SingleTex2DShader texShader;
1815 FlatColorShader colorShader;
1816 uint32_t texShaderID = context.createProgram(&texShader);
1817 uint32_t colorShaderID = context.createProgram(&colorShader);
1818 uint32_t quadsTex = 1;
1819 uint32_t metaballsTex = 2;
1820 bool depth = getConfig().depthbufferType != GL_NONE;
1821 bool stencil = getConfig().stencilbufferType != GL_NONE;
1822
1823 createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
1824 createMetaballsTex2D(context, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 32, 32);
1825
1826 Framebuffer fbo(context, getConfig(), 128, 128);
1827 fbo.checkCompleteness();
1828
1829 // Setup shaders
1830 texShader.setUnit(context, texShaderID, 0);
1831 colorShader.setColor(context, colorShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
1832
1833 // Render quads
1834 context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
1835 context.viewport(0, 0, 128, 128);
1836 context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
1837 context.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1838 context.bindTexture(GL_TEXTURE_2D, quadsTex);
1839 sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1840
1841 if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
1842 {
1843 // Render fbo to screen
1844 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1845 context.viewport(0, 0, context.getWidth(), context.getHeight());
1846 context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
1847 sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1848
1849 // Restore binding
1850 context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
1851 }
1852
1853 int newWidth = 64;
1854 int newHeight = 32;
1855
1856 // Resize buffers
1857 switch (fbo.getConfig().colorbufferType)
1858 {
1859 case GL_TEXTURE_2D:
1860 context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
1861 context.texImage2D(GL_TEXTURE_2D, 0, fbo.getConfig().colorbufferFormat, newWidth, newHeight);
1862 break;
1863
1864 case GL_RENDERBUFFER:
1865 context.bindRenderbuffer(GL_RENDERBUFFER, fbo.getColorbuffer());
1866 context.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().colorbufferFormat, newWidth, newHeight);
1867 break;
1868
1869 default:
1870 DE_ASSERT(false);
1871 }
1872
1873 if (depth)
1874 {
1875 DE_ASSERT(fbo.getConfig().depthbufferType == GL_RENDERBUFFER);
1876 context.bindRenderbuffer(GL_RENDERBUFFER, fbo.getDepthbuffer());
1877 context.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().depthbufferFormat, newWidth, newHeight);
1878 }
1879
1880 if (stencil)
1881 {
1882 DE_ASSERT(fbo.getConfig().stencilbufferType == GL_RENDERBUFFER);
1883 context.bindRenderbuffer(GL_RENDERBUFFER, fbo.getStencilbuffer());
1884 context.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().stencilbufferFormat, newWidth, newHeight);
1885 }
1886
1887 // Render to resized fbo
1888 context.viewport(0, 0, newWidth, newHeight);
1889 context.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
1890 context.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1891
1892 context.enable(GL_DEPTH_TEST);
1893
1894 context.bindTexture(GL_TEXTURE_2D, metaballsTex);
1895 sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
1896
1897 context.bindTexture(GL_TEXTURE_2D, quadsTex);
1898 sglr::drawQuad(context, texShaderID, Vec3(0.0f, 0.0f, -1.0f), Vec3(+1.0f, +1.0f, 1.0f));
1899
1900 context.disable(GL_DEPTH_TEST);
1901
1902 if (stencil)
1903 {
1904 context.enable(GL_SCISSOR_TEST);
1905 context.scissor(10, 10, 5, 15);
1906 context.clearStencil(1);
1907 context.clear(GL_STENCIL_BUFFER_BIT);
1908 context.disable(GL_SCISSOR_TEST);
1909
1910 context.enable(GL_STENCIL_TEST);
1911 context.stencilFunc(GL_EQUAL, 1, 0xffu);
1912 sglr::drawQuad(context, colorShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
1913 context.disable(GL_STENCIL_TEST);
1914 }
1915
1916 if (getConfig().colorbufferType == GL_TEXTURE_2D)
1917 {
1918 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1919 context.viewport(0, 0, context.getWidth(), context.getHeight());
1920 context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
1921 sglr::drawQuad(context, texShaderID, Vec3(-0.5f, -0.5f, 0.0f), Vec3(0.5f, 0.5f, 0.0f));
1922 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
1923 }
1924 else
1925 context.readPixels(dst, 0, 0, newWidth, newHeight);
1926 }
1927
1928 template <GLenum Buffers>
1929 class RecreateBuffersTest : public FboRenderCase
1930 {
1931 public:
1932 RecreateBuffersTest(Context &context, const FboConfig &config, bool rebind);
~RecreateBuffersTest(void)1933 virtual ~RecreateBuffersTest(void)
1934 {
1935 }
1936
1937 static bool isConfigSupported(const FboConfig &config);
1938 void render(sglr::Context &context, Surface &dst);
1939
1940 private:
1941 bool m_rebind;
1942 };
1943
1944 template <GLenum Buffers>
1945 class RecreateBuffersNoRebindTest : public RecreateBuffersTest<Buffers>
1946 {
1947 public:
RecreateBuffersNoRebindTest(Context & context,const FboConfig & config)1948 RecreateBuffersNoRebindTest(Context &context, const FboConfig &config)
1949 : RecreateBuffersTest<Buffers>(context, config, false)
1950 {
1951 }
1952 };
1953
1954 template <GLenum Buffers>
1955 class RecreateBuffersRebindTest : public RecreateBuffersTest<Buffers>
1956 {
1957 public:
RecreateBuffersRebindTest(Context & context,const FboConfig & config)1958 RecreateBuffersRebindTest(Context &context, const FboConfig &config)
1959 : RecreateBuffersTest<Buffers>(context, config, true)
1960 {
1961 }
1962 };
1963
1964 template <GLenum Buffers>
RecreateBuffersTest(Context & context,const FboConfig & config,bool rebind)1965 RecreateBuffersTest<Buffers>::RecreateBuffersTest(Context &context, const FboConfig &config, bool rebind)
1966 : FboRenderCase(context, (string(rebind ? "rebind_" : "no_rebind_") + config.getName()).c_str(), "Recreate buffers",
1967 config)
1968 , m_rebind(rebind)
1969 {
1970 }
1971
1972 template <GLenum Buffers>
isConfigSupported(const FboConfig & config)1973 bool RecreateBuffersTest<Buffers>::isConfigSupported(const FboConfig &config)
1974 {
1975 if ((Buffers & GL_COLOR_BUFFER_BIT) && config.colorbufferType == GL_NONE)
1976 return false;
1977 if ((Buffers & GL_DEPTH_BUFFER_BIT) && config.depthbufferType == GL_NONE)
1978 return false;
1979 if ((Buffers & GL_STENCIL_BUFFER_BIT) && config.stencilbufferType == GL_NONE)
1980 return false;
1981 return true;
1982 }
1983
1984 template <GLenum Buffers>
render(sglr::Context & ctx,Surface & dst)1985 void RecreateBuffersTest<Buffers>::render(sglr::Context &ctx, Surface &dst)
1986 {
1987 SingleTex2DShader texShader;
1988 uint32_t texShaderID = ctx.createProgram(&texShader);
1989 int width = 128;
1990 int height = 128;
1991 uint32_t metaballsTex = 1;
1992 uint32_t quadsTex = 2;
1993 bool stencil = getConfig().stencilbufferType != GL_NONE;
1994
1995 createQuadsTex2D(ctx, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
1996 createMetaballsTex2D(ctx, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
1997
1998 Framebuffer fbo(ctx, getConfig(), width, height);
1999 fbo.checkCompleteness();
2000
2001 // Setup shader
2002 texShader.setUnit(ctx, texShaderID, 0);
2003
2004 // Draw scene
2005 ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
2006 ctx.viewport(0, 0, width, height);
2007 ctx.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
2008 ctx.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2009
2010 ctx.enable(GL_DEPTH_TEST);
2011
2012 ctx.bindTexture(GL_TEXTURE_2D, quadsTex);
2013 sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
2014
2015 if (stencil)
2016 {
2017 ctx.enable(GL_SCISSOR_TEST);
2018 ctx.scissor(width / 4, height / 4, width / 2, height / 2);
2019 ctx.clearStencil(1);
2020 ctx.clear(GL_STENCIL_BUFFER_BIT);
2021 ctx.disable(GL_SCISSOR_TEST);
2022 }
2023
2024 // Recreate buffers
2025 if (!m_rebind)
2026 ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);
2027
2028 if (Buffers & GL_COLOR_BUFFER_BIT)
2029 {
2030 uint32_t colorbuf = fbo.getColorbuffer();
2031 switch (fbo.getConfig().colorbufferType)
2032 {
2033 case GL_TEXTURE_2D:
2034 ctx.deleteTextures(1, &colorbuf);
2035 ctx.bindTexture(GL_TEXTURE_2D, colorbuf);
2036 ctx.texImage2D(GL_TEXTURE_2D, 0, fbo.getConfig().colorbufferFormat, width, height);
2037 ctx.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2038
2039 if (m_rebind)
2040 ctx.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuf, 0);
2041 break;
2042
2043 case GL_RENDERBUFFER:
2044 ctx.deleteRenderbuffers(1, &colorbuf);
2045 ctx.bindRenderbuffer(GL_RENDERBUFFER, colorbuf);
2046 ctx.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().colorbufferFormat, width, height);
2047
2048 if (m_rebind)
2049 ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuf);
2050 break;
2051
2052 default:
2053 DE_ASSERT(false);
2054 }
2055 }
2056
2057 if (Buffers & GL_DEPTH_BUFFER_BIT)
2058 {
2059 uint32_t depthbuf = fbo.getDepthbuffer();
2060 DE_ASSERT(fbo.getConfig().depthbufferType == GL_RENDERBUFFER);
2061
2062 ctx.deleteRenderbuffers(1, &depthbuf);
2063 ctx.bindRenderbuffer(GL_RENDERBUFFER, depthbuf);
2064 ctx.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().depthbufferFormat, width, height);
2065
2066 if (m_rebind)
2067 ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthbuf);
2068 }
2069
2070 if (Buffers & GL_STENCIL_BUFFER_BIT)
2071 {
2072 uint32_t stencilbuf = fbo.getStencilbuffer();
2073 DE_ASSERT(fbo.getConfig().stencilbufferType == GL_RENDERBUFFER);
2074
2075 ctx.deleteRenderbuffers(1, &stencilbuf);
2076 ctx.bindRenderbuffer(GL_RENDERBUFFER, stencilbuf);
2077 ctx.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().stencilbufferFormat, width, height);
2078
2079 if (m_rebind)
2080 ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, stencilbuf);
2081 }
2082
2083 if (!m_rebind)
2084 ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
2085
2086 ctx.clearColor(0.0f, 0.0f, 1.0f, 0.0f);
2087 ctx.clearStencil(0);
2088 ctx.clear(Buffers); // \note Clear only buffers that were re-created
2089
2090 if (stencil)
2091 {
2092 // \note Stencil test enabled only if we have stencil buffer
2093 ctx.enable(GL_STENCIL_TEST);
2094 ctx.stencilFunc(GL_EQUAL, 0, 0xffu);
2095 }
2096 ctx.bindTexture(GL_TEXTURE_2D, metaballsTex);
2097 sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 1.0f), Vec3(1.0f, 1.0f, -1.0f));
2098 if (stencil)
2099 ctx.disable(GL_STENCIL_TEST);
2100
2101 ctx.disable(GL_DEPTH_TEST);
2102
2103 // Read from fbo
2104 ctx.readPixels(dst, 0, 0, width, height);
2105 }
2106
2107 class RepeatedClearCase : public FboRenderCase
2108 {
2109 private:
makeConfig(uint32_t format)2110 static FboConfig makeConfig(uint32_t format)
2111 {
2112 FboConfig cfg;
2113 cfg.colorbufferType = GL_TEXTURE_2D;
2114 cfg.colorbufferFormat = format;
2115 cfg.depthbufferType = GL_NONE;
2116 cfg.stencilbufferType = GL_NONE;
2117 return cfg;
2118 }
2119
2120 public:
RepeatedClearCase(Context & context,uint32_t format)2121 RepeatedClearCase(Context &context, uint32_t format)
2122 : FboRenderCase(context, makeConfig(format).getName().c_str(), "Repeated clears", makeConfig(format))
2123 {
2124 }
2125
2126 protected:
render(sglr::Context & ctx,Surface & dst)2127 void render(sglr::Context &ctx, Surface &dst)
2128 {
2129 const int numRowsCols = 4;
2130 const int cellSize = 16;
2131 const int fboSizes[] = {cellSize, cellSize * numRowsCols};
2132
2133 SingleTex2DShader fboBlitShader;
2134 const uint32_t fboBlitShaderID = ctx.createProgram(&fboBlitShader);
2135
2136 de::Random rnd(18169662);
2137 uint32_t fbos[] = {0, 0};
2138 uint32_t textures[] = {0, 0};
2139
2140 ctx.genFramebuffers(2, &fbos[0]);
2141 ctx.genTextures(2, &textures[0]);
2142
2143 for (int fboNdx = 0; fboNdx < DE_LENGTH_OF_ARRAY(fbos); fboNdx++)
2144 {
2145 ctx.bindTexture(GL_TEXTURE_2D, textures[fboNdx]);
2146 ctx.texImage2D(GL_TEXTURE_2D, 0, getConfig().colorbufferFormat, fboSizes[fboNdx], fboSizes[fboNdx], 0,
2147 getConfig().colorbufferFormat, GL_UNSIGNED_BYTE, nullptr);
2148 ctx.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2149 ctx.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2150 ctx.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2151 ctx.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2152
2153 ctx.bindFramebuffer(GL_FRAMEBUFFER, fbos[fboNdx]);
2154 ctx.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[fboNdx], 0);
2155
2156 {
2157 const GLenum status = ctx.checkFramebufferStatus(GL_FRAMEBUFFER);
2158 if (status != GL_FRAMEBUFFER_COMPLETE)
2159 throw FboIncompleteException(getConfig(), status, __FILE__, __LINE__);
2160 }
2161 }
2162
2163 // larger fbo bound -- clear to transparent black
2164 ctx.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
2165 ctx.clear(GL_COLOR_BUFFER_BIT);
2166
2167 fboBlitShader.setUnit(ctx, fboBlitShaderID, 0);
2168 ctx.bindTexture(GL_TEXTURE_2D, textures[0]);
2169
2170 for (int cellY = 0; cellY < numRowsCols; cellY++)
2171 for (int cellX = 0; cellX < numRowsCols; cellX++)
2172 {
2173 const float r = rnd.getFloat();
2174 const float g = rnd.getFloat();
2175 const float b = rnd.getFloat();
2176 const float a = rnd.getFloat();
2177
2178 ctx.bindFramebuffer(GL_FRAMEBUFFER, fbos[0]);
2179 ctx.clearColor(r, g, b, a);
2180 ctx.clear(GL_COLOR_BUFFER_BIT);
2181
2182 ctx.bindFramebuffer(GL_FRAMEBUFFER, fbos[1]);
2183 ctx.viewport(cellX * cellSize, cellY * cellSize, cellSize, cellSize);
2184 sglr::drawQuad(ctx, fboBlitShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
2185 }
2186
2187 ctx.readPixels(dst, 0, 0, fboSizes[1], fboSizes[1]);
2188 }
2189 };
2190
2191 } // namespace FboCases
2192
FboRenderTestGroup(Context & context)2193 FboRenderTestGroup::FboRenderTestGroup(Context &context) : TestCaseGroup(context, "render", "Rendering Tests")
2194 {
2195 }
2196
~FboRenderTestGroup(void)2197 FboRenderTestGroup::~FboRenderTestGroup(void)
2198 {
2199 }
2200
2201 namespace
2202 {
2203
2204 struct TypeFormatPair
2205 {
2206 GLenum type;
2207 GLenum format;
2208 };
2209
2210 template <typename CaseType>
addChildVariants(deqp::gles2::TestCaseGroup * group)2211 void addChildVariants(deqp::gles2::TestCaseGroup *group)
2212 {
2213 TypeFormatPair colorbufferConfigs[] = {
2214 // { GL_TEXTURE_2D, GL_ALPHA },
2215 // { GL_TEXTURE_2D, GL_LUMINANCE },
2216 // { GL_TEXTURE_2D, GL_LUMINANCE_ALPHA },
2217 {GL_TEXTURE_2D, GL_RGB},
2218 {GL_TEXTURE_2D, GL_RGBA},
2219 {GL_TEXTURE_2D, GL_BGRA},
2220 {GL_RENDERBUFFER, GL_RGB565},
2221 {GL_RENDERBUFFER, GL_RGB5_A1},
2222 {GL_RENDERBUFFER, GL_RGBA4},
2223 // { GL_RENDERBUFFER, GL_RGBA16F },
2224 // { GL_RENDERBUFFER, GL_RGB16F }
2225 {GL_RENDERBUFFER, GL_BGRA},
2226 };
2227 TypeFormatPair depthbufferConfigs[] = {{GL_NONE, GL_NONE}, {GL_RENDERBUFFER, GL_DEPTH_COMPONENT16}};
2228 TypeFormatPair stencilbufferConfigs[] = {{GL_NONE, GL_NONE}, {GL_RENDERBUFFER, GL_STENCIL_INDEX8}};
2229
2230 for (int colorbufferNdx = 0; colorbufferNdx < DE_LENGTH_OF_ARRAY(colorbufferConfigs); colorbufferNdx++)
2231 for (int depthbufferNdx = 0; depthbufferNdx < DE_LENGTH_OF_ARRAY(depthbufferConfigs); depthbufferNdx++)
2232 for (int stencilbufferNdx = 0; stencilbufferNdx < DE_LENGTH_OF_ARRAY(stencilbufferConfigs);
2233 stencilbufferNdx++)
2234 {
2235 FboConfig config;
2236 config.colorbufferType = colorbufferConfigs[colorbufferNdx].type;
2237 config.colorbufferFormat = colorbufferConfigs[colorbufferNdx].format;
2238 config.depthbufferType = depthbufferConfigs[depthbufferNdx].type;
2239 config.depthbufferFormat = depthbufferConfigs[depthbufferNdx].format;
2240 config.stencilbufferType = stencilbufferConfigs[stencilbufferNdx].type;
2241 config.stencilbufferFormat = stencilbufferConfigs[stencilbufferNdx].format;
2242
2243 if (CaseType::isConfigSupported(config))
2244 group->addChild(new CaseType(group->getContext(), config));
2245 }
2246 }
2247
2248 template <typename CaseType>
createChildGroup(deqp::gles2::TestCaseGroup * parent,const char * name,const char * description)2249 void createChildGroup(deqp::gles2::TestCaseGroup *parent, const char *name, const char *description)
2250 {
2251 deqp::gles2::TestCaseGroup *tmpGroup = new deqp::gles2::TestCaseGroup(parent->getContext(), name, description);
2252 parent->addChild(tmpGroup);
2253 addChildVariants<CaseType>(tmpGroup);
2254 }
2255
2256 template <GLbitfield Buffers>
createRecreateBuffersGroup(deqp::gles2::TestCaseGroup * parent,const char * name,const char * description)2257 void createRecreateBuffersGroup(deqp::gles2::TestCaseGroup *parent, const char *name, const char *description)
2258 {
2259 deqp::gles2::TestCaseGroup *tmpGroup = new deqp::gles2::TestCaseGroup(parent->getContext(), name, description);
2260 parent->addChild(tmpGroup);
2261 addChildVariants<FboCases::RecreateBuffersRebindTest<Buffers>>(tmpGroup);
2262 addChildVariants<FboCases::RecreateBuffersNoRebindTest<Buffers>>(tmpGroup);
2263 }
2264
2265 } // namespace
2266
init(void)2267 void FboRenderTestGroup::init(void)
2268 {
2269 createChildGroup<FboCases::ColorClearsTest>(this, "color_clear", "Color buffer clears");
2270 createChildGroup<FboCases::StencilClearsTest>(this, "stencil_clear", "Stencil buffer clears");
2271
2272 deqp::gles2::TestCaseGroup *colorGroup = new deqp::gles2::TestCaseGroup(m_context, "color", "Color buffer tests");
2273 addChild(colorGroup);
2274 addChildVariants<FboCases::MixTest>(colorGroup);
2275 addChildVariants<FboCases::MixNpotTest>(colorGroup);
2276 addChildVariants<FboCases::BlendTest>(colorGroup);
2277 addChildVariants<FboCases::BlendNpotTest>(colorGroup);
2278
2279 deqp::gles2::TestCaseGroup *depthGroup = new deqp::gles2::TestCaseGroup(m_context, "depth", "Depth bufer tests");
2280 addChild(depthGroup);
2281 addChildVariants<FboCases::IntersectingQuadsTest>(depthGroup);
2282 addChildVariants<FboCases::IntersectingQuadsNpotTest>(depthGroup);
2283
2284 deqp::gles2::TestCaseGroup *stencilGroup =
2285 new deqp::gles2::TestCaseGroup(m_context, "stencil", "Stencil buffer tests");
2286 addChild(stencilGroup);
2287 addChildVariants<FboCases::StencilTest>(stencilGroup);
2288 addChildVariants<FboCases::StencilNpotTest>(stencilGroup);
2289
2290 createChildGroup<FboCases::SharedColorbufferClearsTest>(this, "shared_colorbuffer_clear",
2291 "Shared colorbuffer clears");
2292 createChildGroup<FboCases::SharedColorbufferTest>(this, "shared_colorbuffer", "Shared colorbuffer tests");
2293 createChildGroup<FboCases::SharedDepthbufferTest>(this, "shared_depthbuffer", "Shared depthbuffer tests");
2294 createChildGroup<FboCases::ResizeTest>(this, "resize", "FBO resize tests");
2295
2296 createRecreateBuffersGroup<GL_COLOR_BUFFER_BIT>(this, "recreate_colorbuffer", "Recreate colorbuffer tests");
2297 createRecreateBuffersGroup<GL_DEPTH_BUFFER_BIT>(this, "recreate_depthbuffer", "Recreate depthbuffer tests");
2298 createRecreateBuffersGroup<GL_STENCIL_BUFFER_BIT>(this, "recreate_stencilbuffer", "Recreate stencilbuffer tests");
2299
2300 deqp::gles2::TestCaseGroup *texSubImageGroup =
2301 new deqp::gles2::TestCaseGroup(m_context, "texsubimage", "TexSubImage interop with FBO colorbuffer texture");
2302 addChild(texSubImageGroup);
2303 addChildVariants<FboCases::TexSubImageAfterRenderTest>(texSubImageGroup);
2304 addChildVariants<FboCases::TexSubImageBetweenRenderTest>(texSubImageGroup);
2305
2306 {
2307 tcu::TestCaseGroup *const repeatedClearGroup =
2308 new tcu::TestCaseGroup(m_testCtx, "repeated_clear", "Repeated FBO clears");
2309 addChild(repeatedClearGroup);
2310
2311 repeatedClearGroup->addChild(new FboCases::RepeatedClearCase(m_context, GL_RGB));
2312 repeatedClearGroup->addChild(new FboCases::RepeatedClearCase(m_context, GL_RGBA));
2313 }
2314 }
2315
2316 } // namespace Functional
2317 } // namespace gles2
2318 } // namespace deqp
2319