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