1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2017 The Khronos Group Inc.
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 es32cCopyImageTests.cpp
21 * \brief Implements CopyImageSubData functional tests.
22 */ /*-------------------------------------------------------------------*/
23
24 #include "es32cCopyImageTests.hpp"
25
26 #include "gluDefs.hpp"
27 #include "gluDrawUtil.hpp"
28 #include "gluShaderProgram.hpp"
29 #include "gluStrUtil.hpp"
30 #include "glwEnums.hpp"
31 #include "glwFunctions.hpp"
32 #include "tcuFloat.hpp"
33 #include "tcuStringTemplate.hpp"
34 #include "tcuTestLog.hpp"
35
36 #include <algorithm>
37 #include <iomanip>
38 #include <map>
39 #include <sstream>
40 #include <vector>
41
42 #include "deMath.h"
43
44 using namespace glw;
45
46 #define TEXTURE_WIDTH 16
47 #define TEXTURE_HEIGHT 16
48
49 namespace glcts
50 {
51
52 /** Implements functional test. Description follows:
53 *
54 * 1. Create a single level integer texture, with BASE_LEVEL and MAX_LEVEL set to 0.
55 * 2. Leave the mipmap filters at the default of GL_NEAREST_MIPMAP_LINEAR and GL_LINEAR.
56 * 3. Do glCopyImageSubData to or from that texture.
57 * 4. Make sure it succeeds and does not raise GL_INVALID_OPERATION.
58 **/
59 class IntegerTexTest : public deqp::TestCase
60 {
61 public:
62 IntegerTexTest(deqp::Context &context, const char *name, glw::GLint internal_format, glw::GLuint type);
63
~IntegerTexTest()64 virtual ~IntegerTexTest()
65 {
66 }
67
68 /* Implementation of tcu::TestNode methods */
69 virtual IterateResult iterate(void);
70
71 private:
72 /* Private methods */
73 GLuint createTexture(const GLvoid *data, GLint minFilter, GLint magFilter);
74 bool verify(glw::GLuint texture_name, glw::GLuint sampler_type);
75 void clean();
76
77 /* Private fields */
78 glw::GLuint m_dst_tex_name;
79 glw::GLuint m_src_tex_name;
80 glw::GLint m_internal_format;
81 glw::GLuint m_type;
82 };
83
84 /** Constructor
85 *
86 * @param context Text context
87 **/
IntegerTexTest(deqp::Context & context,const char * name,glw::GLint internal_format,glw::GLuint type)88 IntegerTexTest::IntegerTexTest(deqp::Context &context, const char *name, glw::GLint internal_format, glw::GLuint type)
89 : TestCase(
90 context, name,
91 "Test verifies if INVALID_OPERATION is generated when texture provided to CopySubImageData is incomplete")
92 , m_dst_tex_name(0)
93 , m_src_tex_name(0)
94 , m_internal_format(internal_format)
95 , m_type(type)
96 {
97 }
98
99 /** Create texture
100 *
101 * @return Texture name
102 **/
createTexture(const GLvoid * data,GLint minFilter,GLint magFilter)103 GLuint IntegerTexTest::createTexture(const GLvoid *data, GLint minFilter, GLint magFilter)
104 {
105 const Functions &gl = m_context.getRenderContext().getFunctions();
106 GLuint tex_name;
107
108 gl.genTextures(1, &tex_name);
109 GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
110 gl.bindTexture(GL_TEXTURE_2D, tex_name);
111 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
112 gl.texImage2D(GL_TEXTURE_2D, 0, m_internal_format, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_RED_INTEGER, m_type, data);
113 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage2D");
114 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
115 GLU_EXPECT_NO_ERROR(gl.getError(), "TexParameteri");
116 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
117 GLU_EXPECT_NO_ERROR(gl.getError(), "TexParameteri");
118 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
119 GLU_EXPECT_NO_ERROR(gl.getError(), "TexParameteri");
120 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
121 GLU_EXPECT_NO_ERROR(gl.getError(), "TexParameteri");
122 gl.bindTexture(GL_TEXTURE_2D, 0);
123
124 return tex_name;
125 }
126
127 /** Execute test
128 *
129 * @return CONTINUE as long there are more test case, STOP otherwise
130 **/
iterate()131 tcu::TestNode::IterateResult IntegerTexTest::iterate()
132 {
133 const Functions &gl = m_context.getRenderContext().getFunctions();
134
135 /* Create destination and source textures */
136 std::vector<int> data_buf(TEXTURE_WIDTH * TEXTURE_HEIGHT, 1);
137 m_dst_tex_name = createTexture(&data_buf[0], GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR);
138 std::fill(data_buf.begin(), data_buf.end(), 0);
139 m_src_tex_name = createTexture(&data_buf[0], GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR);
140
141 /* Execute CopyImageSubData */
142 gl.copyImageSubData(m_src_tex_name, GL_TEXTURE_2D, 0 /* srcLevel */, 0 /* srcX */, 0 /* srcY */, 0 /* srcZ */,
143 m_dst_tex_name, GL_TEXTURE_2D, 0 /* dstLevel */, 0 /* dstX */, 0 /* dstY */, 0 /* dstZ */,
144 1 /* srcWidth */, 1 /* srcHeight */, 1 /* srcDepth */);
145
146 GLenum error = gl.getError();
147 if (error == GL_NO_ERROR)
148 {
149 /* Verify result */
150 if (verify(m_dst_tex_name, m_type))
151 {
152 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
153 }
154 else
155 {
156 m_context.getTestContext().getLog()
157 << tcu::TestLog::Message << "Failure. Image data is not valid." << tcu::TestLog::EndMessage;
158
159 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
160 }
161 }
162 else
163 {
164 m_context.getTestContext().getLog()
165 << tcu::TestLog::Message << "Failure. Expected no error, got: " << glu::getErrorStr(error)
166 << ". Texture internal format: " << glu::getTextureFormatStr(m_internal_format) << tcu::TestLog::EndMessage;
167
168 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
169 }
170
171 /* Remove resources */
172 clean();
173
174 /* Done */
175 return tcu::TestNode::STOP;
176 }
177
178 /** Verify result
179 *
180 **/
verify(glw::GLuint texture_name,glw::GLuint sampler_type)181 bool IntegerTexTest::verify(glw::GLuint texture_name, glw::GLuint sampler_type)
182 {
183 static char const *vs = "${VERSION}\n"
184 "in highp vec2 a_position;\n"
185 "void main(void)\n"
186 "{\n"
187 " gl_Position = vec4(a_position, 0.0, 1.0);\n"
188 "}\n";
189
190 static char const *fs = "${VERSION}\n"
191 "uniform highp ${SAMPLER} u_texture;\n"
192 "layout(location = 0) out highp vec4 o_color;\n"
193 "void main(void)\n"
194 "{\n"
195 " ivec2 coord = ivec2(gl_FragCoord.x, gl_FragCoord.y);\n"
196 " o_color = vec4(texelFetch(u_texture, coord, 0).r);\n"
197 "}\n";
198
199 glu::RenderContext &render_context = m_context.getRenderContext();
200 glu::GLSLVersion glsl_version = glu::getContextTypeGLSLVersion(render_context.getType());
201 const Functions &gl = m_context.getRenderContext().getFunctions();
202
203 std::map<std::string, std::string> specialization_map;
204 specialization_map["VERSION"] = glu::getGLSLVersionDeclaration(glsl_version);
205 specialization_map["SAMPLER"] = (sampler_type == GL_INT) ? "isampler2D" : "usampler2D";
206
207 glu::ShaderProgram program(m_context.getRenderContext(),
208 glu::makeVtxFragSources(tcu::StringTemplate(vs).specialize(specialization_map).c_str(),
209 tcu::StringTemplate(fs).specialize(specialization_map).c_str()));
210
211 if (!program.isOk())
212 {
213 m_testCtx.getLog() << program;
214 TCU_FAIL("Compile failed");
215 }
216
217 static float const position[] = {
218 -1.0f, -1.0f, -1.0f, +1.0f, +1.0f, -1.0f, +1.0f, +1.0f,
219 };
220
221 gl.useProgram(program.getProgram());
222 gl.uniform1i(gl.getUniformLocation(program.getProgram(), "u_texture"), 0);
223
224 static const uint16_t quad_indices[] = {0, 1, 2, 2, 1, 3};
225 glu::VertexArrayBinding vertex_arrays[] = {
226 glu::va::Float("a_position", 2, 4, 0, &position[0]),
227 };
228
229 GLuint rbo;
230 gl.genRenderbuffers(1, &rbo);
231 gl.bindRenderbuffer(GL_RENDERBUFFER, rbo);
232 gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT);
233
234 GLuint fbo;
235 gl.genFramebuffers(1, &fbo);
236 gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
237 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
238 gl.viewport(0, 0, TEXTURE_WIDTH, TEXTURE_HEIGHT);
239
240 gl.activeTexture(GL_TEXTURE0);
241 gl.bindTexture(GL_TEXTURE_2D, texture_name);
242
243 // make texture complete
244 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
245 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
246
247 glu::draw(render_context, program.getProgram(), DE_LENGTH_OF_ARRAY(vertex_arrays), &vertex_arrays[0],
248 glu::pr::Triangles(DE_LENGTH_OF_ARRAY(quad_indices), &quad_indices[0]));
249
250 const unsigned int result_size = TEXTURE_WIDTH * TEXTURE_HEIGHT * 4;
251 std::vector<unsigned char> result(result_size, 3);
252 gl.readPixels(0, 0, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, &result[0]);
253
254 gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
255 gl.deleteFramebuffers(1, &fbo);
256
257 gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
258 gl.deleteRenderbuffers(1, &rbo);
259
260 return ((std::count(result.begin(), result.begin() + 4, 0) == 4) &&
261 (std::count(result.begin() + 4, result.end(), 255) == (result_size - 4)));
262 }
263
264 /** Cleans resources
265 *
266 **/
clean()267 void IntegerTexTest::clean()
268 {
269 const Functions &gl = m_context.getRenderContext().getFunctions();
270
271 /* Clean textures and buffers. Errors ignored */
272 gl.deleteTextures(1, &m_dst_tex_name);
273 gl.deleteTextures(1, &m_src_tex_name);
274
275 m_dst_tex_name = 0;
276 m_src_tex_name = 0;
277 }
278
CopyImageTests(deqp::Context & context)279 CopyImageTests::CopyImageTests(deqp::Context &context) : TestCaseGroup(context, "copy_image", "")
280 {
281 }
282
~CopyImageTests(void)283 CopyImageTests::~CopyImageTests(void)
284 {
285 }
286
init()287 void CopyImageTests::init()
288 {
289 addChild(new IntegerTexTest(m_context, "r32i_texture", GL_R32I, GL_INT));
290 addChild(new IntegerTexTest(m_context, "r32ui_texture", GL_R32UI, GL_UNSIGNED_INT));
291 }
292
293 } /* namespace glcts */
294