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 // clear alpha channel for GL_RGB5_A1 format because test
718 // thresholds for the alpha channel do not account for dithering
719 if(getConfig().colorbufferFormat == GL_RGB5_A1)
720 {
721 context.colorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
722 context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
723 context.clear(GL_COLOR_BUFFER_BIT);
724 context.colorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
725 }
726
727 // Read from fbo
728 context.readPixels(dst, 0, 0, width, height);
729 }
730 }
731
732 class IntersectingQuadsTest : public FboRenderCase
733 {
734 public:
735 IntersectingQuadsTest (Context& context, const FboConfig& config, bool npot = false);
~IntersectingQuadsTest(void)736 virtual ~IntersectingQuadsTest (void) {}
737
738 virtual void render (sglr::Context& context, Surface& dst);
739
740 static bool isConfigSupported (const FboConfig& config);
741
742 private:
743 int m_fboWidth;
744 int m_fboHeight;
745 };
746
747 class IntersectingQuadsNpotTest : public IntersectingQuadsTest
748 {
749 public:
IntersectingQuadsNpotTest(Context & context,const FboConfig & config)750 IntersectingQuadsNpotTest (Context& context, const FboConfig& config)
751 : IntersectingQuadsTest(context, config, true)
752 {
753 }
754 };
755
IntersectingQuadsTest(Context & context,const FboConfig & config,bool npot)756 IntersectingQuadsTest::IntersectingQuadsTest (Context& context, const FboConfig& config, bool npot)
757 : FboRenderCase (context, (string(npot ? "npot_" : "") + config.getName()).c_str(), "Intersecting textured quads", config)
758 , m_fboWidth (npot ? 127 : 128)
759 , m_fboHeight (npot ? 95 : 128)
760 {
761 }
762
isConfigSupported(const FboConfig & config)763 bool IntersectingQuadsTest::isConfigSupported (const FboConfig& config)
764 {
765 // \note Disabled for stencil configurations since doesn't exercise stencil buffer
766 return config.depthbufferType != GL_NONE &&
767 config.stencilbufferType == GL_NONE;
768 }
769
render(sglr::Context & ctx,Surface & dst)770 void IntersectingQuadsTest::render (sglr::Context& ctx, Surface& dst)
771 {
772 SingleTex2DShader texShader;
773 deUint32 texShaderID = ctx.createProgram(&texShader);
774
775 deUint32 metaballsTex = 1;
776 deUint32 quadsTex = 2;
777
778 createMetaballsTex2D(ctx, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
779 createQuadsTex2D(ctx, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
780
781 int width = m_fboWidth;
782 int height = m_fboHeight;
783 Framebuffer fbo(ctx, getConfig(), width, height);
784 fbo.checkCompleteness();
785
786 // Setup shaders
787 texShader.setUnit(ctx, texShaderID, 0);
788
789 // Draw scene
790 ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
791 ctx.viewport(0, 0, width, height);
792 ctx.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
793 ctx.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
794
795 ctx.enable(GL_DEPTH_TEST);
796
797 ctx.bindTexture(GL_TEXTURE_2D, metaballsTex);
798 sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));
799
800 ctx.bindTexture(GL_TEXTURE_2D, quadsTex);
801 sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 1.0f), Vec3(1.0f, 1.0f, -1.0f));
802
803 ctx.disable(GL_DEPTH_TEST);
804
805 if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
806 {
807 // Unbind fbo
808 ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);
809
810 // Draw to screen
811 ctx.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
812 ctx.viewport(0, 0, ctx.getWidth(), ctx.getHeight());
813 sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
814
815 // Read from screen
816 ctx.readPixels(dst, 0, 0, ctx.getWidth(), ctx.getHeight());
817 }
818 else
819 {
820 // Read from fbo
821 ctx.readPixels(dst, 0, 0, width, height);
822 }
823 }
824
825 class MixTest : public FboRenderCase
826 {
827 public:
828 MixTest (Context& context, const FboConfig& config, bool npot = false);
~MixTest(void)829 virtual ~MixTest (void) {}
830
831 void render (sglr::Context& context, Surface& dst);
832
833 static bool isConfigSupported (const FboConfig& config);
834
835 private:
836 int m_fboAWidth;
837 int m_fboAHeight;
838 int m_fboBWidth;
839 int m_fboBHeight;
840 };
841
842 class MixNpotTest : public MixTest
843 {
844 public:
MixNpotTest(Context & context,const FboConfig & config)845 MixNpotTest (Context& context, const FboConfig& config)
846 : MixTest(context, config, true)
847 {
848 }
849 };
850
MixTest(Context & context,const FboConfig & config,bool npot)851 MixTest::MixTest (Context& context, const FboConfig& config, bool npot)
852 : FboRenderCase (context, (string(npot ? "mix_npot_" : "mix_") + config.getName()).c_str(), "Use two fbos as sources in draw operation", config)
853 , m_fboAWidth (npot ? 127 : 128)
854 , m_fboAHeight (npot ? 95 : 128)
855 , m_fboBWidth (npot ? 55 : 64)
856 , m_fboBHeight (npot ? 63 : 64)
857 {
858 }
859
isConfigSupported(const FboConfig & config)860 bool MixTest::isConfigSupported (const FboConfig& config)
861 {
862 // \note Disabled for stencil configurations since doesn't exercise stencil buffer
863 return config.colorbufferType == GL_TEXTURE_2D &&
864 config.stencilbufferType == GL_NONE;
865 }
866
render(sglr::Context & context,Surface & dst)867 void MixTest::render (sglr::Context& context, Surface& dst)
868 {
869 SingleTex2DShader singleTexShader;
870 MixTexturesShader mixShader;
871
872 deUint32 singleTexShaderID = context.createProgram(&singleTexShader);
873 deUint32 mixShaderID = context.createProgram(&mixShader);
874
875 // Texture with metaballs
876 deUint32 metaballsTex = 1;
877 context.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
878 createMetaballsTex2D(context, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
879
880 // Setup shaders
881 singleTexShader.setUnit(context, singleTexShaderID, 0);
882 mixShader.setUnits(context, mixShaderID, 0, 1);
883
884 // Fbo, quad with metaballs texture
885 Framebuffer fboA(context, getConfig(), m_fboAWidth, m_fboAHeight);
886 fboA.checkCompleteness();
887 context.bindFramebuffer(GL_FRAMEBUFFER, fboA.getFramebuffer());
888 context.viewport(0, 0, m_fboAWidth, m_fboAHeight);
889 context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
890 context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
891 context.bindTexture(GL_TEXTURE_2D, metaballsTex);
892 sglr::drawQuad(context, singleTexShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
893
894 // Fbo, color clears
895 Framebuffer fboB(context, getConfig(), m_fboBWidth, m_fboBHeight);
896 fboB.checkCompleteness();
897 context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
898 context.viewport(0, 0, m_fboBWidth, m_fboBHeight);
899 context.enable(GL_SCISSOR_TEST);
900 context.scissor(0, 0, 32, 64);
901 context.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
902 context.clear(GL_COLOR_BUFFER_BIT);
903 context.scissor(32, 0, 32, 64);
904 context.clearColor(0.0f, 1.0f, 0.0f, 1.0f);
905 context.clear(GL_COLOR_BUFFER_BIT);
906 context.disable(GL_SCISSOR_TEST);
907
908 // Final mix op
909 context.activeTexture(GL_TEXTURE0);
910 context.bindTexture(GL_TEXTURE_2D, fboA.getColorbuffer());
911 context.activeTexture(GL_TEXTURE1);
912 context.bindTexture(GL_TEXTURE_2D, fboB.getColorbuffer());
913 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
914 context.viewport(0, 0, context.getWidth(), context.getHeight());
915 sglr::drawQuad(context, mixShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
916
917 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
918 }
919
920 class BlendTest : public FboRenderCase
921 {
922 public:
923 BlendTest (Context& context, const FboConfig& config, bool npot = false);
~BlendTest(void)924 virtual ~BlendTest (void) {}
925
926 void render (sglr::Context& context, Surface& dst);
927
928 static bool isConfigSupported (const FboConfig& config);
929
930 private:
931 int m_fboWidth;
932 int m_fboHeight;
933 };
934
935 class BlendNpotTest : public BlendTest
936 {
937 public:
BlendNpotTest(Context & context,const FboConfig & config)938 BlendNpotTest (Context& context, const FboConfig& config)
939 : BlendTest(context, config, true)
940 {
941 }
942 };
943
BlendTest(Context & context,const FboConfig & config,bool npot)944 BlendTest::BlendTest (Context& context, const FboConfig& config, bool npot)
945 : FboRenderCase (context, (string(npot ? "blend_npot_" : "blend_") + config.getName()).c_str(), "Blend to fbo", config)
946 , m_fboWidth (npot ? 111 : 128)
947 , m_fboHeight (npot ? 122 : 128)
948 {
949 }
950
isConfigSupported(const FboConfig & config)951 bool BlendTest::isConfigSupported (const FboConfig& config)
952 {
953 // \note Disabled for stencil configurations since doesn't exercise stencil buffer
954 return config.stencilbufferType == GL_NONE;
955 }
956
render(sglr::Context & context,Surface & dst)957 void BlendTest::render (sglr::Context& context, Surface& dst)
958 {
959 SingleTex2DShader shader;
960 deUint32 shaderID = context.createProgram(&shader);
961 int width = m_fboWidth;
962 int height = m_fboHeight;
963 deUint32 metaballsTex = 1;
964
965 createMetaballsTex2D(context, metaballsTex, GL_RGBA, GL_UNSIGNED_BYTE, 64, 64);
966
967 Framebuffer fbo(context, getConfig(), width, height);
968 fbo.checkCompleteness();
969
970 shader.setUnit(context, shaderID, 0);
971
972 context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
973 context.viewport(0, 0, width, height);
974 context.bindTexture(GL_TEXTURE_2D, metaballsTex);
975 context.clearColor(0.6f, 0.0f, 0.6f, 1.0f);
976 context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
977
978 context.enable(GL_BLEND);
979 context.blendEquation(GL_FUNC_ADD);
980 context.blendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
981 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
982 context.disable(GL_BLEND);
983
984 if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
985 {
986 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
987 context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
988 context.viewport(0, 0, context.getWidth(), context.getHeight());
989 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
990 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
991 }
992 else
993 context.readPixels(dst, 0, 0, width, height);
994 }
995
996 class StencilClearsTest : public FboRenderCase
997 {
998 public:
999 StencilClearsTest (Context& context, const FboConfig& config);
~StencilClearsTest(void)1000 virtual ~StencilClearsTest (void) {};
1001
1002 void render (sglr::Context& context, Surface& dst);
1003
1004 static bool isConfigSupported (const FboConfig& config);
1005 };
1006
StencilClearsTest(Context & context,const FboConfig & config)1007 StencilClearsTest::StencilClearsTest (Context& context, const FboConfig& config)
1008 : FboRenderCase(context, config.getName().c_str(), "Stencil clears", config)
1009 {
1010 }
1011
render(sglr::Context & context,Surface & dst)1012 void StencilClearsTest::render (sglr::Context& context, Surface& dst)
1013 {
1014 SingleTex2DShader shader;
1015 deUint32 shaderID = context.createProgram(&shader);
1016 int width = 128;
1017 int height = 128;
1018 deUint32 quadsTex = 1;
1019 deUint32 metaballsTex = 2;
1020
1021 createQuadsTex2D(context, quadsTex, GL_RGBA, GL_UNSIGNED_BYTE, width, height);
1022 createMetaballsTex2D(context, metaballsTex, GL_RGBA, GL_UNSIGNED_BYTE, width, height);
1023
1024 Framebuffer fbo(context, getConfig(), width, height);
1025 fbo.checkCompleteness();
1026
1027 // Bind framebuffer and clear
1028 context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
1029 context.viewport(0, 0, width, height);
1030 context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
1031 context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
1032
1033 // Do stencil clears
1034 context.enable(GL_SCISSOR_TEST);
1035 context.scissor(10, 16, 32, 120);
1036 context.clearStencil(1);
1037 context.clear(GL_STENCIL_BUFFER_BIT);
1038 context.scissor(16, 32, 100, 64);
1039 context.clearStencil(2);
1040 context.clear(GL_STENCIL_BUFFER_BIT);
1041 context.disable(GL_SCISSOR_TEST);
1042
1043 // Draw 2 textures with stecil tests
1044 context.activeTexture(GL_TEXTURE0);
1045 context.bindTexture(GL_TEXTURE_2D, quadsTex);
1046 context.activeTexture(GL_TEXTURE1);
1047 context.bindTexture(GL_TEXTURE_2D, metaballsTex);
1048
1049 context.enable(GL_STENCIL_TEST);
1050 context.stencilFunc(GL_EQUAL, 1, 0xffffffffu);
1051 shader.setUnit(context, shaderID, 0);
1052 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1053
1054 context.stencilFunc(GL_EQUAL, 2, 0xffffffffu);
1055 shader.setUnit(context, shaderID, 1);
1056 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1057
1058 context.disable(GL_STENCIL_TEST);
1059
1060 if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
1061 {
1062 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1063 context.activeTexture(GL_TEXTURE0);
1064 context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
1065 context.viewport(0, 0, context.getWidth(), context.getHeight());
1066 shader.setUnit(context, shaderID, 0);
1067 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1068 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
1069 }
1070 else
1071 {
1072 // clear alpha channel for GL_RGB5_A1 format because test
1073 // thresholds for the alpha channel do not account for dithering
1074 if(getConfig().colorbufferFormat == GL_RGB5_A1)
1075 {
1076 context.colorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
1077 context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
1078 context.clear(GL_COLOR_BUFFER_BIT);
1079 context.colorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1080 }
1081
1082 context.readPixels(dst, 0, 0, width, height);
1083 }
1084 }
1085
isConfigSupported(const FboConfig & config)1086 bool StencilClearsTest::isConfigSupported (const FboConfig& config)
1087 {
1088 return config.stencilbufferType != GL_NONE;
1089 }
1090
1091 class StencilTest : public FboRenderCase
1092 {
1093 public:
1094 StencilTest (Context& context, const FboConfig& config, bool npot = false);
~StencilTest(void)1095 virtual ~StencilTest (void) {};
1096
1097 void render (sglr::Context& context, Surface& dst);
1098
1099 static bool isConfigSupported (const FboConfig& config);
1100
1101 private:
1102 int m_fboWidth;
1103 int m_fboHeight;
1104 };
1105
1106 class StencilNpotTest : public StencilTest
1107 {
1108 public:
StencilNpotTest(Context & context,const FboConfig & config)1109 StencilNpotTest (Context& context, const FboConfig& config)
1110 : StencilTest(context, config, true)
1111 {
1112 }
1113 };
1114
StencilTest(Context & context,const FboConfig & config,bool npot)1115 StencilTest::StencilTest (Context& context, const FboConfig& config, bool npot)
1116 : FboRenderCase (context, (string(npot ? "npot_" : "") + config.getName()).c_str(), "Stencil ops", config)
1117 , m_fboWidth (npot ? 99 : 128)
1118 , m_fboHeight (npot ? 110 : 128)
1119 {
1120 }
1121
isConfigSupported(const FboConfig & config)1122 bool StencilTest::isConfigSupported (const FboConfig& config)
1123 {
1124 return config.stencilbufferType != GL_NONE;
1125 }
1126
render(sglr::Context & ctx,Surface & dst)1127 void StencilTest::render (sglr::Context& ctx, Surface& dst)
1128 {
1129 FlatColorShader colorShader;
1130 SingleTex2DShader texShader;
1131 deUint32 colorShaderID = ctx.createProgram(&colorShader);
1132 deUint32 texShaderID = ctx.createProgram(&texShader);
1133 int width = m_fboWidth;
1134 int height = m_fboHeight;
1135 int texWidth = 64;
1136 int texHeight = 64;
1137 deUint32 quadsTex = 1;
1138 deUint32 metaballsTex = 2;
1139 bool depth = getConfig().depthbufferType != GL_NONE;
1140
1141 createQuadsTex2D(ctx, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, texWidth, texHeight);
1142 createMetaballsTex2D(ctx, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, texWidth, texHeight);
1143
1144 Framebuffer fbo(ctx, getConfig(), width, height);
1145 fbo.checkCompleteness();
1146
1147 // Bind framebuffer and clear
1148 ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
1149 ctx.viewport(0, 0, width, height);
1150 ctx.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
1151 ctx.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
1152
1153 // Render intersecting quads - increment stencil on depth pass
1154 ctx.enable(GL_DEPTH_TEST);
1155 ctx.enable(GL_STENCIL_TEST);
1156 ctx.stencilFunc(GL_ALWAYS, 0, 0xffu);
1157 ctx.stencilOp(GL_KEEP, GL_KEEP, GL_INCR);
1158
1159 colorShader.setColor(ctx, colorShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f));
1160 sglr::drawQuad(ctx, colorShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
1161
1162 ctx.bindTexture(GL_TEXTURE_2D, quadsTex);
1163 texShader.setUnit(ctx, texShaderID, 0);
1164 sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(+1.0f, +1.0f, +1.0f));
1165
1166 // Draw quad with stencil test (stencil == 1 or 2 depending on depth) - decrement on stencil failure
1167 ctx.disable(GL_DEPTH_TEST);
1168 ctx.stencilFunc(GL_EQUAL, depth ? 2 : 1, 0xffu);
1169 ctx.stencilOp(GL_DECR, GL_KEEP, GL_KEEP);
1170 colorShader.setColor(ctx, colorShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
1171 sglr::drawQuad(ctx, colorShaderID, Vec3(-0.5f, -0.5f, 0.0f), Vec3(+0.5f, +0.5f, 0.0f));
1172
1173 // Draw metaballs with stencil test where stencil > 1 or 2 depending on depth buffer
1174 ctx.bindTexture(GL_TEXTURE_2D, metaballsTex);
1175 ctx.stencilFunc(GL_GREATER, depth ? 1 : 2, 0xffu);
1176 ctx.stencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
1177 sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
1178
1179 ctx.disable(GL_STENCIL_TEST);
1180
1181 if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
1182 {
1183 ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);
1184 ctx.activeTexture(GL_TEXTURE0);
1185 ctx.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
1186 ctx.viewport(0, 0, ctx.getWidth(), ctx.getHeight());
1187 sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1188 ctx.readPixels(dst, 0, 0, ctx.getWidth(), ctx.getHeight());
1189 }
1190 else
1191 ctx.readPixels(dst, 0, 0, width, height);
1192 }
1193
1194 class SharedColorbufferTest : public FboRenderCase
1195 {
1196 public:
1197 SharedColorbufferTest (Context& context, const FboConfig& config);
~SharedColorbufferTest(void)1198 virtual ~SharedColorbufferTest (void) {};
1199
1200 void render (sglr::Context& context, Surface& dst);
1201 };
1202
SharedColorbufferTest(Context & context,const FboConfig & config)1203 SharedColorbufferTest::SharedColorbufferTest (Context& context, const FboConfig& config)
1204 : FboRenderCase(context, config.getName().c_str(), "Shared colorbuffer", config)
1205 {
1206 }
1207
render(sglr::Context & context,Surface & dst)1208 void SharedColorbufferTest::render (sglr::Context& context, Surface& dst)
1209 {
1210 SingleTex2DShader shader;
1211 deUint32 shaderID = context.createProgram(&shader);
1212 int width = 128;
1213 int height = 128;
1214 // bool depth = getConfig().depthbufferFormat != GL_NONE;
1215 bool stencil = getConfig().stencilbufferFormat != GL_NONE;
1216
1217 // Textures
1218 deUint32 quadsTex = 1;
1219 deUint32 metaballsTex = 2;
1220 createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
1221 createMetaballsTex2D(context, metaballsTex, GL_RGBA, GL_UNSIGNED_BYTE, 64, 64);
1222
1223 context.viewport(0, 0, width, height);
1224
1225 shader.setUnit(context, shaderID, 0);
1226
1227 // Fbo A
1228 Framebuffer fboA(context, getConfig(), width, height);
1229 fboA.checkCompleteness();
1230
1231 // Fbo B - don't create colorbuffer
1232 FboConfig cfg = getConfig();
1233 cfg.colorbufferType = GL_NONE;
1234 cfg.colorbufferFormat = GL_NONE;
1235 Framebuffer fboB(context, cfg, width, height);
1236
1237 // Attach color buffer from fbo A
1238 context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
1239 switch (getConfig().colorbufferType)
1240 {
1241 case GL_TEXTURE_2D:
1242 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboA.getColorbuffer(), 0);
1243 break;
1244
1245 case GL_RENDERBUFFER:
1246 context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, fboA.getColorbuffer());
1247 break;
1248
1249 default:
1250 DE_ASSERT(false);
1251 }
1252
1253 // Clear depth and stencil in fbo B
1254 context.clear(GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
1255
1256 // Render quads to fbo 1, with depth 0.0
1257 context.bindFramebuffer(GL_FRAMEBUFFER, fboA.getFramebuffer());
1258 context.bindTexture(GL_TEXTURE_2D, quadsTex);
1259 context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
1260 context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
1261
1262 if (stencil)
1263 {
1264 // Stencil to 1 in fbo A
1265 context.clearStencil(1);
1266 context.clear(GL_STENCIL_BUFFER_BIT);
1267 }
1268
1269 context.enable(GL_DEPTH_TEST);
1270 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1271 context.disable(GL_DEPTH_TEST);
1272
1273 // Blend metaballs to fbo 2
1274 context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
1275 context.bindTexture(GL_TEXTURE_2D, metaballsTex);
1276 context.enable(GL_BLEND);
1277 context.blendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
1278 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1279
1280 // Render small quad that is only visible if depth buffer is not shared with fbo A - or there is no depth bits
1281 context.bindTexture(GL_TEXTURE_2D, quadsTex);
1282 context.enable(GL_DEPTH_TEST);
1283 sglr::drawQuad(context, shaderID, Vec3(0.5f, 0.5f, 0.5f), Vec3(1.0f, 1.0f, 0.5f));
1284 context.disable(GL_DEPTH_TEST);
1285
1286 if (stencil)
1287 {
1288 FlatColorShader flatShader;
1289 deUint32 flatShaderID = context.createProgram(&flatShader);
1290
1291 flatShader.setColor(context, flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
1292
1293 // Clear subset of stencil buffer to 1
1294 context.enable(GL_SCISSOR_TEST);
1295 context.scissor(10, 10, 12, 25);
1296 context.clearStencil(1);
1297 context.clear(GL_STENCIL_BUFFER_BIT);
1298 context.disable(GL_SCISSOR_TEST);
1299
1300 // Render quad with stencil mask == 1
1301 context.enable(GL_STENCIL_TEST);
1302 context.stencilFunc(GL_EQUAL, 1, 0xffu);
1303 sglr::drawQuad(context, flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1304 context.disable(GL_STENCIL_TEST);
1305 }
1306
1307 // Get results
1308 if (fboA.getConfig().colorbufferType == GL_TEXTURE_2D)
1309 {
1310 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1311 context.bindTexture(GL_TEXTURE_2D, fboA.getColorbuffer());
1312 context.viewport(0, 0, context.getWidth(), context.getHeight());
1313 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1314 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
1315 }
1316 else
1317 context.readPixels(dst, 0, 0, width, height);
1318 }
1319
1320 class SharedColorbufferClearsTest : public FboRenderCase
1321 {
1322 public:
1323 SharedColorbufferClearsTest (Context& context, const FboConfig& config);
~SharedColorbufferClearsTest(void)1324 virtual ~SharedColorbufferClearsTest (void) {}
1325
1326 static bool isConfigSupported (const FboConfig& config);
1327 void render (sglr::Context& context, Surface& dst);
1328 };
1329
SharedColorbufferClearsTest(Context & context,const FboConfig & config)1330 SharedColorbufferClearsTest::SharedColorbufferClearsTest (Context& context, const FboConfig& config)
1331 : FboRenderCase(context, config.getName().c_str(), "Shared colorbuffer clears", config)
1332 {
1333 }
1334
isConfigSupported(const FboConfig & config)1335 bool SharedColorbufferClearsTest::isConfigSupported (const FboConfig& config)
1336 {
1337 return config.colorbufferType != GL_NONE &&
1338 config.depthbufferType == GL_NONE &&
1339 config.stencilbufferType == GL_NONE;
1340 }
1341
render(sglr::Context & context,Surface & dst)1342 void SharedColorbufferClearsTest::render (sglr::Context& context, Surface& dst)
1343 {
1344 int width = 128;
1345 int height = 128;
1346 deUint32 colorbuffer = 1;
1347
1348 checkColorFormatSupport(context, getConfig().colorbufferFormat);
1349
1350 // Single colorbuffer
1351 if (getConfig().colorbufferType == GL_TEXTURE_2D)
1352 {
1353 context.bindTexture(GL_TEXTURE_2D, colorbuffer);
1354 context.texImage2D(GL_TEXTURE_2D, 0, getConfig().colorbufferFormat, width, height);
1355 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1356 }
1357 else
1358 {
1359 DE_ASSERT(getConfig().colorbufferType == GL_RENDERBUFFER);
1360 context.bindRenderbuffer(GL_RENDERBUFFER, colorbuffer);
1361 context.renderbufferStorage(GL_RENDERBUFFER, getConfig().colorbufferFormat, width, height);
1362 }
1363
1364 // Multiple framebuffers sharing the colorbuffer
1365 for (int fbo = 1; fbo <= 3; fbo++)
1366 {
1367 context.bindFramebuffer(GL_FRAMEBUFFER, fbo);
1368
1369 if (getConfig().colorbufferType == GL_TEXTURE_2D)
1370 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer, 0);
1371 else
1372 context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuffer);
1373 }
1374
1375 context.bindFramebuffer(GL_FRAMEBUFFER, 1);
1376
1377 // Check completeness
1378 {
1379 GLenum status = context.checkFramebufferStatus(GL_FRAMEBUFFER);
1380 if (status != GL_FRAMEBUFFER_COMPLETE)
1381 throw FboIncompleteException(getConfig(), status, __FILE__, __LINE__);
1382 }
1383
1384 // Render to them
1385 context.viewport(0, 0, width, height);
1386 context.clearColor(0.0f, 0.0f, 1.0f, 1.0f);
1387 context.clear(GL_COLOR_BUFFER_BIT);
1388
1389 context.enable(GL_SCISSOR_TEST);
1390
1391 context.bindFramebuffer(GL_FRAMEBUFFER, 2);
1392 context.clearColor(0.6f, 0.0f, 0.0f, 1.0f);
1393 context.scissor(10, 10, 64, 64);
1394 context.clear(GL_COLOR_BUFFER_BIT);
1395 context.clearColor(0.0f, 0.6f, 0.0f, 1.0f);
1396 context.scissor(60, 60, 40, 20);
1397 context.clear(GL_COLOR_BUFFER_BIT);
1398
1399 context.bindFramebuffer(GL_FRAMEBUFFER, 3);
1400 context.clearColor(0.0f, 0.0f, 0.6f, 1.0f);
1401 context.scissor(20, 20, 100, 10);
1402 context.clear(GL_COLOR_BUFFER_BIT);
1403
1404 context.bindFramebuffer(GL_FRAMEBUFFER, 1);
1405 context.clearColor(0.6f, 0.0f, 0.6f, 1.0f);
1406 context.scissor(20, 20, 5, 100);
1407 context.clear(GL_COLOR_BUFFER_BIT);
1408
1409 context.disable(GL_SCISSOR_TEST);
1410
1411 if (getConfig().colorbufferType == GL_TEXTURE_2D)
1412 {
1413 SingleTex2DShader shader;
1414 deUint32 shaderID = context.createProgram(&shader);
1415
1416 shader.setUnit(context, shaderID, 0);
1417
1418 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1419 context.viewport(0, 0, context.getWidth(), context.getHeight());
1420 sglr::drawQuad(context, shaderID, Vec3(-0.9f, -0.9f, 0.0f), Vec3(0.9f, 0.9f, 0.0f));
1421 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
1422 }
1423 else
1424 context.readPixels(dst, 0, 0, width, height);
1425 }
1426
1427 class SharedDepthbufferTest : public FboRenderCase
1428 {
1429 public:
1430 SharedDepthbufferTest (Context& context, const FboConfig& config);
~SharedDepthbufferTest(void)1431 virtual ~SharedDepthbufferTest (void) {};
1432
1433 static bool isConfigSupported (const FboConfig& config);
1434 void render (sglr::Context& context, Surface& dst);
1435 };
1436
SharedDepthbufferTest(Context & context,const FboConfig & config)1437 SharedDepthbufferTest::SharedDepthbufferTest (Context& context, const FboConfig& config)
1438 : FboRenderCase(context, config.getName().c_str(), "Shared depthbuffer", config)
1439 {
1440 }
1441
isConfigSupported(const FboConfig & config)1442 bool SharedDepthbufferTest::isConfigSupported (const FboConfig& config)
1443 {
1444 return config.depthbufferType == GL_RENDERBUFFER;
1445 }
1446
render(sglr::Context & context,Surface & dst)1447 void SharedDepthbufferTest::render (sglr::Context& context, Surface& dst)
1448 {
1449 SingleTex2DShader texShader;
1450 FlatColorShader colorShader;
1451 deUint32 texShaderID = context.createProgram(&texShader);
1452 deUint32 colorShaderID = context.createProgram(&colorShader);
1453 int width = 128;
1454 int height = 128;
1455 bool stencil = getConfig().stencilbufferType != GL_NONE;
1456
1457 // Setup shaders
1458 texShader.setUnit(context, texShaderID, 0);
1459 colorShader.setColor(context, colorShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
1460
1461 // Textures
1462 deUint32 metaballsTex = 5;
1463 deUint32 quadsTex = 6;
1464 createMetaballsTex2D(context, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
1465 createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
1466
1467 context.viewport(0, 0, width, height);
1468
1469 // Fbo A
1470 Framebuffer fboA(context, getConfig(), width, height);
1471 fboA.checkCompleteness();
1472
1473 // Fbo B
1474 FboConfig cfg = getConfig();
1475 cfg.depthbufferType = GL_NONE;
1476 cfg.depthbufferFormat = GL_NONE;
1477 Framebuffer fboB(context, cfg, width, height);
1478
1479 // Bind depth buffer from fbo A to fbo B
1480 DE_ASSERT(fboA.getConfig().depthbufferType == GL_RENDERBUFFER);
1481 context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
1482 context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fboA.getDepthbuffer());
1483
1484 // Clear fbo B color to red and stencil to 1
1485 context.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
1486 context.clearStencil(1);
1487 context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
1488
1489 // Enable depth test.
1490 context.enable(GL_DEPTH_TEST);
1491
1492 // Render quad to fbo A
1493 context.bindFramebuffer(GL_FRAMEBUFFER, fboA.getFramebuffer());
1494 context.bindTexture(GL_TEXTURE_2D, quadsTex);
1495 context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
1496 context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
1497 sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1498
1499 // Render metaballs to fbo B
1500 context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
1501 context.bindTexture(GL_TEXTURE_2D, metaballsTex);
1502 sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));
1503
1504 context.disable(GL_DEPTH_TEST);
1505
1506 if (stencil)
1507 {
1508 // Clear subset of stencil buffer to 0
1509 context.enable(GL_SCISSOR_TEST);
1510 context.scissor(10, 10, 12, 25);
1511 context.clearStencil(0);
1512 context.clear(GL_STENCIL_BUFFER_BIT);
1513 context.disable(GL_SCISSOR_TEST);
1514
1515 // Render quad with stencil mask == 0
1516 context.enable(GL_STENCIL_TEST);
1517 context.stencilFunc(GL_EQUAL, 0, 0xffu);
1518 sglr::drawQuad(context, colorShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1519 context.disable(GL_STENCIL_TEST);
1520 }
1521
1522 if (getConfig().colorbufferType == GL_TEXTURE_2D)
1523 {
1524 // Render both to screen
1525 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1526 context.viewport(0, 0, context.getWidth(), context.getHeight());
1527 context.bindTexture(GL_TEXTURE_2D, fboA.getColorbuffer());
1528 sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(0.0f, 1.0f, 0.0f));
1529 context.bindTexture(GL_TEXTURE_2D, fboB.getColorbuffer());
1530 sglr::drawQuad(context, texShaderID, Vec3(0.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1531
1532 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
1533 }
1534 else
1535 {
1536 // Read results from fbo B
1537 context.readPixels(dst, 0, 0, width, height);
1538 }
1539 }
1540
1541 class TexSubImageAfterRenderTest : public FboRenderCase
1542 {
1543 public:
1544 TexSubImageAfterRenderTest (Context& context, const FboConfig& config);
~TexSubImageAfterRenderTest(void)1545 virtual ~TexSubImageAfterRenderTest (void) {}
1546
1547 static bool isConfigSupported (const FboConfig& config);
1548 void render (sglr::Context& context, Surface& dst);
1549 };
1550
TexSubImageAfterRenderTest(Context & context,const FboConfig & config)1551 TexSubImageAfterRenderTest::TexSubImageAfterRenderTest (Context& context, const FboConfig& config)
1552 : FboRenderCase(context, (string("after_render_") + config.getName()).c_str(), "TexSubImage after rendering to texture", config)
1553 {
1554 }
1555
isConfigSupported(const FboConfig & config)1556 bool TexSubImageAfterRenderTest::isConfigSupported (const FboConfig& config)
1557 {
1558 return config.colorbufferType == GL_TEXTURE_2D &&
1559 (config.colorbufferFormat == GL_RGB || config.colorbufferFormat == GL_RGBA) &&
1560 config.depthbufferType == GL_NONE &&
1561 config.stencilbufferType == GL_NONE;
1562 }
1563
render(sglr::Context & context,Surface & dst)1564 void TexSubImageAfterRenderTest::render (sglr::Context& context, Surface& dst)
1565 {
1566 SingleTex2DShader shader;
1567 deUint32 shaderID = context.createProgram(&shader);
1568 bool isRGBA = getConfig().colorbufferFormat == GL_RGBA;
1569
1570 tcu::TextureLevel fourQuads(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), 64, 64);
1571 tcu::fillWithRGBAQuads(fourQuads.getAccess());
1572
1573 tcu::TextureLevel metaballs(tcu::TextureFormat(isRGBA ? tcu::TextureFormat::RGBA : tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), 64, 64);
1574 tcu::fillWithMetaballs(metaballs.getAccess(), 5, 3);
1575
1576 shader.setUnit(context, shaderID, 0);
1577
1578 deUint32 fourQuadsTex = 1;
1579 context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
1580 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1581 context.texImage2D(GL_TEXTURE_2D, 0, GL_RGB, 64, 64, 0, GL_RGB, GL_UNSIGNED_BYTE, fourQuads.getAccess().getDataPtr());
1582
1583 context.bindFramebuffer(GL_FRAMEBUFFER, 1);
1584
1585 deUint32 fboTex = 2;
1586 context.bindTexture(GL_TEXTURE_2D, fboTex);
1587 context.texImage2D(GL_TEXTURE_2D, 0, isRGBA ? GL_RGBA : GL_RGB, 128, 128);
1588 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1589 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0);
1590
1591 // Render to fbo
1592 context.viewport(0, 0, 128, 128);
1593 context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
1594 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1595
1596 // Update texture using TexSubImage2D
1597 context.bindTexture(GL_TEXTURE_2D, fboTex);
1598 context.texSubImage2D(GL_TEXTURE_2D, 0, 32, 32, 64, 64, isRGBA ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, metaballs.getAccess().getDataPtr());
1599
1600 // Draw to screen
1601 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1602 context.viewport(0, 0, context.getWidth(), context.getHeight());
1603 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1604 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
1605 }
1606
1607 class TexSubImageBetweenRenderTest : public FboRenderCase
1608 {
1609 public:
1610 TexSubImageBetweenRenderTest (Context& context, const FboConfig& config);
~TexSubImageBetweenRenderTest(void)1611 virtual ~TexSubImageBetweenRenderTest (void) {}
1612
1613 static bool isConfigSupported (const FboConfig& config);
1614 void render (sglr::Context& context, Surface& dst);
1615 };
1616
TexSubImageBetweenRenderTest(Context & context,const FboConfig & config)1617 TexSubImageBetweenRenderTest::TexSubImageBetweenRenderTest (Context& context, const FboConfig& config)
1618 : FboRenderCase(context, (string("between_render_") + config.getName()).c_str(), "TexSubImage between rendering calls", config)
1619 {
1620 }
1621
isConfigSupported(const FboConfig & config)1622 bool TexSubImageBetweenRenderTest::isConfigSupported (const FboConfig& config)
1623 {
1624 return config.colorbufferType == GL_TEXTURE_2D &&
1625 (config.colorbufferFormat == GL_RGB || config.colorbufferFormat == GL_RGBA) &&
1626 config.depthbufferType == GL_NONE &&
1627 config.stencilbufferType == GL_NONE;
1628 }
1629
render(sglr::Context & context,Surface & dst)1630 void TexSubImageBetweenRenderTest::render (sglr::Context& context, Surface& dst)
1631 {
1632 SingleTex2DShader shader;
1633 deUint32 shaderID = context.createProgram(&shader);
1634 bool isRGBA = getConfig().colorbufferFormat == GL_RGBA;
1635
1636 tcu::TextureLevel fourQuads(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), 64, 64);
1637 tcu::fillWithRGBAQuads(fourQuads.getAccess());
1638
1639 tcu::TextureLevel metaballs(tcu::TextureFormat(isRGBA ? tcu::TextureFormat::RGBA : tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), 64, 64);
1640 tcu::fillWithMetaballs(metaballs.getAccess(), 5, 3);
1641
1642 tcu::TextureLevel metaballs2(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 64, 64);
1643 tcu::fillWithMetaballs(metaballs2.getAccess(), 5, 4);
1644
1645 deUint32 metaballsTex = 3;
1646 context.bindTexture(GL_TEXTURE_2D, metaballsTex);
1647 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1648 context.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, metaballs2.getAccess().getDataPtr());
1649
1650 deUint32 fourQuadsTex = 1;
1651 context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
1652 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1653 context.texImage2D(GL_TEXTURE_2D, 0, GL_RGB, 64, 64, 0, GL_RGB, GL_UNSIGNED_BYTE, fourQuads.getAccess().getDataPtr());
1654
1655 context.bindFramebuffer(GL_FRAMEBUFFER, 1);
1656
1657 deUint32 fboTex = 2;
1658 context.bindTexture(GL_TEXTURE_2D, fboTex);
1659 context.texImage2D(GL_TEXTURE_2D, 0, isRGBA ? GL_RGBA : GL_RGB, 128, 128);
1660 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1661 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0);
1662
1663 shader.setUnit(context, shaderID, 0);
1664
1665 // Render to fbo
1666 context.viewport(0, 0, 128, 128);
1667 context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
1668 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1669
1670 // Update texture using TexSubImage2D
1671 context.bindTexture(GL_TEXTURE_2D, fboTex);
1672 context.texSubImage2D(GL_TEXTURE_2D, 0, 32, 32, 64, 64, isRGBA ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, metaballs.getAccess().getDataPtr());
1673
1674 // Render again to fbo
1675 context.bindTexture(GL_TEXTURE_2D, metaballsTex);
1676 context.enable(GL_BLEND);
1677 context.blendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
1678 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1679 context.disable(GL_BLEND);
1680
1681 // Draw to screen
1682 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1683 context.viewport(0, 0, context.getWidth(), context.getHeight());
1684 context.bindTexture(GL_TEXTURE_2D, fboTex);
1685 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1686
1687 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
1688 }
1689
1690 class ResizeTest : public FboRenderCase
1691 {
1692 public:
1693 ResizeTest (Context& context, const FboConfig& config);
~ResizeTest(void)1694 virtual ~ResizeTest (void) {}
1695
1696 void render (sglr::Context& context, Surface& dst);
1697 };
1698
ResizeTest(Context & context,const FboConfig & config)1699 ResizeTest::ResizeTest (Context& context, const FboConfig& config)
1700 : FboRenderCase(context, config.getName().c_str(), "Resize framebuffer", config)
1701 {
1702 }
1703
render(sglr::Context & context,Surface & dst)1704 void ResizeTest::render (sglr::Context& context, Surface& dst)
1705 {
1706 SingleTex2DShader texShader;
1707 FlatColorShader colorShader;
1708 deUint32 texShaderID = context.createProgram(&texShader);
1709 deUint32 colorShaderID = context.createProgram(&colorShader);
1710 deUint32 quadsTex = 1;
1711 deUint32 metaballsTex = 2;
1712 bool depth = getConfig().depthbufferType != GL_NONE;
1713 bool stencil = getConfig().stencilbufferType != GL_NONE;
1714
1715 createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
1716 createMetaballsTex2D(context, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 32, 32);
1717
1718 Framebuffer fbo(context, getConfig(), 128, 128);
1719 fbo.checkCompleteness();
1720
1721 // Setup shaders
1722 texShader.setUnit(context, texShaderID, 0);
1723 colorShader.setColor(context, colorShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
1724
1725 // Render quads
1726 context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
1727 context.viewport(0, 0, 128, 128);
1728 context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
1729 context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
1730 context.bindTexture(GL_TEXTURE_2D, quadsTex);
1731 sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1732
1733 if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
1734 {
1735 // Render fbo to screen
1736 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1737 context.viewport(0, 0, context.getWidth(), context.getHeight());
1738 context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
1739 sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1740
1741 // Restore binding
1742 context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
1743 }
1744
1745 int newWidth = 64;
1746 int newHeight = 32;
1747
1748 // Resize buffers
1749 switch (fbo.getConfig().colorbufferType)
1750 {
1751 case GL_TEXTURE_2D:
1752 context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
1753 context.texImage2D(GL_TEXTURE_2D, 0, fbo.getConfig().colorbufferFormat, newWidth, newHeight);
1754 break;
1755
1756 case GL_RENDERBUFFER:
1757 context.bindRenderbuffer(GL_RENDERBUFFER, fbo.getColorbuffer());
1758 context.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().colorbufferFormat, newWidth, newHeight);
1759 break;
1760
1761 default:
1762 DE_ASSERT(false);
1763 }
1764
1765 if (depth)
1766 {
1767 DE_ASSERT(fbo.getConfig().depthbufferType == GL_RENDERBUFFER);
1768 context.bindRenderbuffer(GL_RENDERBUFFER, fbo.getDepthbuffer());
1769 context.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().depthbufferFormat, newWidth, newHeight);
1770 }
1771
1772 if (stencil)
1773 {
1774 DE_ASSERT(fbo.getConfig().stencilbufferType == GL_RENDERBUFFER);
1775 context.bindRenderbuffer(GL_RENDERBUFFER, fbo.getStencilbuffer());
1776 context.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().stencilbufferFormat, newWidth, newHeight);
1777 }
1778
1779 // Render to resized fbo
1780 context.viewport(0, 0, newWidth, newHeight);
1781 context.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
1782 context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
1783
1784 context.enable(GL_DEPTH_TEST);
1785
1786 context.bindTexture(GL_TEXTURE_2D, metaballsTex);
1787 sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
1788
1789 context.bindTexture(GL_TEXTURE_2D, quadsTex);
1790 sglr::drawQuad(context, texShaderID, Vec3(0.0f, 0.0f, -1.0f), Vec3(+1.0f, +1.0f, 1.0f));
1791
1792 context.disable(GL_DEPTH_TEST);
1793
1794 if (stencil)
1795 {
1796 context.enable(GL_SCISSOR_TEST);
1797 context.scissor(10, 10, 5, 15);
1798 context.clearStencil(1);
1799 context.clear(GL_STENCIL_BUFFER_BIT);
1800 context.disable(GL_SCISSOR_TEST);
1801
1802 context.enable(GL_STENCIL_TEST);
1803 context.stencilFunc(GL_EQUAL, 1, 0xffu);
1804 sglr::drawQuad(context, colorShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
1805 context.disable(GL_STENCIL_TEST);
1806 }
1807
1808 if (getConfig().colorbufferType == GL_TEXTURE_2D)
1809 {
1810 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1811 context.viewport(0, 0, context.getWidth(), context.getHeight());
1812 context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
1813 sglr::drawQuad(context, texShaderID, Vec3(-0.5f, -0.5f, 0.0f), Vec3(0.5f, 0.5f, 0.0f));
1814 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
1815 }
1816 else
1817 context.readPixels(dst, 0, 0, newWidth, newHeight);
1818 }
1819
1820 template <GLenum Buffers>
1821 class RecreateBuffersTest : public FboRenderCase
1822 {
1823 public:
1824 RecreateBuffersTest (Context& context, const FboConfig& config, bool rebind);
~RecreateBuffersTest(void)1825 virtual ~RecreateBuffersTest (void) {}
1826
1827 static bool isConfigSupported (const FboConfig& config);
1828 void render (sglr::Context& context, Surface& dst);
1829
1830 private:
1831 bool m_rebind;
1832 };
1833
1834 template <GLenum Buffers>
1835 class RecreateBuffersNoRebindTest : public RecreateBuffersTest<Buffers>
1836 {
1837 public:
RecreateBuffersNoRebindTest(Context & context,const FboConfig & config)1838 RecreateBuffersNoRebindTest (Context& context, const FboConfig& config)
1839 : RecreateBuffersTest<Buffers>(context, config, false)
1840 {
1841 }
1842 };
1843
1844 template <GLenum Buffers>
1845 class RecreateBuffersRebindTest : public RecreateBuffersTest<Buffers>
1846 {
1847 public:
RecreateBuffersRebindTest(Context & context,const FboConfig & config)1848 RecreateBuffersRebindTest (Context& context, const FboConfig& config)
1849 : RecreateBuffersTest<Buffers>(context, config, true)
1850 {
1851 }
1852 };
1853
1854 template <GLenum Buffers>
RecreateBuffersTest(Context & context,const FboConfig & config,bool rebind)1855 RecreateBuffersTest<Buffers>::RecreateBuffersTest (Context& context, const FboConfig& config, bool rebind)
1856 : FboRenderCase (context, (string(rebind ? "rebind_" : "no_rebind_") + config.getName()).c_str(), "Recreate buffers", config)
1857 , m_rebind (rebind)
1858 {
1859 }
1860
1861 template <GLenum Buffers>
isConfigSupported(const FboConfig & config)1862 bool RecreateBuffersTest<Buffers>::isConfigSupported (const FboConfig& config)
1863 {
1864 if ((Buffers & GL_COLOR_BUFFER_BIT) && config.colorbufferType == GL_NONE)
1865 return false;
1866 if ((Buffers & GL_DEPTH_BUFFER_BIT) && config.depthbufferType == GL_NONE)
1867 return false;
1868 if ((Buffers & GL_STENCIL_BUFFER_BIT) && config.stencilbufferType == GL_NONE)
1869 return false;
1870 return true;
1871 }
1872
1873 template <GLenum Buffers>
render(sglr::Context & ctx,Surface & dst)1874 void RecreateBuffersTest<Buffers>::render (sglr::Context& ctx, Surface& dst)
1875 {
1876 SingleTex2DShader texShader;
1877 deUint32 texShaderID = ctx.createProgram(&texShader);
1878 int width = 128;
1879 int height = 128;
1880 deUint32 metaballsTex = 1;
1881 deUint32 quadsTex = 2;
1882 bool stencil = getConfig().stencilbufferType != GL_NONE;
1883
1884 createQuadsTex2D(ctx, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
1885 createMetaballsTex2D(ctx, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
1886
1887 Framebuffer fbo(ctx, getConfig(), width, height);
1888 fbo.checkCompleteness();
1889
1890 // Setup shader
1891 texShader.setUnit(ctx, texShaderID, 0);
1892
1893 // Draw scene
1894 ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
1895 ctx.viewport(0, 0, width, height);
1896 ctx.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
1897 ctx.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
1898
1899 ctx.enable(GL_DEPTH_TEST);
1900
1901 ctx.bindTexture(GL_TEXTURE_2D, quadsTex);
1902 sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1903
1904 if (stencil)
1905 {
1906 ctx.enable(GL_SCISSOR_TEST);
1907 ctx.scissor(width/4, height/4, width/2, height/2);
1908 ctx.clearStencil(1);
1909 ctx.clear(GL_STENCIL_BUFFER_BIT);
1910 ctx.disable(GL_SCISSOR_TEST);
1911 }
1912
1913 // Recreate buffers
1914 if (!m_rebind)
1915 ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);
1916
1917 if (Buffers & GL_COLOR_BUFFER_BIT)
1918 {
1919 deUint32 colorbuf = fbo.getColorbuffer();
1920 switch (fbo.getConfig().colorbufferType)
1921 {
1922 case GL_TEXTURE_2D:
1923 ctx.deleteTextures(1, &colorbuf);
1924 ctx.bindTexture(GL_TEXTURE_2D, colorbuf);
1925 ctx.texImage2D(GL_TEXTURE_2D, 0, fbo.getConfig().colorbufferFormat, width, height);
1926 ctx.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1927
1928 if (m_rebind)
1929 ctx.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuf, 0);
1930 break;
1931
1932 case GL_RENDERBUFFER:
1933 ctx.deleteRenderbuffers(1, &colorbuf);
1934 ctx.bindRenderbuffer(GL_RENDERBUFFER, colorbuf);
1935 ctx.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().colorbufferFormat, width, height);
1936
1937 if (m_rebind)
1938 ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuf);
1939 break;
1940
1941 default:
1942 DE_ASSERT(false);
1943 }
1944 }
1945
1946 if (Buffers & GL_DEPTH_BUFFER_BIT)
1947 {
1948 deUint32 depthbuf = fbo.getDepthbuffer();
1949 DE_ASSERT(fbo.getConfig().depthbufferType == GL_RENDERBUFFER);
1950
1951 ctx.deleteRenderbuffers(1, &depthbuf);
1952 ctx.bindRenderbuffer(GL_RENDERBUFFER, depthbuf);
1953 ctx.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().depthbufferFormat, width, height);
1954
1955 if (m_rebind)
1956 ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthbuf);
1957 }
1958
1959 if (Buffers & GL_STENCIL_BUFFER_BIT)
1960 {
1961 deUint32 stencilbuf = fbo.getStencilbuffer();
1962 DE_ASSERT(fbo.getConfig().stencilbufferType == GL_RENDERBUFFER);
1963
1964 ctx.deleteRenderbuffers(1, &stencilbuf);
1965 ctx.bindRenderbuffer(GL_RENDERBUFFER, stencilbuf);
1966 ctx.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().stencilbufferFormat, width, height);
1967
1968 if (m_rebind)
1969 ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, stencilbuf);
1970 }
1971
1972 if (!m_rebind)
1973 ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
1974
1975 ctx.clearColor(0.0f, 0.0f, 1.0f, 0.0f);
1976 ctx.clearStencil(0);
1977 ctx.clear(Buffers); // \note Clear only buffers that were re-created
1978
1979 if (stencil)
1980 {
1981 // \note Stencil test enabled only if we have stencil buffer
1982 ctx.enable(GL_STENCIL_TEST);
1983 ctx.stencilFunc(GL_EQUAL, 0, 0xffu);
1984 }
1985 ctx.bindTexture(GL_TEXTURE_2D, metaballsTex);
1986 sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 1.0f), Vec3(1.0f, 1.0f, -1.0f));
1987 if (stencil)
1988 ctx.disable(GL_STENCIL_TEST);
1989
1990 ctx.disable(GL_DEPTH_TEST);
1991
1992 // Read from fbo
1993 ctx.readPixels(dst, 0, 0, width, height);
1994 }
1995
1996 class RepeatedClearCase : public FboRenderCase
1997 {
1998 private:
makeConfig(deUint32 format)1999 static FboConfig makeConfig (deUint32 format)
2000 {
2001 FboConfig cfg;
2002 cfg.colorbufferType = GL_TEXTURE_2D;
2003 cfg.colorbufferFormat = format;
2004 cfg.depthbufferType = GL_NONE;
2005 cfg.stencilbufferType = GL_NONE;
2006 return cfg;
2007 }
2008
2009 public:
RepeatedClearCase(Context & context,deUint32 format)2010 RepeatedClearCase (Context& context, deUint32 format)
2011 : FboRenderCase(context, makeConfig(format).getName().c_str(), "Repeated clears", makeConfig(format))
2012 {
2013 }
2014
2015 protected:
render(sglr::Context & ctx,Surface & dst)2016 void render (sglr::Context& ctx, Surface& dst)
2017 {
2018 const int numRowsCols = 4;
2019 const int cellSize = 16;
2020 const int fboSizes[] = { cellSize, cellSize*numRowsCols };
2021
2022 SingleTex2DShader fboBlitShader;
2023 const deUint32 fboBlitShaderID = ctx.createProgram(&fboBlitShader);
2024
2025 de::Random rnd (18169662);
2026 deUint32 fbos[] = { 0, 0 };
2027 deUint32 textures[] = { 0, 0 };
2028
2029 ctx.genFramebuffers(2, &fbos[0]);
2030 ctx.genTextures(2, &textures[0]);
2031
2032 for (int fboNdx = 0; fboNdx < DE_LENGTH_OF_ARRAY(fbos); fboNdx++)
2033 {
2034 ctx.bindTexture(GL_TEXTURE_2D, textures[fboNdx]);
2035 ctx.texImage2D(GL_TEXTURE_2D, 0, getConfig().colorbufferFormat, fboSizes[fboNdx], fboSizes[fboNdx], 0,
2036 getConfig().colorbufferFormat, GL_UNSIGNED_BYTE, DE_NULL);
2037 ctx.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2038 ctx.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2039 ctx.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2040 ctx.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2041
2042 ctx.bindFramebuffer(GL_FRAMEBUFFER, fbos[fboNdx]);
2043 ctx.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[fboNdx], 0);
2044
2045 {
2046 const GLenum status = ctx.checkFramebufferStatus(GL_FRAMEBUFFER);
2047 if (status != GL_FRAMEBUFFER_COMPLETE)
2048 throw FboIncompleteException(getConfig(), status, __FILE__, __LINE__);
2049 }
2050 }
2051
2052 // larger fbo bound -- clear to transparent black
2053 ctx.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
2054 ctx.clear(GL_COLOR_BUFFER_BIT);
2055
2056 fboBlitShader.setUnit(ctx, fboBlitShaderID, 0);
2057 ctx.bindTexture(GL_TEXTURE_2D, textures[0]);
2058
2059 for (int cellY = 0; cellY < numRowsCols; cellY++)
2060 for (int cellX = 0; cellX < numRowsCols; cellX++)
2061 {
2062 const float r = rnd.getFloat();
2063 const float g = rnd.getFloat();
2064 const float b = rnd.getFloat();
2065 const float a = rnd.getFloat();
2066
2067 ctx.bindFramebuffer(GL_FRAMEBUFFER, fbos[0]);
2068 ctx.clearColor(r, g, b, a);
2069 ctx.clear(GL_COLOR_BUFFER_BIT);
2070
2071 ctx.bindFramebuffer(GL_FRAMEBUFFER, fbos[1]);
2072 ctx.viewport(cellX*cellSize, cellY*cellSize, cellSize, cellSize);
2073 sglr::drawQuad(ctx, fboBlitShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
2074 }
2075
2076 ctx.readPixels(dst, 0, 0, fboSizes[1], fboSizes[1]);
2077 }
2078 };
2079
2080 } // FboCases
2081
FboRenderTestGroup(Context & context)2082 FboRenderTestGroup::FboRenderTestGroup (Context& context)
2083 : TestCaseGroup(context, "render", "Rendering Tests")
2084 {
2085 }
2086
~FboRenderTestGroup(void)2087 FboRenderTestGroup::~FboRenderTestGroup (void)
2088 {
2089 }
2090
2091 namespace
2092 {
2093
2094 struct TypeFormatPair
2095 {
2096 GLenum type;
2097 GLenum format;
2098 };
2099
2100 template <typename CaseType>
addChildVariants(deqp::gles2::TestCaseGroup * group)2101 void addChildVariants (deqp::gles2::TestCaseGroup* group)
2102 {
2103 TypeFormatPair colorbufferConfigs[] =
2104 {
2105 // { GL_TEXTURE_2D, GL_ALPHA },
2106 // { GL_TEXTURE_2D, GL_LUMINANCE },
2107 // { GL_TEXTURE_2D, GL_LUMINANCE_ALPHA },
2108 { GL_TEXTURE_2D, GL_RGB },
2109 { GL_TEXTURE_2D, GL_RGBA },
2110 { GL_RENDERBUFFER, GL_RGB565 },
2111 { GL_RENDERBUFFER, GL_RGB5_A1 },
2112 { GL_RENDERBUFFER, GL_RGBA4 },
2113 // { GL_RENDERBUFFER, GL_RGBA16F },
2114 // { GL_RENDERBUFFER, GL_RGB16F }
2115 };
2116 TypeFormatPair depthbufferConfigs[] =
2117 {
2118 { GL_NONE, GL_NONE },
2119 { GL_RENDERBUFFER, GL_DEPTH_COMPONENT16 }
2120 };
2121 TypeFormatPair stencilbufferConfigs[] =
2122 {
2123 { GL_NONE, GL_NONE },
2124 { GL_RENDERBUFFER, GL_STENCIL_INDEX8 }
2125 };
2126
2127 for (int colorbufferNdx = 0; colorbufferNdx < DE_LENGTH_OF_ARRAY(colorbufferConfigs); colorbufferNdx++)
2128 for (int depthbufferNdx = 0; depthbufferNdx < DE_LENGTH_OF_ARRAY(depthbufferConfigs); depthbufferNdx++)
2129 for (int stencilbufferNdx = 0; stencilbufferNdx < DE_LENGTH_OF_ARRAY(stencilbufferConfigs); stencilbufferNdx++)
2130 {
2131 FboConfig config;
2132 config.colorbufferType = colorbufferConfigs[colorbufferNdx].type;
2133 config.colorbufferFormat = colorbufferConfigs[colorbufferNdx].format;
2134 config.depthbufferType = depthbufferConfigs[depthbufferNdx].type;
2135 config.depthbufferFormat = depthbufferConfigs[depthbufferNdx].format;
2136 config.stencilbufferType = stencilbufferConfigs[stencilbufferNdx].type;
2137 config.stencilbufferFormat = stencilbufferConfigs[stencilbufferNdx].format;
2138
2139 if (CaseType::isConfigSupported(config))
2140 group->addChild(new CaseType(group->getContext(), config));
2141 }
2142 }
2143
2144 template <typename CaseType>
createChildGroup(deqp::gles2::TestCaseGroup * parent,const char * name,const char * description)2145 void createChildGroup (deqp::gles2::TestCaseGroup* parent, const char* name, const char* description)
2146 {
2147 deqp::gles2::TestCaseGroup* tmpGroup = new deqp::gles2::TestCaseGroup(parent->getContext(), name, description);
2148 parent->addChild(tmpGroup);
2149 addChildVariants<CaseType>(tmpGroup);
2150 }
2151
2152 template <GLbitfield Buffers>
createRecreateBuffersGroup(deqp::gles2::TestCaseGroup * parent,const char * name,const char * description)2153 void createRecreateBuffersGroup (deqp::gles2::TestCaseGroup* parent, const char* name, const char* description)
2154 {
2155 deqp::gles2::TestCaseGroup* tmpGroup = new deqp::gles2::TestCaseGroup(parent->getContext(), name, description);
2156 parent->addChild(tmpGroup);
2157 addChildVariants<FboCases::RecreateBuffersRebindTest<Buffers> > (tmpGroup);
2158 addChildVariants<FboCases::RecreateBuffersNoRebindTest<Buffers> > (tmpGroup);
2159 }
2160
2161 } // anonymous
2162
init(void)2163 void FboRenderTestGroup::init (void)
2164 {
2165 createChildGroup<FboCases::ColorClearsTest> (this, "color_clear", "Color buffer clears");
2166 createChildGroup<FboCases::StencilClearsTest> (this, "stencil_clear", "Stencil buffer clears");
2167
2168 deqp::gles2::TestCaseGroup* colorGroup = new deqp::gles2::TestCaseGroup(m_context, "color", "Color buffer tests");
2169 addChild(colorGroup);
2170 addChildVariants<FboCases::MixTest> (colorGroup);
2171 addChildVariants<FboCases::MixNpotTest> (colorGroup);
2172 addChildVariants<FboCases::BlendTest> (colorGroup);
2173 addChildVariants<FboCases::BlendNpotTest> (colorGroup);
2174
2175 deqp::gles2::TestCaseGroup* depthGroup = new deqp::gles2::TestCaseGroup(m_context, "depth", "Depth bufer tests");
2176 addChild(depthGroup);
2177 addChildVariants<FboCases::IntersectingQuadsTest> (depthGroup);
2178 addChildVariants<FboCases::IntersectingQuadsNpotTest> (depthGroup);
2179
2180 deqp::gles2::TestCaseGroup* stencilGroup = new deqp::gles2::TestCaseGroup(m_context, "stencil", "Stencil buffer tests");
2181 addChild(stencilGroup);
2182 addChildVariants<FboCases::StencilTest> (stencilGroup);
2183 addChildVariants<FboCases::StencilNpotTest> (stencilGroup);
2184
2185 createChildGroup<FboCases::SharedColorbufferClearsTest> (this, "shared_colorbuffer_clear", "Shared colorbuffer clears");
2186 createChildGroup<FboCases::SharedColorbufferTest> (this, "shared_colorbuffer", "Shared colorbuffer tests");
2187 createChildGroup<FboCases::SharedDepthbufferTest> (this, "shared_depthbuffer", "Shared depthbuffer tests");
2188 createChildGroup<FboCases::ResizeTest> (this, "resize", "FBO resize tests");
2189
2190 createRecreateBuffersGroup<GL_COLOR_BUFFER_BIT> (this, "recreate_colorbuffer", "Recreate colorbuffer tests");
2191 createRecreateBuffersGroup<GL_DEPTH_BUFFER_BIT> (this, "recreate_depthbuffer", "Recreate depthbuffer tests");
2192 createRecreateBuffersGroup<GL_STENCIL_BUFFER_BIT> (this, "recreate_stencilbuffer", "Recreate stencilbuffer tests");
2193
2194 deqp::gles2::TestCaseGroup* texSubImageGroup = new deqp::gles2::TestCaseGroup(m_context, "texsubimage", "TexSubImage interop with FBO colorbuffer texture");
2195 addChild(texSubImageGroup);
2196 addChildVariants<FboCases::TexSubImageAfterRenderTest> (texSubImageGroup);
2197 addChildVariants<FboCases::TexSubImageBetweenRenderTest> (texSubImageGroup);
2198
2199 {
2200 tcu::TestCaseGroup* const repeatedClearGroup = new tcu::TestCaseGroup(m_testCtx, "repeated_clear", "Repeated FBO clears");
2201 addChild(repeatedClearGroup);
2202
2203 repeatedClearGroup->addChild(new FboCases::RepeatedClearCase(m_context, GL_RGB));
2204 repeatedClearGroup->addChild(new FboCases::RepeatedClearCase(m_context, GL_RGBA));
2205 }
2206 }
2207
2208 } // Functional
2209 } // gles2
2210 } // deqp
2211