1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.1 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 "es31fFboColorbufferTests.hpp"
25 #include "es31fFboTestCase.hpp"
26 #include "es31fFboTestUtil.hpp"
27
28 #include "gluTextureUtil.hpp"
29 #include "gluContextInfo.hpp"
30
31 #include "tcuCommandLine.hpp"
32 #include "tcuImageCompare.hpp"
33 #include "tcuRGBA.hpp"
34 #include "tcuTestLog.hpp"
35 #include "tcuTextureUtil.hpp"
36
37 #include "sglrContextUtil.hpp"
38
39 #include "deRandom.hpp"
40 #include "deString.h"
41
42 #include "glwEnums.hpp"
43
44 namespace deqp
45 {
46 namespace gles31
47 {
48 namespace Functional
49 {
50
51 using std::string;
52 using tcu::Vec2;
53 using tcu::Vec3;
54 using tcu::Vec4;
55 using tcu::IVec2;
56 using tcu::IVec3;
57 using tcu::IVec4;
58 using tcu::UVec4;
59 using tcu::TestLog;
60 using namespace FboTestUtil;
61
62 const tcu::RGBA MIN_THRESHOLD(12, 12, 12, 12);
63
generateRandomColor(de::Random & random)64 static tcu::Vec4 generateRandomColor (de::Random& random)
65 {
66 tcu::Vec4 retVal;
67
68 retVal[0] = random.getFloat();
69 retVal[1] = random.getFloat();
70 retVal[2] = random.getFloat();
71 retVal[3] = 1.0f;
72
73 return retVal;
74 }
75
getCubeFaceFromNdx(int ndx)76 static tcu::CubeFace getCubeFaceFromNdx (int ndx)
77 {
78 switch (ndx)
79 {
80 case 0: return tcu::CUBEFACE_POSITIVE_X;
81 case 1: return tcu::CUBEFACE_NEGATIVE_X;
82 case 2: return tcu::CUBEFACE_POSITIVE_Y;
83 case 3: return tcu::CUBEFACE_NEGATIVE_Y;
84 case 4: return tcu::CUBEFACE_POSITIVE_Z;
85 case 5: return tcu::CUBEFACE_NEGATIVE_Z;
86 default:
87 DE_ASSERT(false);
88 return tcu::CUBEFACE_LAST;
89 }
90 }
91
92 class FboColorbufferCase : public FboTestCase
93 {
94 public:
FboColorbufferCase(Context & context,const char * name,const char * desc,const deUint32 format)95 FboColorbufferCase (Context& context, const char* name, const char* desc, const deUint32 format)
96 : FboTestCase (context, name, desc)
97 , m_format (format)
98 {
99 }
100
compare(const tcu::Surface & reference,const tcu::Surface & result)101 bool compare (const tcu::Surface& reference, const tcu::Surface& result)
102 {
103 const tcu::RGBA threshold (tcu::max(getFormatThreshold(m_format), MIN_THRESHOLD));
104
105 m_testCtx.getLog() << TestLog::Message << "Comparing images, threshold: " << threshold << TestLog::EndMessage;
106
107 return tcu::bilinearCompare(m_testCtx.getLog(), "Result", "Image comparison result", reference.getAccess(), result.getAccess(), threshold, tcu::COMPARE_LOG_RESULT);
108 }
109
110 protected:
111 const deUint32 m_format;
112 };
113
114 class FboColorTexCubeArrayCase : public FboColorbufferCase
115 {
116 public:
FboColorTexCubeArrayCase(Context & context,const char * name,const char * description,deUint32 texFmt,const IVec3 & texSize)117 FboColorTexCubeArrayCase (Context& context, const char* name, const char* description, deUint32 texFmt, const IVec3& texSize)
118 : FboColorbufferCase (context, name, description, texFmt)
119 , m_texSize (texSize)
120 {
121 DE_ASSERT(texSize.z() % 6 == 0);
122 }
123
124 protected:
preCheck(void)125 void preCheck (void)
126 {
127 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_cube_map_array"))
128 throw tcu::NotSupportedError("GL_EXT_texture_cube_map_array not supported");
129
130 checkFormatSupport(m_format);
131 }
132
render(tcu::Surface & dst)133 void render (tcu::Surface& dst)
134 {
135 TestLog& log = m_testCtx.getLog();
136 de::Random rnd (deStringHash(getName()) ^ 0xed607a89 ^ m_testCtx.getCommandLine().getBaseSeed());
137 tcu::TextureFormat texFmt = glu::mapGLInternalFormat(m_format);
138 tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
139
140 Texture2DShader texToFboShader (DataTypes() << glu::TYPE_SAMPLER_2D, getFragmentOutputType(texFmt), fmtInfo.valueMax-fmtInfo.valueMin, fmtInfo.valueMin);
141 TextureCubeArrayShader arrayTexShader (glu::getSamplerCubeArrayType(texFmt), glu::TYPE_FLOAT_VEC4);
142
143 deUint32 texToFboShaderID = getCurrentContext()->createProgram(&texToFboShader);
144 deUint32 arrayTexShaderID = getCurrentContext()->createProgram(&arrayTexShader);
145
146 // Setup textures
147 texToFboShader.setUniforms(*getCurrentContext(), texToFboShaderID);
148 arrayTexShader.setTexScaleBias(fmtInfo.lookupScale, fmtInfo.lookupBias);
149
150 // Framebuffers.
151 std::vector<deUint32> fbos;
152 deUint32 tex;
153
154 {
155 glu::TransferFormat transferFmt = glu::getTransferFormat(texFmt);
156 bool isFilterable = glu::isGLInternalColorFormatFilterable(m_format);
157 const IVec3& size = m_texSize;
158
159 log << TestLog::Message
160 << "Creating a cube map array texture ("
161 << size.x() << "x" << size.y()
162 << ", depth: "
163 << size.z() << ")"
164 << TestLog::EndMessage;
165
166 glGenTextures(1, &tex);
167
168 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, tex);
169 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
170 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
171 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
172 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, isFilterable ? GL_LINEAR : GL_NEAREST);
173 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, isFilterable ? GL_LINEAR : GL_NEAREST);
174 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, m_format, size.x(), size.y(), size.z(), 0, transferFmt.format, transferFmt.dataType, DE_NULL);
175
176 log << TestLog::Message << "Creating a framebuffer object for each layer-face" << TestLog::EndMessage;
177
178 // Generate an FBO for each layer-face
179 for (int ndx = 0; ndx < m_texSize.z(); ndx++)
180 {
181 deUint32 layerFbo;
182
183 glGenFramebuffers(1, &layerFbo);
184 glBindFramebuffer(GL_FRAMEBUFFER, layerFbo);
185 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, ndx);
186 checkError();
187 checkFramebufferStatus(GL_FRAMEBUFFER);
188
189 fbos.push_back(layerFbo);
190 }
191 }
192
193 log << TestLog::Message << "Rendering test images to layer-faces in randomized order" << TestLog::EndMessage;
194
195 {
196 std::vector<int> order(fbos.size());
197
198 for (size_t n = 0; n < order.size(); n++)
199 order[n] = (int)n;
200 rnd.shuffle(order.begin(), order.end());
201
202 for (size_t ndx = 0; ndx < order.size(); ndx++)
203 {
204 const int layerFace = order[ndx];
205 const deUint32 format = GL_RGBA;
206 const deUint32 dataType = GL_UNSIGNED_BYTE;
207 const int texW = 128;
208 const int texH = 128;
209 deUint32 tmpTex = 0;
210 const deUint32 fbo = fbos[layerFace];
211 const IVec3& viewport = m_texSize;
212 tcu::TextureLevel data (glu::mapGLTransferFormat(format, dataType), texW, texH, 1);
213
214 tcu::fillWithGrid(data.getAccess(), 8, generateRandomColor(rnd), Vec4(0.0f));
215
216 glGenTextures(1, &tmpTex);
217 glBindTexture(GL_TEXTURE_2D, tmpTex);
218 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
219 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
220 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
221 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
222 glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
223
224 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
225 glViewport(0, 0, viewport.x(), viewport.y());
226 sglr::drawQuad(*getCurrentContext(), texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
227 checkError();
228
229 // Render to framebuffer
230 {
231 const Vec3 p0 = Vec3(float(ndx % 2) - 1.0f, float(ndx / 2) - 1.0f, 0.0f);
232 const Vec3 p1 = p0 + Vec3(1.0f, 1.0f, 0.0f);
233 const int layer = layerFace / 6;
234 const tcu::CubeFace face = getCubeFaceFromNdx(layerFace % 6);
235
236 glBindFramebuffer(GL_FRAMEBUFFER, 0);
237 glViewport(0, 0, getWidth(), getHeight());
238
239 glActiveTexture(GL_TEXTURE0);
240 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, tex);
241
242 arrayTexShader.setLayer(layer);
243 arrayTexShader.setFace(face);
244 arrayTexShader.setUniforms(*getCurrentContext(), arrayTexShaderID);
245
246 sglr::drawQuad(*getCurrentContext(), arrayTexShaderID, p0, p1);
247 checkError();
248 }
249 }
250 }
251
252 readPixels(dst, 0, 0, getWidth(), getHeight());
253 }
254
255 private:
256 IVec3 m_texSize;
257 };
258
FboColorTests(Context & context)259 FboColorTests::FboColorTests (Context& context)
260 : TestCaseGroup(context, "color", "Colorbuffer tests")
261 {
262 }
263
~FboColorTests(void)264 FboColorTests::~FboColorTests (void)
265 {
266 }
267
init(void)268 void FboColorTests::init (void)
269 {
270 static const deUint32 colorFormats[] =
271 {
272 // RGBA formats
273 GL_RGBA32I,
274 GL_RGBA32UI,
275 GL_RGBA16I,
276 GL_RGBA16UI,
277 GL_RGBA8,
278 GL_RGBA8I,
279 GL_RGBA8UI,
280 GL_SRGB8_ALPHA8,
281 GL_RGB10_A2,
282 GL_RGB10_A2UI,
283 GL_RGBA4,
284 GL_RGB5_A1,
285
286 // RGB formats
287 GL_RGB8,
288 GL_RGB565,
289
290 // RG formats
291 GL_RG32I,
292 GL_RG32UI,
293 GL_RG16I,
294 GL_RG16UI,
295 GL_RG8,
296 GL_RG8I,
297 GL_RG8UI,
298
299 // R formats
300 GL_R32I,
301 GL_R32UI,
302 GL_R16I,
303 GL_R16UI,
304 GL_R8,
305 GL_R8I,
306 GL_R8UI,
307
308 // GL_EXT_color_buffer_float
309 GL_RGBA32F,
310 GL_RGBA16F,
311 GL_R11F_G11F_B10F,
312 GL_RG32F,
313 GL_RG16F,
314 GL_R32F,
315 GL_R16F,
316
317 // GL_EXT_color_buffer_half_float
318 GL_RGB16F
319 };
320
321 // .texcubearray
322 {
323 tcu::TestCaseGroup* texCubeArrayGroup = new tcu::TestCaseGroup(m_testCtx, "texcubearray", "Cube map array texture tests");
324 addChild(texCubeArrayGroup);
325
326 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
327 texCubeArrayGroup->addChild(new FboColorTexCubeArrayCase(m_context, getFormatName(colorFormats[fmtNdx]), "",
328 colorFormats[fmtNdx], IVec3(128, 128, 12)));
329 }
330 }
331
332 } // Functional
333 } // gles31
334 } // deqp
335