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