1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2021 Google Inc.
6 * Copyright (c) 2021 The Khronos Group Inc.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 */ /*!
21 * \file glcTexSubImageTests.cpp
22 * \brief Texture compatibility tests
23 */ /*-------------------------------------------------------------------*/
24
25 #include "glcTextureCompatibilityTests.hpp"
26
27 #include "glwEnums.hpp"
28 #include "glwFunctions.hpp"
29
30 #include "tcuImageCompare.hpp"
31 #include "tcuStringTemplate.hpp"
32 #include "tcuSurface.hpp"
33 #include "tcuTestLog.hpp"
34 #include "tcuTextureUtil.hpp"
35
36 #include "gluDefs.hpp"
37 #include "gluDrawUtil.hpp"
38 #include "gluPixelTransfer.hpp"
39 #include "gluShaderProgram.hpp"
40 #include "gluStrUtil.hpp"
41 #include "gluTextureUtil.hpp"
42
43 #include <map>
44 #include <memory>
45 #include <vector>
46
47 namespace glcts
48 {
49 namespace
50 {
51 const float vertexPositions[] = {
52 -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f,
53 };
54
55 const float vertexTexCoords[] = {
56 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
57 };
58
59 const char *vertShader = "${VERSION}\n"
60 "in highp vec4 in_position;\n"
61 "in highp vec2 in_texCoord;\n"
62 "out highp vec2 v_texCoord;\n"
63 "void main (void)\n"
64 "{\n"
65 " gl_Position = in_position;\n"
66 " v_texCoord = in_texCoord;\n"
67 "}\n";
68
69 const char *fragShader = "${VERSION}\n"
70 "precision mediump float;\n"
71 "uniform sampler2D texture0;\n"
72 "in vec2 v_texCoord;\n"
73 "out vec4 color;\n"
74 "void main(void)\n"
75 "{\n"
76 " color = texture(texture0, v_texCoord);\n"
77 "}";
78
79 struct TestParameters
80 {
81 std::string testName;
82 glw::GLenum internalFormat;
83 glw::GLenum format;
84 glw::GLenum testType;
85 };
86
87 static const TestParameters testParameters[] = {
88 {"rgba4_unsigned_byte", GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE},
89 {"rgb5_a1_unsigned_byte", GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_BYTE},
90 {"rgb5_a1_unsigned_int_10_a2", GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV},
91 {"r16f_float", GL_R16F, GL_RED, GL_FLOAT},
92 {"rg16f_float", GL_RG16F, GL_RG, GL_FLOAT},
93 {"rgb16f_float", GL_RGB16F, GL_RGB, GL_FLOAT},
94 {"rgba16f_float", GL_RGBA16F, GL_RGBA, GL_FLOAT},
95 {"r11f_g11f_b10f_half_float", GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT},
96 {"r11f_g11f_b10f_float", GL_R11F_G11F_B10F, GL_RGB, GL_FLOAT},
97 {"rgb9_e5_half_float", GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT},
98 {"rgb9_e5_float", GL_RGB9_E5, GL_RGB, GL_FLOAT},
99 {"rgb565_unsigned_byte", GL_RGB565, GL_RGB, GL_UNSIGNED_BYTE},
100 {"depth_component16_uint", GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT}};
101
102 class SubImageFormatTest : public deqp::TestCase
103 {
104 public:
105 SubImageFormatTest(deqp::Context &context, const TestParameters testParam, glw::GLsizei textureSize);
106
107 virtual ~SubImageFormatTest();
108
109 virtual void init(void);
110 virtual void deinit(void);
111
112 virtual IterateResult iterate(void);
113
114 private:
115 void setTextureParameters(glw::GLenum target);
116 void drawTexture(void);
117
118 void initializeProgram();
119 void setVertexBufferObjects();
120 void setVertexArrayObjects();
121
122 std::shared_ptr<glu::ShaderProgram> m_program;
123
124 TestParameters m_testParams;
125 glw::GLsizei m_textureSize;
126 glw::GLuint m_texId;
127 glw::GLuint m_vaoId;
128 glw::GLenum m_vboIds[2];
129 };
130
SubImageFormatTest(deqp::Context & context,const TestParameters testParams,glw::GLsizei textureSize)131 SubImageFormatTest::SubImageFormatTest(deqp::Context &context, const TestParameters testParams,
132 glw::GLsizei textureSize)
133 : deqp::TestCase(context, ("texsubimage_format_" + testParams.testName).c_str(),
134 "Pass glTexSubImage with different client format to glTexImage")
135 , m_testParams(testParams)
136 , m_textureSize(textureSize)
137 , m_texId(0)
138 , m_vaoId(0)
139 , m_vboIds{0, 0}
140 {
141 }
142
~SubImageFormatTest()143 SubImageFormatTest::~SubImageFormatTest()
144 {
145 }
146
init(void)147 void SubImageFormatTest::init(void)
148 {
149 initializeProgram();
150 setVertexBufferObjects();
151 setVertexArrayObjects();
152 }
153
deinit(void)154 void SubImageFormatTest::deinit(void)
155 {
156 const auto &gl = m_context.getRenderContext().getFunctions();
157
158 gl.deleteTextures(1, &m_texId);
159 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures() failed");
160
161 gl.deleteBuffers(1, &m_vaoId);
162 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteBuffers() failed");
163
164 gl.deleteBuffers(DE_LENGTH_OF_ARRAY(m_vboIds), m_vboIds);
165 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteBuffers() failed");
166 }
167
iterate(void)168 SubImageFormatTest::IterateResult SubImageFormatTest::iterate(void)
169 {
170 const auto &gl = m_context.getRenderContext().getFunctions();
171
172 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
173
174 // Render buffer
175 glw::GLuint rboId;
176 gl.genRenderbuffers(1, &rboId);
177 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers() failed");
178 gl.bindRenderbuffer(GL_RENDERBUFFER, rboId);
179 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer() failed");
180 gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, m_textureSize, m_textureSize);
181 GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage() failed");
182 gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
183
184 // Frame buffer
185 glw::GLuint fboId;
186 gl.genFramebuffers(1, &fboId);
187 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() failed");
188 gl.bindFramebuffer(GL_FRAMEBUFFER, fboId);
189 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() failed");
190 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rboId);
191 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer() failed");
192
193 gl.viewport(0, 0, m_textureSize, m_textureSize);
194 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() failed");
195
196 gl.disable(GL_BLEND);
197
198 gl.bindTexture(GL_TEXTURE_2D, m_texId);
199 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() failed");
200
201 gl.bindVertexArray(m_vaoId);
202 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() failed");
203
204 // Create main texture.
205 tcu::TextureFormat refTexFormat(glu::mapGLInternalFormat(m_testParams.internalFormat));
206 glu::TransferFormat refTransferFormat = glu::getTransferFormat(refTexFormat);
207 tcu::Texture2D refTexture(refTexFormat, m_textureSize, m_textureSize, 1);
208
209 refTexture.allocLevel(0);
210 tcu::fillWithComponentGradients(refTexture.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
211 tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
212
213 // Create variables for reference sub texture.
214 tcu::TextureFormat refTexFormatSub = glu::mapGLInternalFormat(m_testParams.internalFormat);
215 tcu::Texture2D refSubTexture(refTexFormatSub, m_textureSize / 2, m_textureSize / 2, 1);
216 tcu::Surface refSurface(m_textureSize, m_textureSize);
217
218 refSubTexture.allocLevel(0);
219 tcu::fillWithComponentGradients(refSubTexture.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
220 tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
221
222 // Upload the main texture data.
223 gl.texImage2D(GL_TEXTURE_2D, 0, m_testParams.internalFormat, m_textureSize, m_textureSize, 0,
224 refTransferFormat.format, refTransferFormat.dataType, refTexture.getLevel(0).getDataPtr());
225 GLU_EXPECT_NO_ERROR(
226 gl.getError(),
227 ("gltexImage2D() failed" + glu::getTextureFormatStr(m_testParams.internalFormat).toString()).c_str());
228
229 // Update the content of a previously allocated texture with reference sub texture.
230 // Reference sub texture is using the same format and data type than main texture.
231 gl.texSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_textureSize / 2, m_textureSize / 2, refTransferFormat.format,
232 refTransferFormat.dataType, refSubTexture.getLevel(0).getDataPtr());
233 GLU_EXPECT_NO_ERROR(
234 gl.getError(),
235 ("gltexSubImage2D() failed" + glu::getTextureFormatStr(m_testParams.internalFormat).toString()).c_str());
236
237 setTextureParameters(GL_TEXTURE_2D);
238
239 drawTexture();
240
241 m_context.getTestContext().getLog() << tcu::TestLog::Message << m_testParams.testName.c_str() << " ("
242 << m_textureSize << " x " << m_textureSize << ")" << tcu::TestLog::EndMessage;
243
244 // Read rendered pixels to reference surface.
245 glu::readPixels(m_context.getRenderContext(), 0, 0, refSurface.getAccess());
246
247 // Create variables for test sub texture.
248 tcu::TextureFormat testTexFormatSub = glu::mapGLTransferFormat(m_testParams.format, m_testParams.testType);
249 tcu::Texture2D testSubTexture(testTexFormatSub, m_textureSize / 2, m_textureSize / 2, 1);
250 tcu::Surface testSurface(m_textureSize, m_textureSize);
251
252 testSubTexture.allocLevel(0);
253 tcu::fillWithComponentGradients(testSubTexture.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
254 tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
255
256 // Upload the main texture data again.
257 gl.texImage2D(GL_TEXTURE_2D, 0, m_testParams.internalFormat, m_textureSize, m_textureSize, 0,
258 refTransferFormat.format, refTransferFormat.dataType, refTexture.getLevel(0).getDataPtr());
259 GLU_EXPECT_NO_ERROR(
260 gl.getError(),
261 ("gltexImage2D() failed" + glu::getTextureFormatStr(m_testParams.internalFormat).toString()).c_str());
262
263 // Update the content of a previously allocated texture with sub texture but different data type.
264 gl.texSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_textureSize / 2, m_textureSize / 2, m_testParams.format,
265 m_testParams.testType, testSubTexture.getLevel(0).getDataPtr());
266 GLU_EXPECT_NO_ERROR(
267 gl.getError(),
268 ("gltexSubImage2D() failed" + glu::getTextureFormatStr(m_testParams.internalFormat).toString()).c_str());
269
270 setTextureParameters(GL_TEXTURE_2D);
271
272 drawTexture();
273
274 // Read rendered pixels to test surface.
275 readPixels(m_context.getRenderContext(), 0, 0, testSurface.getAccess());
276
277 // Execute the comparison.
278 if (tcu::fuzzyCompare(m_testCtx.getLog(), "texsubimage_format_",
279 "Pass glTexSubImage with different client format to glTexImage", refSurface, testSurface,
280 0.001f, tcu::COMPARE_LOG_RESULT))
281 {
282 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
283 }
284
285 // Cleanup
286 gl.bindTexture(GL_TEXTURE_2D, 0);
287 gl.bindFramebuffer(GL_FRAMEBUFFER, fboId);
288 gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
289 gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
290 gl.deleteFramebuffers(1, &fboId);
291
292 return IterateResult::STOP;
293 }
294
setTextureParameters(glw::GLenum target)295 void SubImageFormatTest::setTextureParameters(glw::GLenum target)
296 {
297 const auto &gl = m_context.getRenderContext().getFunctions();
298
299 gl.texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
300 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() failed");
301
302 gl.texParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
303 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() failed");
304
305 gl.texParameteri(target, GL_TEXTURE_BASE_LEVEL, 0);
306 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() failed");
307
308 gl.texParameteri(target, GL_TEXTURE_MAX_LEVEL, 0);
309 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() failed");
310
311 gl.texParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
312 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() failed");
313
314 gl.texParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
315 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() failed");
316
317 gl.texParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
318 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() failed");
319 }
320
drawTexture(void)321 void SubImageFormatTest::drawTexture(void)
322 {
323 const auto &gl = m_context.getRenderContext().getFunctions();
324
325 gl.useProgram(m_program->getProgram());
326 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed");
327
328 gl.clearColor(1.0f, 0.0f, 1.0f, 1.0f);
329 gl.clear(GL_COLOR_BUFFER_BIT);
330 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() failed");
331
332 gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
333 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed");
334
335 gl.finish();
336 }
337
setVertexBufferObjects()338 void SubImageFormatTest::setVertexBufferObjects()
339 {
340 const auto &gl = m_context.getRenderContext().getFunctions();
341
342 gl.genBuffers(DE_LENGTH_OF_ARRAY(m_vboIds), m_vboIds);
343 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed");
344
345 gl.bindBuffer(GL_ARRAY_BUFFER, m_vboIds[0]);
346 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed");
347
348 gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW);
349 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed");
350
351 gl.bindBuffer(GL_ARRAY_BUFFER, m_vboIds[1]);
352 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed");
353
354 gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertexTexCoords), vertexTexCoords, GL_STATIC_DRAW);
355 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed");
356
357 gl.bindBuffer(GL_ARRAY_BUFFER, 0);
358 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed");
359 }
360
setVertexArrayObjects()361 void SubImageFormatTest::setVertexArrayObjects()
362 {
363 const auto &gl = m_context.getRenderContext().getFunctions();
364 const auto program = m_program->getProgram();
365 const auto positionLoc = gl.getAttribLocation(program, "in_position");
366 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation() failed");
367
368 const auto texCoordLoc = gl.getAttribLocation(program, "in_texCoord");
369 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation() failed");
370
371 gl.genVertexArrays(1, &m_vaoId);
372 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() failed");
373
374 gl.bindVertexArray(m_vaoId);
375 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() failed");
376
377 gl.bindBuffer(GL_ARRAY_BUFFER, m_vboIds[0]);
378 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed");
379
380 gl.enableVertexAttribArray(positionLoc);
381 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() failed");
382
383 gl.vertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
384 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() failed");
385
386 gl.bindBuffer(GL_ARRAY_BUFFER, m_vboIds[1]);
387 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed");
388
389 gl.enableVertexAttribArray(texCoordLoc);
390 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() failed");
391
392 gl.vertexAttribPointer(texCoordLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
393 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() failed");
394
395 gl.bindVertexArray(0);
396 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() failed");
397 }
398
initializeProgram()399 void SubImageFormatTest::initializeProgram()
400 {
401 const auto &gl = m_context.getRenderContext().getFunctions();
402
403 gl.genTextures(1, &m_texId);
404 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
405
406 const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
407 const auto glslVersion = glu::getGLSLVersionDeclaration(supportsES32 ? glu::GLSLVersion::GLSL_VERSION_320_ES :
408 glu::GLSLVersion::GLSL_VERSION_310_ES);
409 const auto args = std::map<std::string, std::string>{{"VERSION", glslVersion}};
410 const auto vs = tcu::StringTemplate(vertShader).specialize(args);
411 const auto fs = tcu::StringTemplate(fragShader).specialize(args);
412
413 m_program = std::make_shared<glu::ShaderProgram>(
414 m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(vs) << glu::FragmentSource(fs));
415
416 if (!m_program->isOk())
417 throw std::runtime_error("Compiling shader program failed.");
418 }
419
420 } // namespace
421
TextureCompatibilityTests(deqp::Context & context)422 TextureCompatibilityTests::TextureCompatibilityTests(deqp::Context &context)
423 : deqp::TestCaseGroup(context, "texture_compatibility", "Tests for texture format compatibility")
424 {
425 }
426
~TextureCompatibilityTests(void)427 TextureCompatibilityTests::~TextureCompatibilityTests(void)
428 {
429 }
430
init(void)431 void TextureCompatibilityTests::init(void)
432 {
433 for (const auto &test : testParameters)
434 addChild(new SubImageFormatTest(m_context, test, 32));
435 }
436
437 } // namespace glcts
438