xref: /aosp_15_r20/external/deqp/external/openglcts/modules/gles32/es32cCopyImageTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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