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