2 * Copyright © 2015 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
24 /** @file gettransformfeedback.c
25 * Simple transform feedback test drawing GL_POINTS and checking that all the
26 * state is well reported by the GetTransformFeedback*() functions.
28 * Greatly inspired from ext_transform_feedback/points.c.
30 * From OpenGL 4.5, section 22.4 "Transform Feedback State Queries", page 552:
32 * "void GetTransformFeedbackiv(uint xfb, enum pname, int *param);
33 * void GetTransformFeedbacki v(uint xfb, enum pname, uint index, int *param);
34 * void GetTransformFeedbacki64 v(uint xfb, enum pname,uint index,
37 * xfb must be zero, indicating the default transform feedback object, or the
38 * name of an existing transform feedback object. pname must be one of the
39 * tokens listed in table 23.48, depending on the command name as shown in the
40 * errors section below. For indexed state, index is the index of the transform
41 * feedback stream. param is the address of a variable to receive the result of
45 * An INVALID_OPERATION error is generated by GetTransformFeedback* if xfb is
46 * not zero or the name of an existing transform feedback object.
47 * An INVALID_ENUM error is generated by GetTransformFeedbackiv if pname is not
48 * TRANSFORM_FEEDBACK_PAUSED or TRANSFORM_FEEDBACK_ACTIVE.
49 * An INVALID_ENUM error is generated by GetTransformFeedbacki v if pname is
50 * not TRANSFORM_FEEDBACK_BUFFER_BINDING.
51 * An INVALID_ENUM error is generated by GetTransformFeedbacki64 v if pname is
52 * not TRANSFORM_FEEDBACK_BUFFER_START or TRANSFORM_FEEDBACK_BUFFER_SIZE.
53 * An INVALID_VALUE error is generated by GetTransformFeedbacki v and
54 * GetTransformFeedbacki64 v if index is greater than or equal to the number
55 * of binding points for transform feedback, as described in section 6.7.1."
58 #include "piglit-util-gl.h"
59 #include "dsa-utils.h"
61 PIGLIT_GL_TEST_CONFIG_BEGIN
62 config
.supports_gl_core_version
= 31;
63 config
.window_visual
= PIGLIT_GL_VISUAL_DOUBLE
| PIGLIT_GL_VISUAL_RGBA
;
64 config
.khr_no_error_support
= PIGLIT_NO_ERRORS
;
65 PIGLIT_GL_TEST_CONFIG_END
69 static GLuint xfb_buf
[3], input_buf
, vao
;
70 static bool pass
= true;
72 static const char *vstext
= {
78 " valOut1 = valIn + 1;"
79 " valOut2 = valIn * 2;"
84 static const GLfloat inputs
[NUM_INPUTS
] = {-1.0, 0.0, 1.0, 3.0};
97 check_active_paused_state(const char *test_name
)
101 glGetTransformFeedbackiv(0, GL_TRANSFORM_FEEDBACK_PAUSED
, ¶m
);
102 piglit_check_gl_error(GL_NO_ERROR
);
103 PIGLIT_SUBTEST_CONDITION(param
== ctx
.paused
, pass
, "%s: paused state "
106 glGetTransformFeedbackiv(0, GL_TRANSFORM_FEEDBACK_ACTIVE
, ¶m
);
107 piglit_check_gl_error(GL_NO_ERROR
);
108 PIGLIT_SUBTEST_CONDITION(param
== ctx
.active
, pass
, "%s: active state "
113 check_binding_state(const char *test_name
)
119 for (i
= 0; i
< 3; i
++) {
120 glGetTransformFeedbacki_v(0,
121 GL_TRANSFORM_FEEDBACK_BUFFER_BINDING
,
123 piglit_check_gl_error(GL_NO_ERROR
);
124 PIGLIT_SUBTEST_CONDITION(param
== ctx
.bo_state
[i
].binding
, pass
,
125 "%s: bound buffer %i valid", test_name
, i
);
127 glGetTransformFeedbacki64_v(0,
128 GL_TRANSFORM_FEEDBACK_BUFFER_START
,
130 piglit_check_gl_error(GL_NO_ERROR
);
131 PIGLIT_SUBTEST_CONDITION(param64
== ctx
.bo_state
[i
].start
, pass
,
132 "%s: bound buffer %i start valid", test_name
,
135 glGetTransformFeedbacki64_v(0,
136 GL_TRANSFORM_FEEDBACK_BUFFER_SIZE
,
138 piglit_check_gl_error(GL_NO_ERROR
);
139 PIGLIT_SUBTEST_CONDITION(param64
== ctx
.bo_state
[i
].size
, pass
,
140 "%s: bound buffer %i size valid", test_name
,
146 check_invalid_queries()
151 if (piglit_khr_no_error
)
154 glGetTransformFeedbackiv(0, GL_TRANSFORM_FEEDBACK_BINDING
, ¶m
);
155 PIGLIT_SUBTEST_ERROR(GL_INVALID_ENUM
, pass
,
156 "glGetTransformFeedbackiv: fetch invalid attribute");
158 glGetTransformFeedbacki_v(0, GL_TRANSFORM_FEEDBACK_ACTIVE
, 0, ¶m
);
159 PIGLIT_SUBTEST_ERROR(GL_INVALID_ENUM
, pass
,
160 "glGetTransformFeedbacki_v: fetch invalid attribute");
162 glGetTransformFeedbacki64_v(0, GL_TRANSFORM_FEEDBACK_BUFFER_BINDING
,
164 PIGLIT_SUBTEST_ERROR(GL_INVALID_ENUM
, pass
,
165 "glGetTransformFeedbacki64_v: fetch invalid attribute");
169 piglit_init(int argc
, char **argv
)
171 static const char *varyings
[] = { "valOut1", "valOut2" };
176 /* Check the driver. */
177 piglit_require_extension("GL_ARB_transform_feedback3");
178 piglit_require_extension("GL_ARB_direct_state_access");
180 /* Create shaders. */
181 prog
= piglit_build_simple_program_unlinked(vstext
, NULL
);
182 glTransformFeedbackVaryings(prog
, 2, varyings
,
183 GL_SEPARATE_ATTRIBS
);
185 if (!piglit_link_check_status(prog
)) {
186 glDeleteProgram(prog
);
187 piglit_report_result(PIGLIT_FAIL
);
191 /* Set up the Vertex Array Buffer */
192 glEnable(GL_VERTEX_ARRAY
);
193 glGenVertexArrays(1, &vao
);
194 glBindVertexArray(vao
);
196 /* Set up the input data buffer */
197 glGenBuffers(1, &input_buf
);
198 glBindBuffer(GL_ARRAY_BUFFER
, input_buf
);
199 glBufferData(GL_ARRAY_BUFFER
, sizeof(inputs
), inputs
, GL_STATIC_DRAW
);
200 inAttrib
= glGetAttribLocation(prog
, "valIn");
201 piglit_check_gl_error(GL_NO_ERROR
);
202 glVertexAttribPointer(inAttrib
, 1, GL_FLOAT
, GL_FALSE
, 0, 0);
203 glEnableVertexAttribArray(inAttrib
);
205 /* set the initial state */
208 for (i
= 0; i
< 3; i
++) {
209 ctx
.bo_state
[i
].binding
= 0;
210 ctx
.bo_state
[i
].start
= 0;
211 ctx
.bo_state
[i
].size
= 0;
213 check_active_paused_state("initial state");
214 check_binding_state("initial state");
216 /* Set up the transform feedback buffer */
217 glGenBuffers(3, xfb_buf
);
218 for (i
= 0; i
< 2; i
++) {
219 start
= rand() & 0xFC;
220 size
= 0x100 + (rand() & 0xFFC);
222 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER
, xfb_buf
[i
]);
223 piglit_check_gl_error(GL_NO_ERROR
);
224 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER
,
225 start
+ size
, NULL
, GL_STREAM_READ
);
226 piglit_check_gl_error(GL_NO_ERROR
);
227 glTransformFeedbackBufferRange(0, i
, xfb_buf
[i
], start
, size
);
228 piglit_check_gl_error(GL_NO_ERROR
);
230 ctx
.bo_state
[i
].binding
= xfb_buf
[i
];
231 ctx
.bo_state
[i
].start
= start
;
232 ctx
.bo_state
[i
].size
= size
;
235 check_binding_state("post-binding state");
241 check_invalid_queries();
243 glClear(GL_COLOR_BUFFER_BIT
);
245 glBeginTransformFeedback(GL_POINTS
);
248 check_active_paused_state("TransformFeedback started");
250 glPauseTransformFeedback();
253 check_active_paused_state("TransformFeedback paused");
255 glResumeTransformFeedback();
258 check_active_paused_state("TransformFeedback resumed");
260 glEndTransformFeedback();
263 check_active_paused_state("TransformFeedback ended");
265 /* clean-up everything */
266 glDeleteBuffers(3, xfb_buf
);
267 glDeleteBuffers(1, &input_buf
);
268 glDeleteVertexArrays(1, &vao
);
269 glDeleteProgram(prog
);
271 return pass
? PIGLIT_PASS
: PIGLIT_FAIL
;