• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 deUint16   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