1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.0 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief FBO colorbuffer tests.
22 *//*--------------------------------------------------------------------*/
23
24 #include "es3fFboColorbufferTests.hpp"
25 #include "es3fFboTestCase.hpp"
26 #include "es3fFboTestUtil.hpp"
27 #include "gluTextureUtil.hpp"
28 #include "gluContextInfo.hpp"
29 #include "tcuImageCompare.hpp"
30 #include "tcuRGBA.hpp"
31 #include "tcuTestLog.hpp"
32 #include "tcuTextureUtil.hpp"
33 #include "sglrContextUtil.hpp"
34 #include "deRandom.hpp"
35 #include "deString.h"
36 #include "glwEnums.hpp"
37
38 namespace deqp
39 {
40 namespace gles3
41 {
42 namespace Functional
43 {
44
45 using std::string;
46 using tcu::Vec2;
47 using tcu::Vec3;
48 using tcu::Vec4;
49 using tcu::IVec2;
50 using tcu::IVec3;
51 using tcu::IVec4;
52 using tcu::UVec4;
53 using tcu::TestLog;
54 using namespace FboTestUtil;
55
56 const tcu::RGBA MIN_THRESHOLD(12, 12, 12, 12);
57
58 template <int Size>
59 static tcu::Vector<float, Size> randomVector (de::Random& rnd, const tcu::Vector<float, Size>& minVal = tcu::Vector<float, Size>(0.0f), const tcu::Vector<float, Size>& maxVal = tcu::Vector<float, Size>(1.0f))
60 {
61 tcu::Vector<float, Size> res;
62 for (int ndx = 0; ndx < Size; ndx++)
63 res[ndx] = rnd.getFloat(minVal[ndx], maxVal[ndx]);
64 return res;
65 }
66
generateRandomColor(de::Random & random)67 static tcu::Vec4 generateRandomColor (de::Random& random)
68 {
69 tcu::Vec4 retVal;
70
71 for (int i = 0; i < 3; ++i)
72 retVal[i] = random.getFloat();
73 retVal[3] = 1.0f;
74
75 return retVal;
76 }
77
78 class FboColorbufferCase : public FboTestCase
79 {
80 public:
FboColorbufferCase(Context & context,const char * name,const char * desc,const deUint32 format)81 FboColorbufferCase (Context& context, const char* name, const char* desc, const deUint32 format)
82 : FboTestCase (context, name, desc)
83 , m_format (format)
84 {
85 }
86
compare(const tcu::Surface & reference,const tcu::Surface & result)87 bool compare (const tcu::Surface& reference, const tcu::Surface& result)
88 {
89 const tcu::RGBA threshold (tcu::max(getFormatThreshold(m_format), MIN_THRESHOLD));
90
91 m_testCtx.getLog() << TestLog::Message << "Comparing images, threshold: " << threshold << TestLog::EndMessage;
92
93 return tcu::bilinearCompare(m_testCtx.getLog(), "Result", "Image comparison result", reference.getAccess(), result.getAccess(), threshold, tcu::COMPARE_LOG_RESULT);
94 }
95
96 protected:
97 const deUint32 m_format;
98 };
99
100 class FboColorClearCase : public FboColorbufferCase
101 {
102 public:
FboColorClearCase(Context & context,const char * name,const char * desc,deUint32 format,int width,int height)103 FboColorClearCase (Context& context, const char* name, const char* desc, deUint32 format, int width, int height)
104 : FboColorbufferCase (context, name, desc, format)
105 , m_width (width)
106 , m_height (height)
107 {
108 }
109
110 protected:
preCheck(void)111 void preCheck (void)
112 {
113 checkFormatSupport(m_format);
114 }
115
render(tcu::Surface & dst)116 void render (tcu::Surface& dst)
117 {
118 tcu::TextureFormat fboFormat = glu::mapGLInternalFormat(m_format);
119 tcu::TextureChannelClass fmtClass = tcu::getTextureChannelClass(fboFormat.type);
120 tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(fboFormat);
121 de::Random rnd (17);
122 const int numClears = 16;
123 deUint32 fbo = 0;
124 deUint32 rbo = 0;
125
126 glGenFramebuffers(1, &fbo);
127 glGenRenderbuffers(1, &rbo);
128
129 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
130 glRenderbufferStorage(GL_RENDERBUFFER, m_format, m_width, m_height);
131 checkError();
132
133 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
134 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
135 checkError();
136 checkFramebufferStatus(GL_FRAMEBUFFER);
137
138 glViewport(0, 0, m_width, m_height);
139
140 // Initialize to transparent black.
141 switch (fmtClass)
142 {
143 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
144 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
145 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
146 glClearBufferfv(GL_COLOR, 0, Vec4(0.0f).getPtr());
147 break;
148
149 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
150 glClearBufferuiv(GL_COLOR, 0, UVec4(0).getPtr());
151 break;
152
153 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
154 glClearBufferiv(GL_COLOR, 0, IVec4(0).getPtr());
155 break;
156
157 default:
158 DE_ASSERT(DE_FALSE);
159 }
160
161 // Do random scissored clears.
162 glEnable(GL_SCISSOR_TEST);
163 for (int ndx = 0; ndx < numClears; ndx++)
164 {
165 int x = rnd.getInt(0, m_width - 1);
166 int y = rnd.getInt(0, m_height - 1);
167 int w = rnd.getInt(1, m_width - x);
168 int h = rnd.getInt(1, m_height - y);
169 Vec4 color = randomVector<4>(rnd, fmtInfo.valueMin, fmtInfo.valueMax);
170
171 glScissor(x, y, w, h);
172
173 switch (fmtClass)
174 {
175 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
176 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
177 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
178 glClearBufferfv(GL_COLOR, 0, color.getPtr());
179 break;
180
181 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
182 glClearBufferuiv(GL_COLOR, 0, color.cast<deUint32>().getPtr());
183 break;
184
185 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
186 glClearBufferiv(GL_COLOR, 0, color.cast<int>().getPtr());
187 break;
188
189 default:
190 DE_ASSERT(DE_FALSE);
191 }
192 }
193
194 // Read results from renderbuffer.
195 readPixels(dst, 0, 0, m_width, m_height, fboFormat, fmtInfo.lookupScale, fmtInfo.lookupBias);
196 checkError();
197 }
198
199 private:
200 const int m_width;
201 const int m_height;
202 };
203
204 class FboColorMultiTex2DCase : public FboColorbufferCase
205 {
206 public:
FboColorMultiTex2DCase(Context & context,const char * name,const char * description,deUint32 tex0Fmt,const IVec2 & tex0Size,deUint32 tex1Fmt,const IVec2 & tex1Size)207 FboColorMultiTex2DCase (Context& context, const char* name, const char* description, deUint32 tex0Fmt, const IVec2& tex0Size, deUint32 tex1Fmt, const IVec2& tex1Size)
208 : FboColorbufferCase (context, name, description, tex0Fmt)
209 , m_tex0Fmt (tex0Fmt)
210 , m_tex1Fmt (tex1Fmt)
211 , m_tex0Size (tex0Size)
212 , m_tex1Size (tex1Size)
213 {
214 }
215
216 protected:
preCheck(void)217 void preCheck (void)
218 {
219 checkFormatSupport(m_tex0Fmt);
220 checkFormatSupport(m_tex1Fmt);
221 }
222
render(tcu::Surface & dst)223 void render (tcu::Surface& dst)
224 {
225 tcu::TextureFormat texFmt0 = glu::mapGLInternalFormat(m_tex0Fmt);
226 tcu::TextureFormat texFmt1 = glu::mapGLInternalFormat(m_tex1Fmt);
227 tcu::TextureFormatInfo fmtInfo0 = tcu::getTextureFormatInfo(texFmt0);
228 tcu::TextureFormatInfo fmtInfo1 = tcu::getTextureFormatInfo(texFmt1);
229
230 Texture2DShader texToFbo0Shader (DataTypes() << glu::TYPE_SAMPLER_2D, getFragmentOutputType(texFmt0), fmtInfo0.valueMax-fmtInfo0.valueMin, fmtInfo0.valueMin);
231 Texture2DShader texToFbo1Shader (DataTypes() << glu::TYPE_SAMPLER_2D, getFragmentOutputType(texFmt1), fmtInfo1.valueMax-fmtInfo1.valueMin, fmtInfo1.valueMin);
232 Texture2DShader multiTexShader (DataTypes() << glu::getSampler2DType(texFmt0) << glu::getSampler2DType(texFmt1), glu::TYPE_FLOAT_VEC4);
233
234 deUint32 texToFbo0ShaderID = getCurrentContext()->createProgram(&texToFbo0Shader);
235 deUint32 texToFbo1ShaderID = getCurrentContext()->createProgram(&texToFbo1Shader);
236 deUint32 multiTexShaderID = getCurrentContext()->createProgram(&multiTexShader);
237
238 // Setup shaders
239 multiTexShader.setTexScaleBias(0, fmtInfo0.lookupScale * 0.5f, fmtInfo0.lookupBias * 0.5f);
240 multiTexShader.setTexScaleBias(1, fmtInfo1.lookupScale * 0.5f, fmtInfo1.lookupBias * 0.5f);
241 texToFbo0Shader.setUniforms(*getCurrentContext(), texToFbo0ShaderID);
242 texToFbo1Shader.setUniforms(*getCurrentContext(), texToFbo1ShaderID);
243 multiTexShader.setUniforms (*getCurrentContext(), multiTexShaderID);
244
245 // Framebuffers.
246 deUint32 fbo0, fbo1;
247 deUint32 tex0, tex1;
248
249 for (int ndx = 0; ndx < 2; ndx++)
250 {
251 glu::TransferFormat transferFmt = glu::getTransferFormat(ndx ? texFmt1 : texFmt0);
252 deUint32 format = ndx ? m_tex1Fmt : m_tex0Fmt;
253 bool isFilterable = glu::isGLInternalColorFormatFilterable(format);
254 const IVec2& size = ndx ? m_tex1Size : m_tex0Size;
255 deUint32& fbo = ndx ? fbo1 : fbo0;
256 deUint32& tex = ndx ? tex1 : tex0;
257
258 glGenFramebuffers(1, &fbo);
259 glGenTextures(1, &tex);
260
261 glBindTexture(GL_TEXTURE_2D, tex);
262 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
263 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
264 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, isFilterable ? GL_LINEAR : GL_NEAREST);
265 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, isFilterable ? GL_LINEAR : GL_NEAREST);
266 glTexImage2D(GL_TEXTURE_2D, 0, format, size.x(), size.y(), 0, transferFmt.format, transferFmt.dataType, DE_NULL);
267
268 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
269 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
270 checkError();
271 checkFramebufferStatus(GL_FRAMEBUFFER);
272 }
273
274 // Render textures to both framebuffers.
275 for (int ndx = 0; ndx < 2; ndx++)
276 {
277 const deUint32 format = GL_RGBA;
278 const deUint32 dataType = GL_UNSIGNED_BYTE;
279 const int texW = 128;
280 const int texH = 128;
281 deUint32 tmpTex = 0;
282 deUint32 fbo = ndx ? fbo1 : fbo0;
283 const IVec2& viewport = ndx ? m_tex1Size : m_tex0Size;
284 tcu::TextureLevel data (glu::mapGLTransferFormat(format, dataType), texW, texH, 1);
285
286 if (ndx == 0)
287 tcu::fillWithComponentGradients(data.getAccess(), Vec4(0.0f), Vec4(1.0f));
288 else
289 tcu::fillWithGrid(data.getAccess(), 8, Vec4(0.2f, 0.7f, 0.1f, 1.0f), Vec4(0.7f, 0.1f, 0.5f, 0.8f));
290
291 glGenTextures(1, &tmpTex);
292 glBindTexture(GL_TEXTURE_2D, tmpTex);
293 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
294 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
295 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
296 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
297 glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
298
299 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
300 glViewport(0, 0, viewport.x(), viewport.y());
301 sglr::drawQuad(*getCurrentContext(), ndx ? texToFbo1ShaderID : texToFbo0ShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
302 }
303
304 // Render to framebuffer.
305 glBindFramebuffer(GL_FRAMEBUFFER, 0);
306 glViewport(0, 0, getWidth(), getHeight());
307 glActiveTexture(GL_TEXTURE0);
308 glBindTexture(GL_TEXTURE_2D, tex0);
309 glActiveTexture(GL_TEXTURE1);
310 glBindTexture(GL_TEXTURE_2D, tex1);
311 sglr::drawQuad(*getCurrentContext(), multiTexShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
312
313 readPixels(dst, 0, 0, getWidth(), getHeight());
314 }
315
316 private:
317 deUint32 m_tex0Fmt;
318 deUint32 m_tex1Fmt;
319 IVec2 m_tex0Size;
320 IVec2 m_tex1Size;
321 };
322
323 class FboColorTexCubeCase : public FboColorbufferCase
324 {
325 public:
FboColorTexCubeCase(Context & context,const char * name,const char * description,deUint32 texFmt,const IVec2 & texSize)326 FboColorTexCubeCase (Context& context, const char* name, const char* description, deUint32 texFmt, const IVec2& texSize)
327 : FboColorbufferCase (context, name, description, texFmt)
328 , m_texSize (texSize)
329 {
330 }
331
332 protected:
preCheck(void)333 void preCheck (void)
334 {
335 checkFormatSupport(m_format);
336 }
337
render(tcu::Surface & dst)338 void render (tcu::Surface& dst)
339 {
340 static const deUint32 cubeGLFaces[] =
341 {
342 GL_TEXTURE_CUBE_MAP_POSITIVE_X,
343 GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
344 GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
345 GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
346 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
347 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
348 };
349
350 static const tcu::CubeFace cubeTexFaces[] =
351 {
352 tcu::CUBEFACE_POSITIVE_X,
353 tcu::CUBEFACE_POSITIVE_Y,
354 tcu::CUBEFACE_POSITIVE_Z,
355 tcu::CUBEFACE_NEGATIVE_X,
356 tcu::CUBEFACE_NEGATIVE_Y,
357 tcu::CUBEFACE_NEGATIVE_Z
358 };
359
360 de::Random rnd (deStringHash(getName()) ^ 0x9eef603d);
361 tcu::TextureFormat texFmt = glu::mapGLInternalFormat(m_format);
362 tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
363
364 Texture2DShader texToFboShader (DataTypes() << glu::TYPE_SAMPLER_2D, getFragmentOutputType(texFmt), fmtInfo.valueMax-fmtInfo.valueMin, fmtInfo.valueMin);
365 TextureCubeShader cubeTexShader (glu::getSamplerCubeType(texFmt), glu::TYPE_FLOAT_VEC4);
366
367 deUint32 texToFboShaderID = getCurrentContext()->createProgram(&texToFboShader);
368 deUint32 cubeTexShaderID = getCurrentContext()->createProgram(&cubeTexShader);
369
370 // Setup shaders
371 texToFboShader.setUniforms(*getCurrentContext(), texToFboShaderID);
372 cubeTexShader.setTexScaleBias(fmtInfo.lookupScale, fmtInfo.lookupBias);
373
374 // Framebuffers.
375 std::vector<deUint32> fbos;
376 deUint32 tex;
377
378 {
379 glu::TransferFormat transferFmt = glu::getTransferFormat(texFmt);
380 bool isFilterable = glu::isGLInternalColorFormatFilterable(m_format);
381 const IVec2& size = m_texSize;
382
383
384 glGenTextures(1, &tex);
385
386 glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
387 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
388 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
389 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, isFilterable ? GL_LINEAR : GL_NEAREST);
390 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, isFilterable ? GL_LINEAR : GL_NEAREST);
391
392 // Generate an image and FBO for each cube face
393 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cubeGLFaces); ndx++)
394 glTexImage2D(cubeGLFaces[ndx], 0, m_format, size.x(), size.y(), 0, transferFmt.format, transferFmt.dataType, DE_NULL);
395 checkError();
396
397 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cubeGLFaces); ndx++)
398 {
399 deUint32 layerFbo;
400
401 glGenFramebuffers(1, &layerFbo);
402 glBindFramebuffer(GL_FRAMEBUFFER, layerFbo);
403 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cubeGLFaces[ndx], tex, 0);
404 checkError();
405 checkFramebufferStatus(GL_FRAMEBUFFER);
406
407 fbos.push_back(layerFbo);
408 }
409 }
410
411 // Render test images to random cube faces
412 std::vector<int> order;
413
414 for (size_t n = 0; n < fbos.size(); n++)
415 order.push_back((int)n);
416 rnd.shuffle(order.begin(), order.end());
417
418 DE_ASSERT(order.size() >= 4);
419 for (int ndx = 0; ndx < 4; ndx++)
420 {
421 const int face = order[ndx];
422 const deUint32 format = GL_RGBA;
423 const deUint32 dataType = GL_UNSIGNED_BYTE;
424 const int texW = 128;
425 const int texH = 128;
426 deUint32 tmpTex = 0;
427 const deUint32 fbo = fbos[face];
428 const IVec2& viewport = m_texSize;
429 tcu::TextureLevel data (glu::mapGLTransferFormat(format, dataType), texW, texH, 1);
430
431 tcu::fillWithGrid(data.getAccess(), 8, generateRandomColor(rnd), Vec4(0.0f));
432
433 glGenTextures(1, &tmpTex);
434 glBindTexture(GL_TEXTURE_2D, tmpTex);
435 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
436 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
437 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
438 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
439 glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
440
441 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
442 glViewport(0, 0, viewport.x(), viewport.y());
443 sglr::drawQuad(*getCurrentContext(), texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
444 checkError();
445
446 // Render to framebuffer
447 {
448 const Vec3 p0 = Vec3(float(ndx % 2) - 1.0f, float(ndx / 2) - 1.0f, 0.0f);
449 const Vec3 p1 = p0 + Vec3(1.0f, 1.0f, 0.0f);
450
451 glBindFramebuffer(GL_FRAMEBUFFER, 0);
452 glViewport(0, 0, getWidth(), getHeight());
453
454 glActiveTexture(GL_TEXTURE0);
455 glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
456
457 cubeTexShader.setFace(cubeTexFaces[face]);
458 cubeTexShader.setUniforms(*getCurrentContext(), cubeTexShaderID);
459
460 sglr::drawQuad(*getCurrentContext(), cubeTexShaderID, p0, p1);
461 checkError();
462 }
463 }
464
465 readPixels(dst, 0, 0, getWidth(), getHeight());
466 }
467
468 private:
469 IVec2 m_texSize;
470 };
471
472 class FboColorTex2DArrayCase : public FboColorbufferCase
473 {
474 public:
FboColorTex2DArrayCase(Context & context,const char * name,const char * description,deUint32 texFmt,const IVec3 & texSize)475 FboColorTex2DArrayCase (Context& context, const char* name, const char* description, deUint32 texFmt, const IVec3& texSize)
476 : FboColorbufferCase (context, name, description, texFmt)
477 , m_texSize (texSize)
478 {
479 }
480
481 protected:
preCheck(void)482 void preCheck (void)
483 {
484 checkFormatSupport(m_format);
485 }
486
render(tcu::Surface & dst)487 void render (tcu::Surface& dst)
488 {
489 de::Random rnd (deStringHash(getName()) ^ 0xed607a89);
490 tcu::TextureFormat texFmt = glu::mapGLInternalFormat(m_format);
491 tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
492
493 Texture2DShader texToFboShader (DataTypes() << glu::TYPE_SAMPLER_2D, getFragmentOutputType(texFmt), fmtInfo.valueMax-fmtInfo.valueMin, fmtInfo.valueMin);
494 Texture2DArrayShader arrayTexShader (glu::getSampler2DArrayType(texFmt), glu::TYPE_FLOAT_VEC4);
495
496 deUint32 texToFboShaderID = getCurrentContext()->createProgram(&texToFboShader);
497 deUint32 arrayTexShaderID = getCurrentContext()->createProgram(&arrayTexShader);
498
499 // Setup textures
500 texToFboShader.setUniforms(*getCurrentContext(), texToFboShaderID);
501 arrayTexShader.setTexScaleBias(fmtInfo.lookupScale, fmtInfo.lookupBias);
502
503 // Framebuffers.
504 std::vector<deUint32> fbos;
505 deUint32 tex;
506
507 {
508 glu::TransferFormat transferFmt = glu::getTransferFormat(texFmt);
509 bool isFilterable = glu::isGLInternalColorFormatFilterable(m_format);
510 const IVec3& size = m_texSize;
511
512
513 glGenTextures(1, &tex);
514
515 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
516 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
517 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
518 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
519 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, isFilterable ? GL_LINEAR : GL_NEAREST);
520 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, isFilterable ? GL_LINEAR : GL_NEAREST);
521 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, m_format, size.x(), size.y(), size.z(), 0, transferFmt.format, transferFmt.dataType, DE_NULL);
522
523 // Generate an FBO for each layer
524 for (int ndx = 0; ndx < m_texSize.z(); ndx++)
525 {
526 deUint32 layerFbo;
527
528 glGenFramebuffers(1, &layerFbo);
529 glBindFramebuffer(GL_FRAMEBUFFER, layerFbo);
530 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, ndx);
531 checkError();
532 checkFramebufferStatus(GL_FRAMEBUFFER);
533
534 fbos.push_back(layerFbo);
535 }
536 }
537
538 // Render test images to random texture layers
539 std::vector<int> order;
540
541 for (size_t n = 0; n < fbos.size(); n++)
542 order.push_back((int)n);
543 rnd.shuffle(order.begin(), order.end());
544
545 for (size_t ndx = 0; ndx < order.size(); ndx++)
546 {
547 const int layer = order[ndx];
548 const deUint32 format = GL_RGBA;
549 const deUint32 dataType = GL_UNSIGNED_BYTE;
550 const int texW = 128;
551 const int texH = 128;
552 deUint32 tmpTex = 0;
553 const deUint32 fbo = fbos[layer];
554 const IVec3& viewport = m_texSize;
555 tcu::TextureLevel data (glu::mapGLTransferFormat(format, dataType), texW, texH, 1);
556
557 tcu::fillWithGrid(data.getAccess(), 8, generateRandomColor(rnd), Vec4(0.0f));
558
559 glGenTextures(1, &tmpTex);
560 glBindTexture(GL_TEXTURE_2D, tmpTex);
561 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
562 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
563 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
564 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
565 glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
566
567 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
568 glViewport(0, 0, viewport.x(), viewport.y());
569 sglr::drawQuad(*getCurrentContext(), texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
570 checkError();
571
572 // Render to framebuffer
573 {
574 const Vec3 p0 = Vec3(float(ndx % 2) - 1.0f, float(ndx / 2) - 1.0f, 0.0f);
575 const Vec3 p1 = p0 + Vec3(1.0f, 1.0f, 0.0f);
576
577 glBindFramebuffer(GL_FRAMEBUFFER, 0);
578 glViewport(0, 0, getWidth(), getHeight());
579
580 glActiveTexture(GL_TEXTURE0);
581 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
582
583 arrayTexShader.setLayer(layer);
584 arrayTexShader.setUniforms(*getCurrentContext(), arrayTexShaderID);
585
586 sglr::drawQuad(*getCurrentContext(), arrayTexShaderID, p0, p1);
587 checkError();
588 }
589 }
590
591 readPixels(dst, 0, 0, getWidth(), getHeight());
592 }
593
594 private:
595 IVec3 m_texSize;
596 };
597
598 class FboColorTex3DCase : public FboColorbufferCase
599 {
600 public:
FboColorTex3DCase(Context & context,const char * name,const char * description,deUint32 texFmt,const IVec3 & texSize)601 FboColorTex3DCase (Context& context, const char* name, const char* description, deUint32 texFmt, const IVec3& texSize)
602 : FboColorbufferCase (context, name, description, texFmt)
603 , m_texSize (texSize)
604 {
605 }
606
607 protected:
preCheck(void)608 void preCheck (void)
609 {
610 checkFormatSupport(m_format);
611 }
612
render(tcu::Surface & dst)613 void render (tcu::Surface& dst)
614 {
615 de::Random rnd (deStringHash(getName()) ^ 0x74d947b2);
616 tcu::TextureFormat texFmt = glu::mapGLInternalFormat(m_format);
617 tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
618
619 Texture2DShader texToFboShader (DataTypes() << glu::TYPE_SAMPLER_2D, getFragmentOutputType(texFmt), fmtInfo.valueMax-fmtInfo.valueMin, fmtInfo.valueMin);
620 Texture3DShader tdTexShader (glu::getSampler3DType(texFmt), glu::TYPE_FLOAT_VEC4);
621
622 deUint32 texToFboShaderID= getCurrentContext()->createProgram(&texToFboShader);
623 deUint32 tdTexShaderID = getCurrentContext()->createProgram(&tdTexShader);
624
625 // Setup shaders
626 texToFboShader.setUniforms(*getCurrentContext(), texToFboShaderID);
627 tdTexShader.setTexScaleBias(fmtInfo.lookupScale, fmtInfo.lookupBias);
628
629 // Framebuffers.
630 std::vector<deUint32> fbos;
631 deUint32 tex;
632
633 {
634 glu::TransferFormat transferFmt = glu::getTransferFormat(texFmt);
635 const IVec3& size = m_texSize;
636
637 glGenTextures(1, &tex);
638
639 glBindTexture(GL_TEXTURE_3D, tex);
640 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
641 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
642 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
643 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
644 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
645 glTexImage3D(GL_TEXTURE_3D, 0, m_format, size.x(), size.y(), size.z(), 0, transferFmt.format, transferFmt.dataType, DE_NULL);
646
647 // Generate an FBO for each layer
648 for (int ndx = 0; ndx < m_texSize.z(); ndx++)
649 {
650 deUint32 layerFbo;
651
652 glGenFramebuffers(1, &layerFbo);
653 glBindFramebuffer(GL_FRAMEBUFFER, layerFbo);
654 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, ndx);
655 checkError();
656 checkFramebufferStatus(GL_FRAMEBUFFER);
657
658 fbos.push_back(layerFbo);
659 }
660 }
661
662 // Render test images to random texture layers
663 std::vector<int> order;
664
665 for (size_t n = 0; n < fbos.size(); n++)
666 order.push_back((int)n);
667 rnd.shuffle(order.begin(), order.end());
668
669 for (size_t ndx = 0; ndx < order.size(); ndx++)
670 {
671 const int layer = order[ndx];
672 const deUint32 format = GL_RGBA;
673 const deUint32 dataType = GL_UNSIGNED_BYTE;
674 const int texW = 128;
675 const int texH = 128;
676 deUint32 tmpTex = 0;
677 const deUint32 fbo = fbos[layer];
678 const IVec3& viewport = m_texSize;
679 tcu::TextureLevel data (glu::mapGLTransferFormat(format, dataType), texW, texH, 1);
680
681 tcu::fillWithGrid(data.getAccess(), 8, generateRandomColor(rnd), Vec4(0.0f));
682
683 glGenTextures(1, &tmpTex);
684 glBindTexture(GL_TEXTURE_2D, tmpTex);
685 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
686 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
687 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
688 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
689 glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
690
691 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
692 glViewport(0, 0, viewport.x(), viewport.y());
693 sglr::drawQuad(*getCurrentContext() , texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
694 checkError();
695
696 // Render to framebuffer
697 {
698 const Vec3 p0 = Vec3(float(ndx % 2) - 1.0f, float(ndx / 2) - 1.0f, 0.0f);
699 const Vec3 p1 = p0 + Vec3(1.0f, 1.0f, 0.0f);
700
701 glBindFramebuffer(GL_FRAMEBUFFER, 0);
702 glViewport(0, 0, getWidth(), getHeight());
703
704 glActiveTexture(GL_TEXTURE0);
705 glBindTexture(GL_TEXTURE_3D, tex);
706
707 tdTexShader.setDepth(float(layer) / float(m_texSize.z()-1));
708 tdTexShader.setUniforms(*getCurrentContext(), tdTexShaderID);
709
710 sglr::drawQuad(*getCurrentContext(), tdTexShaderID, p0, p1);
711 checkError();
712 }
713 }
714
715 readPixels(dst, 0, 0, getWidth(), getHeight());
716 }
717
718 private:
719 IVec3 m_texSize;
720 };
721
722 class FboBlendCase : public FboColorbufferCase
723 {
724 public:
FboBlendCase(Context & context,const char * name,const char * desc,deUint32 format,IVec2 size,deUint32 funcRGB,deUint32 funcAlpha,deUint32 srcRGB,deUint32 dstRGB,deUint32 srcAlpha,deUint32 dstAlpha)725 FboBlendCase (Context& context, const char* name, const char* desc, deUint32 format, IVec2 size, deUint32 funcRGB, deUint32 funcAlpha, deUint32 srcRGB, deUint32 dstRGB, deUint32 srcAlpha, deUint32 dstAlpha)
726 : FboColorbufferCase (context, name, desc, format)
727 , m_size (size)
728 , m_funcRGB (funcRGB)
729 , m_funcAlpha (funcAlpha)
730 , m_srcRGB (srcRGB)
731 , m_dstRGB (dstRGB)
732 , m_srcAlpha (srcAlpha)
733 , m_dstAlpha (dstAlpha)
734 {
735 }
736
737 protected:
preCheck(void)738 void preCheck (void)
739 {
740 checkFormatSupport(m_format);
741 }
742
render(tcu::Surface & dst)743 void render (tcu::Surface& dst)
744 {
745 // \note Assumes floating-point or fixed-point format.
746 tcu::TextureFormat fboFmt = glu::mapGLInternalFormat(m_format);
747 Texture2DShader texShader (DataTypes() << glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC4);
748 GradientShader gradShader (glu::TYPE_FLOAT_VEC4);
749 deUint32 texShaderID = getCurrentContext()->createProgram(&texShader);
750 deUint32 gradShaderID = getCurrentContext()->createProgram(&gradShader);
751 deUint32 fbo = 0;
752 deUint32 rbo = 0;
753
754 // Setup shaders
755 texShader.setUniforms (*getCurrentContext(), texShaderID);
756 gradShader.setGradient(*getCurrentContext(), gradShaderID, tcu::Vec4(0.0f), tcu::Vec4(1.0f));
757
758 glGenFramebuffers(1, &fbo);
759 glGenRenderbuffers(1, &rbo);
760
761 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
762 glRenderbufferStorage(GL_RENDERBUFFER, m_format, m_size.x(), m_size.y());
763 checkError();
764
765 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
766 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
767 checkError();
768 checkFramebufferStatus(GL_FRAMEBUFFER);
769
770 glViewport(0, 0, m_size.x(), m_size.y());
771
772 // Fill framebuffer with grid pattern.
773 {
774 const deUint32 format = GL_RGBA;
775 const deUint32 dataType = GL_UNSIGNED_BYTE;
776 const int texW = 128;
777 const int texH = 128;
778 deUint32 gridTex = 0;
779 tcu::TextureLevel data (glu::mapGLTransferFormat(format, dataType), texW, texH, 1);
780
781 tcu::fillWithGrid(data.getAccess(), 8, Vec4(0.2f, 0.7f, 0.1f, 1.0f), Vec4(0.7f, 0.1f, 0.5f, 0.8f));
782
783 glGenTextures(1, &gridTex);
784 glBindTexture(GL_TEXTURE_2D, gridTex);
785 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
786 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
787 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
788 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
789 glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
790
791 sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
792 }
793
794 // Setup blend.
795 glEnable(GL_BLEND);
796 glBlendEquationSeparate(m_funcRGB, m_funcAlpha);
797 glBlendFuncSeparate(m_srcRGB, m_dstRGB, m_srcAlpha, m_dstAlpha);
798
799 // Render gradient with blend.
800 sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
801
802 readPixels(dst, 0, 0, m_size.x(), m_size.y(), fboFmt, Vec4(1.0f), Vec4(0.0f));
803 }
804
805 private:
806 IVec2 m_size;
807 deUint32 m_funcRGB;
808 deUint32 m_funcAlpha;
809 deUint32 m_srcRGB;
810 deUint32 m_dstRGB;
811 deUint32 m_srcAlpha;
812 deUint32 m_dstAlpha;
813 };
814
815 class FboRepeatedClearSampleTex2DCase : public FboColorbufferCase
816 {
817 public:
FboRepeatedClearSampleTex2DCase(Context & context,const char * name,const char * desc,deUint32 format)818 FboRepeatedClearSampleTex2DCase (Context& context, const char* name, const char* desc, deUint32 format)
819 : FboColorbufferCase(context, name, desc, format)
820 {
821 }
822
823 protected:
preCheck(void)824 void preCheck (void)
825 {
826 checkFormatSupport(m_format);
827 }
828
render(tcu::Surface & dst)829 void render (tcu::Surface& dst)
830 {
831 const tcu::TextureFormat fboFormat = glu::mapGLInternalFormat(m_format);
832 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(fboFormat);
833 const int numRowsCols = 4;
834 const int cellSize = 16;
835 const int fboSizes[] = { cellSize, cellSize*numRowsCols };
836
837 Texture2DShader fboBlitShader (DataTypes() << glu::getSampler2DType(fboFormat), getFragmentOutputType(fboFormat), Vec4(1.0f), Vec4(0.0f));
838 const deUint32 fboBlitShaderID = getCurrentContext()->createProgram(&fboBlitShader);
839
840 de::Random rnd (18169662);
841 deUint32 fbos[] = { 0, 0 };
842 deUint32 textures[] = { 0, 0 };
843
844 glGenFramebuffers(2, &fbos[0]);
845 glGenTextures(2, &textures[0]);
846
847 for (int fboNdx = 0; fboNdx < DE_LENGTH_OF_ARRAY(fbos); fboNdx++)
848 {
849 glBindTexture(GL_TEXTURE_2D, textures[fboNdx]);
850 glTexStorage2D(GL_TEXTURE_2D, 1, m_format, fboSizes[fboNdx], fboSizes[fboNdx]);
851 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
852 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
853 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
854 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
855 checkError();
856
857 glBindFramebuffer(GL_FRAMEBUFFER, fbos[fboNdx]);
858 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[fboNdx], 0);
859 checkError();
860 checkFramebufferStatus(GL_FRAMEBUFFER);
861 }
862
863 // larger fbo bound -- clear to transparent black
864 clearColorBuffer(fboFormat, Vec4(0.0f));
865
866 fboBlitShader.setUniforms(*getCurrentContext(), fboBlitShaderID);
867 glBindTexture(GL_TEXTURE_2D, textures[0]);
868
869 for (int cellY = 0; cellY < numRowsCols; cellY++)
870 for (int cellX = 0; cellX < numRowsCols; cellX++)
871 {
872 const Vec4 color = randomVector<4>(rnd, fmtInfo.valueMin, fmtInfo.valueMax);
873
874 glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]);
875 clearColorBuffer(fboFormat, color);
876
877 glBindFramebuffer(GL_FRAMEBUFFER, fbos[1]);
878 glViewport(cellX*cellSize, cellY*cellSize, cellSize, cellSize);
879 sglr::drawQuad(*getCurrentContext(), fboBlitShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
880 }
881
882 readPixels(dst, 0, 0, fboSizes[1], fboSizes[1], fboFormat, fmtInfo.lookupScale, fmtInfo.lookupBias);
883 checkError();
884 }
885 };
886
887 class FboRepeatedClearBlitTex2DCase : public FboColorbufferCase
888 {
889 public:
FboRepeatedClearBlitTex2DCase(Context & context,const char * name,const char * desc,deUint32 format)890 FboRepeatedClearBlitTex2DCase (Context& context, const char* name, const char* desc, deUint32 format)
891 : FboColorbufferCase(context, name, desc, format)
892 {
893 }
894
895 protected:
preCheck(void)896 void preCheck (void)
897 {
898 checkFormatSupport(m_format);
899 }
900
render(tcu::Surface & dst)901 void render (tcu::Surface& dst)
902 {
903 const tcu::TextureFormat fboFormat = glu::mapGLInternalFormat(m_format);
904 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(fboFormat);
905 const int numRowsCols = 4;
906 const int cellSize = 16;
907 const int fboSizes[] = { cellSize, cellSize*numRowsCols };
908
909 de::Random rnd (18169662);
910 deUint32 fbos[] = { 0, 0 };
911 deUint32 textures[] = { 0, 0 };
912
913 glGenFramebuffers(2, &fbos[0]);
914 glGenTextures(2, &textures[0]);
915
916 for (int fboNdx = 0; fboNdx < DE_LENGTH_OF_ARRAY(fbos); fboNdx++)
917 {
918 glBindTexture(GL_TEXTURE_2D, textures[fboNdx]);
919 glTexStorage2D(GL_TEXTURE_2D, 1, m_format, fboSizes[fboNdx], fboSizes[fboNdx]);
920 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
921 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
922 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
923 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
924 checkError();
925
926 glBindFramebuffer(GL_FRAMEBUFFER, fbos[fboNdx]);
927 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[fboNdx], 0);
928 checkError();
929 checkFramebufferStatus(GL_FRAMEBUFFER);
930 }
931
932 // larger fbo bound -- clear to transparent black
933 clearColorBuffer(fboFormat, Vec4(0.0f));
934
935 for (int cellY = 0; cellY < numRowsCols; cellY++)
936 for (int cellX = 0; cellX < numRowsCols; cellX++)
937 {
938 const Vec4 color = randomVector<4>(rnd, fmtInfo.valueMin, fmtInfo.valueMax);
939
940 glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]);
941 clearColorBuffer(fboFormat, color);
942
943 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]);
944 glBlitFramebuffer(0, 0, cellSize, cellSize, cellX*cellSize, cellY*cellSize, (cellX+1)*cellSize, (cellY+1)*cellSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
945 }
946
947 glBindFramebuffer(GL_FRAMEBUFFER, fbos[1]);
948 readPixels(dst, 0, 0, fboSizes[1], fboSizes[1], fboFormat, fmtInfo.lookupScale, fmtInfo.lookupBias);
949 checkError();
950 }
951 };
952
953 class FboRepeatedClearBlitRboCase : public FboColorbufferCase
954 {
955 public:
FboRepeatedClearBlitRboCase(Context & context,const char * name,const char * desc,deUint32 format)956 FboRepeatedClearBlitRboCase (Context& context, const char* name, const char* desc, deUint32 format)
957 : FboColorbufferCase(context, name, desc, format)
958 {
959 }
960
961 protected:
preCheck(void)962 void preCheck (void)
963 {
964 checkFormatSupport(m_format);
965 }
966
render(tcu::Surface & dst)967 void render (tcu::Surface& dst)
968 {
969 const tcu::TextureFormat fboFormat = glu::mapGLInternalFormat(m_format);
970 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(fboFormat);
971 const int numRowsCols = 4;
972 const int cellSize = 16;
973 const int fboSizes[] = { cellSize, cellSize*numRowsCols };
974
975 de::Random rnd (18169662);
976 deUint32 fbos[] = { 0, 0 };
977 deUint32 rbos[] = { 0, 0 };
978
979 glGenFramebuffers(2, &fbos[0]);
980 glGenRenderbuffers(2, &rbos[0]);
981
982 for (int fboNdx = 0; fboNdx < DE_LENGTH_OF_ARRAY(fbos); fboNdx++)
983 {
984 glBindRenderbuffer(GL_RENDERBUFFER, rbos[fboNdx]);
985 glRenderbufferStorage(GL_RENDERBUFFER, m_format, fboSizes[fboNdx], fboSizes[fboNdx]);
986 checkError();
987
988 glBindFramebuffer(GL_FRAMEBUFFER, fbos[fboNdx]);
989 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbos[fboNdx]);
990 checkError();
991 checkFramebufferStatus(GL_FRAMEBUFFER);
992 }
993
994 // larger fbo bound -- clear to transparent black
995 clearColorBuffer(fboFormat, Vec4(0.0f));
996
997 for (int cellY = 0; cellY < numRowsCols; cellY++)
998 for (int cellX = 0; cellX < numRowsCols; cellX++)
999 {
1000 const Vec4 color = randomVector<4>(rnd, fmtInfo.valueMin, fmtInfo.valueMax);
1001
1002 glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]);
1003 clearColorBuffer(fboFormat, color);
1004
1005 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]);
1006 glBlitFramebuffer(0, 0, cellSize, cellSize, cellX*cellSize, cellY*cellSize, (cellX+1)*cellSize, (cellY+1)*cellSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1007 }
1008
1009 glBindFramebuffer(GL_FRAMEBUFFER, fbos[1]);
1010 readPixels(dst, 0, 0, fboSizes[1], fboSizes[1], fboFormat, fmtInfo.lookupScale, fmtInfo.lookupBias);
1011 checkError();
1012 }
1013 };
1014
FboColorTests(Context & context)1015 FboColorTests::FboColorTests (Context& context)
1016 : TestCaseGroup(context, "color", "Colorbuffer tests")
1017 {
1018 }
1019
~FboColorTests(void)1020 FboColorTests::~FboColorTests (void)
1021 {
1022 }
1023
init(void)1024 void FboColorTests::init (void)
1025 {
1026 static const deUint32 colorFormats[] =
1027 {
1028 // RGBA formats
1029 GL_RGBA32I,
1030 GL_RGBA32UI,
1031 GL_RGBA16I,
1032 GL_RGBA16UI,
1033 GL_RGBA8,
1034 GL_RGBA8I,
1035 GL_RGBA8UI,
1036 GL_SRGB8_ALPHA8,
1037 GL_RGB10_A2,
1038 GL_RGB10_A2UI,
1039 GL_RGBA4,
1040 GL_RGB5_A1,
1041
1042 // RGB formats
1043 GL_RGB8,
1044 GL_RGB565,
1045
1046 // RG formats
1047 GL_RG32I,
1048 GL_RG32UI,
1049 GL_RG16I,
1050 GL_RG16UI,
1051 GL_RG8,
1052 GL_RG8I,
1053 GL_RG8UI,
1054
1055 // R formats
1056 GL_R32I,
1057 GL_R32UI,
1058 GL_R16I,
1059 GL_R16UI,
1060 GL_R8,
1061 GL_R8I,
1062 GL_R8UI,
1063
1064 // GL_EXT_color_buffer_float
1065 GL_RGBA32F,
1066 GL_RGBA16F,
1067 GL_R11F_G11F_B10F,
1068 GL_RG32F,
1069 GL_RG16F,
1070 GL_R32F,
1071 GL_R16F,
1072
1073 // GL_EXT_color_buffer_half_float
1074 GL_RGB16F
1075 };
1076
1077 // .clear
1078 {
1079 tcu::TestCaseGroup* clearGroup = new tcu::TestCaseGroup(m_testCtx, "clear", "Color clears");
1080 addChild(clearGroup);
1081
1082 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(colorFormats); ndx++)
1083 clearGroup->addChild(new FboColorClearCase(m_context, getFormatName(colorFormats[ndx]), "", colorFormats[ndx], 129, 117));
1084 }
1085
1086 // .tex2d
1087 {
1088 tcu::TestCaseGroup* tex2DGroup = new tcu::TestCaseGroup(m_testCtx, "tex2d", "Texture 2D tests");
1089 addChild(tex2DGroup);
1090
1091 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
1092 tex2DGroup->addChild(new FboColorMultiTex2DCase(m_context, getFormatName(colorFormats[fmtNdx]), "",
1093 colorFormats[fmtNdx], IVec2(129, 117),
1094 colorFormats[fmtNdx], IVec2(99, 128)));
1095 }
1096
1097 // .texcube
1098 {
1099 tcu::TestCaseGroup* texCubeGroup = new tcu::TestCaseGroup(m_testCtx, "texcube", "Texture cube map tests");
1100 addChild(texCubeGroup);
1101
1102 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
1103 texCubeGroup->addChild(new FboColorTexCubeCase(m_context, getFormatName(colorFormats[fmtNdx]), "",
1104 colorFormats[fmtNdx], IVec2(128, 128)));
1105 }
1106
1107 // .tex2darray
1108 {
1109 tcu::TestCaseGroup* tex2DArrayGroup = new tcu::TestCaseGroup(m_testCtx, "tex2darray", "Texture 2D array tests");
1110 addChild(tex2DArrayGroup);
1111
1112 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
1113 tex2DArrayGroup->addChild(new FboColorTex2DArrayCase(m_context, getFormatName(colorFormats[fmtNdx]), "",
1114 colorFormats[fmtNdx], IVec3(128, 128, 5)));
1115 }
1116
1117 // .tex3d
1118 {
1119 tcu::TestCaseGroup* tex3DGroup = new tcu::TestCaseGroup(m_testCtx, "tex3d", "Texture 3D tests");
1120 addChild(tex3DGroup);
1121
1122 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
1123 tex3DGroup->addChild(new FboColorTex3DCase(m_context, getFormatName(colorFormats[fmtNdx]), "",
1124 colorFormats[fmtNdx], IVec3(128, 128, 5)));
1125 }
1126
1127 // .blend
1128 {
1129 tcu::TestCaseGroup* blendGroup = new tcu::TestCaseGroup(m_testCtx, "blend", "Blending tests");
1130 addChild(blendGroup);
1131
1132 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
1133 {
1134 deUint32 format = colorFormats[fmtNdx];
1135 tcu::TextureFormat texFmt = glu::mapGLInternalFormat(format);
1136 tcu::TextureChannelClass fmtClass = tcu::getTextureChannelClass(texFmt.type);
1137 string fmtName = getFormatName(format);
1138
1139 if (texFmt.type == tcu::TextureFormat::FLOAT ||
1140 fmtClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER ||
1141 fmtClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
1142 continue; // Blending is not supported.
1143
1144 blendGroup->addChild(new FboBlendCase(m_context, (fmtName + "_src_over").c_str(), "", format, IVec2(127, 111), GL_FUNC_ADD, GL_FUNC_ADD, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE));
1145 }
1146 }
1147
1148 // .repeated_clear
1149 {
1150 tcu::TestCaseGroup* const repeatedClearGroup = new tcu::TestCaseGroup(m_testCtx, "repeated_clear", "Repeated clears and blits");
1151 addChild(repeatedClearGroup);
1152
1153 // .sample.tex2d
1154 {
1155 tcu::TestCaseGroup* const sampleGroup = new tcu::TestCaseGroup(m_testCtx, "sample", "Read by sampling");
1156 repeatedClearGroup->addChild(sampleGroup);
1157
1158 tcu::TestCaseGroup* const tex2DGroup = new tcu::TestCaseGroup(m_testCtx, "tex2d", "2D Texture");
1159 sampleGroup->addChild(tex2DGroup);
1160
1161 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
1162 tex2DGroup->addChild(new FboRepeatedClearSampleTex2DCase(m_context, getFormatName(colorFormats[fmtNdx]),
1163 "", colorFormats[fmtNdx]));
1164 }
1165
1166 // .blit
1167 {
1168 tcu::TestCaseGroup* const blitGroup = new tcu::TestCaseGroup(m_testCtx, "blit", "Blitted");
1169 repeatedClearGroup->addChild(blitGroup);
1170
1171 // .tex2d
1172 {
1173 tcu::TestCaseGroup* const tex2DGroup = new tcu::TestCaseGroup(m_testCtx, "tex2d", "2D Texture");
1174 blitGroup->addChild(tex2DGroup);
1175
1176 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
1177 tex2DGroup->addChild(new FboRepeatedClearBlitTex2DCase(m_context, getFormatName(colorFormats[fmtNdx]),
1178 "", colorFormats[fmtNdx]));
1179 }
1180
1181 // .rbo
1182 {
1183 tcu::TestCaseGroup* const rboGroup = new tcu::TestCaseGroup(m_testCtx, "rbo", "Renderbuffer");
1184 blitGroup->addChild(rboGroup);
1185
1186 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
1187 rboGroup->addChild(new FboRepeatedClearBlitRboCase(m_context, getFormatName(colorFormats[fmtNdx]),
1188 "", colorFormats[fmtNdx]));
1189 }
1190 }
1191 }
1192 }
1193
1194 } // Functional
1195 } // gles3
1196 } // deqp
1197