Esempio n. 1
0
void
piglit_init(int argc, char **argv)
{
	bool pass = true;
	GLuint framebuffer;
	GLuint default_framebuffer = 0;
	GLenum bufs[2] = {GL_BACK_LEFT, GL_BACK};
	GLenum one_buf;
	bool subtest_pass;
	int i;

	glCreateFramebuffers(1, &framebuffer);
	piglit_check_gl_error(GL_NO_ERROR);

	/*
	 * "An INVALID_OPERATION error is generated by
	 *  NamedFramebufferDrawBuffers if framebuffer is not zero or
	 *  the name of an existing framebuffer"
	 */
	glNamedFramebufferDrawBuffers(5, 2, bufs);
	PIGLIT_SUBTEST_ERROR(GL_INVALID_OPERATION, pass, "INVALID_OPERATION if "
			     "framebuffer is not zero or the name of an existing "
			     "framebuffer");

	/*
	 * "An INVALID_VALUE error is generated if n is negative, or greater than the
	 *  value of MAX_DRAW_BUFFERS."
	 */
	int max_draw_buffers;
	glGetIntegerv(GL_MAX_DRAW_BUFFERS, &max_draw_buffers);

	subtest_pass = true;
	glNamedFramebufferDrawBuffers(0, -1, bufs);
	subtest_pass = subtest_pass & piglit_check_gl_error(GL_INVALID_VALUE);

	glNamedFramebufferDrawBuffers(0, max_draw_buffers + 1, bufs);
	subtest_pass = subtest_pass & piglit_check_gl_error(GL_INVALID_VALUE);

	PIGLIT_SUBTEST_CONDITION(subtest_pass, pass, "INVALID_VALUE error is "
				 "generated if n is negative, or greater than "
				 "the value of MAX_DRAW_BUFFERS.");

	/*
	 * From OpenGL 4.5 spec
	 *   "An INVALID_ENUM error is generated if any value in bufs
	 *    is not one of the values in tables 17.5 or 17.6."
	 */
	subtest_pass = true;
	one_buf = GL_RED;
	glNamedFramebufferDrawBuffers(default_framebuffer, 1, &one_buf);
	subtest_pass = subtest_pass && piglit_check_gl_error(GL_INVALID_ENUM);
	glNamedFramebufferDrawBuffers(framebuffer, 1, &one_buf);
	subtest_pass = subtest_pass && piglit_check_gl_error(GL_INVALID_ENUM);

	PIGLIT_SUBTEST_CONDITION(subtest_pass, pass, "INVALID_ENUM error is "
				 "generated if any value in bufs is not one of "
				 "the values in tables 17.5 or 17.6.");
	/*
	* (cont on error out of 17.5 or 17.6) Specifically for the default
	 * framebuffer:
	 * From OpenGL 4.5 spec, page 492 (515 PDF)
	 * "If the default framebuffer is affected, then each of the
	 *  constants must be one of the values listed in table 17.6
	 *  or the special value BACK .""
	 *
	 * And:
	 *"An INVALID_OPERATION error is generated if the default
	 *  framebuffer is affected and any value in bufs is a
	 *  constant (other than NONE or BACK) that does not indicate
	 *  one of the color buffers allocated to the default
	 *  framebuffer."
	 *
	 * So for the default framebuffer, and that table, we expect
	 * GL_NO_ERROR or GL_INVALID_OPERATION.
	 */
	subtest_pass = true;
	for (i = 0; i < ARRAY_SIZE(table_17_6_and_back); i++) {
		GLenum err = 0;

		glNamedFramebufferDrawBuffers(default_framebuffer, 1,
					      &table_17_6_and_back[i]);

		/* We manually check glGetError instead of relying on
		 * piglit_check_gl_error like in other subtests
		 * because for subtests that checks several enums, we
		 * are interested on getting which one failed. That
		 * makes debugging easier.
		 */
		err = glGetError();
		if (err != GL_NO_ERROR && err != GL_INVALID_OPERATION) {
			printf("Expected GL_NO_ERROR or GL_INVALID_OPERATION "
			       "with %s but received: %s\n",
			       piglit_get_gl_enum_name(table_17_6_and_back[i]),
			       piglit_get_gl_error_name(err));
			subtest_pass = false;
		}
	}

	/* For that spec paragraph, we also test enums from table
	 * 17.5. They should return INVALID_OPERATION, as after all,
	 * they are not allocated to the default framebuffer. */
	one_buf = GL_COLOR_ATTACHMENT0;
	glNamedFramebufferDrawBuffers(default_framebuffer, 1, &one_buf);
	subtest_pass = subtest_pass &&
	  piglit_check_gl_error(GL_INVALID_OPERATION);

	PIGLIT_SUBTEST_CONDITION(subtest_pass, pass, "If the default framebuffer"
				 " is affected, then each of the constants must "
				 "be one of the values listed in table 17.6 or "
				 "the special value BACK. INVALID_OPERATION error"
				 " is generated if the default framebuffer is "
				 "affected and any value in bufs is a constant "
				 "(other than NONE or BACK ) that does not indicate "
				 "one of the color buffers allocated to the default"
				 " framebuffer.");

	/* (cont default framebuffer)
	 * From OpenGL 4.5 spec:
	 * "When BACK is used, n must be 1 and color values are
	 *  written into the left buffer for single-buffered
	 *  contexts, or into the back left buffer for
	 *  double-buffered contexts"
	 *
	 * From the error table:
	 * "An INVALID_OPERATION error is generated if any value in
	 *   bufs is BACK , and n is not one."
	 *
	 */
	glNamedFramebufferDrawBuffers(default_framebuffer, 2, bufs);
	PIGLIT_SUBTEST_ERROR(GL_INVALID_OPERATION, pass, "(default framebuffer)"
			     " An INVALID_OPERATION error is generated if any "
			     "value in bufs is BACK, and n is not one.");

	/*
	 * Now, specifically for a framebuffer object:
	 * "If a framebuffer object is affected, then each of the
	 *  constants must be one of the values listed in table 17.5."
	 *
	 * 17.5 is GL_NONE, and COLOR_ATTACHMENTi, where i <
	 * MAX_COLOR_ATTACHMENTS - 1
	 */
	int max_attachments;
	glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &max_attachments);

	subtest_pass = true;
	for (i = 0; i < max_attachments; i++) {
		 one_buf = GL_COLOR_ATTACHMENT0 + i;
		 glNamedFramebufferDrawBuffers(framebuffer, 1, &one_buf);
		 subtest_pass = subtest_pass &&
		   piglit_check_gl_error(GL_NO_ERROR);
	}
	PIGLIT_SUBTEST_CONDITION(subtest_pass, pass, "If a framebuffer object is "
			 "affected, then each of constants must be one of the "
			 "values listed in table 17.5.");

	/*
	 * "An INVALID_OPERATION error is generated if a framebuffer
	 *  object is affected and any value in bufs is a constant
	 *  from table 17.6, or COLOR_ATTACHMENTm where m is greater
	 *  than or equal to the value of MAX_COLOR_ATTACHMENTS."
	 */
	subtest_pass = true;
	/* Starting at 1, as GL_NONE is valid */
	for (i = 1; i < ARRAY_SIZE(table_17_6); i++) {
		GLenum err = 0;

		glNamedFramebufferDrawBuffers(framebuffer, 1, &table_17_6[i]);
		err = glGetError();
		if (err != GL_INVALID_OPERATION) {
			printf("Expected GL_INVALID_OPERATION with"
			       " %s but received: %s\n",
			       piglit_get_gl_enum_name(table_17_6[i]),
			       piglit_get_gl_error_name(err));
			subtest_pass = false;
		}
	}

	one_buf = GL_COLOR_ATTACHMENT0 + max_attachments;
	glNamedFramebufferDrawBuffers(framebuffer, 1, &one_buf);
	subtest_pass = subtest_pass &&
	  piglit_check_gl_error(GL_INVALID_OPERATION);
	PIGLIT_SUBTEST_CONDITION(subtest_pass, pass, "INVALID_OPERATION error is "
			 "generated if a framebuffer object is affected and any "
			 "value in bufs is a constant from table 17.6, or "
			 "COLOR_ATTACHMENTm where m is greater than or equal "
			 "to the value of MAX_COLOR_ATTACHMENTS.");

	/*
	 * "An INVALID_OPERATION error is generated if a buffer other
	 *  than NONE is specified more than once in the array pointed
	 *  to by bufs"
	 */
	bufs[0] = bufs[1] = GL_FRONT_LEFT;
	glNamedFramebufferDrawBuffers(framebuffer, 2, bufs);
	PIGLIT_SUBTEST_ERROR(GL_INVALID_OPERATION, pass, "INVALID_OPERATION error "
			     "is generated if a buffer other than NONE is specified "
			     "more than once in the array pointed to by bufs.");

	/*
	 * From OpenGL 4.5 spec:
	 * "An INVALID_ENUM error is generated if any value in bufs is
	 *  FRONT, LEFT, RIGHT, or FRONT_AND_BACK . This restriction
	 *  applies to both the default framebuffer and framebuffer
	 *  objects, and exists because these constants may themselves
	 *  refer to multiple buffers, as shown in table 17.4."
	 */
	subtest_pass = true;
	for (i = 0; i < ARRAY_SIZE(multiple_buffers); i++) {
		GLenum err = 0;
		bool local_pass = true;

		glNamedFramebufferDrawBuffers(default_framebuffer, 1,
					      &multiple_buffers[i]);
		err = glGetError();
		local_pass = local_pass && (err == GL_INVALID_ENUM);

		glNamedFramebufferDrawBuffers(framebuffer, 1,
					      &multiple_buffers[i]);
		err = glGetError();
		local_pass = local_pass && (err == GL_INVALID_ENUM);

		if (!local_pass)
			printf("Expected GL_INVALID_ENUM with"
			       " %s but received: %s\n",
			       piglit_get_gl_enum_name(table_17_6_and_back[i]),
			       piglit_get_gl_error_name(err));

		subtest_pass = subtest_pass && local_pass;

	}
	PIGLIT_SUBTEST_CONDITION(subtest_pass, pass, "INVALID_ENUM error is "
				 "generated if any value in bufs is FRONT, LEFT,"
				 " RIGHT, or FRONT_AND_BACK ");

	/* clean up */
	glDeleteFramebuffers(1, &framebuffer);

	piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL);
}
enum piglit_result
piglit_display(void)
{
	GLint max_bind_points = 0;
	GLuint q, num_prims;
	bool pass = true, test = true;
	GLfloat *v, *w;
	int i;

	/* init the transform feedback buffers */
	glGenBuffers(3, xfb_buf);
	glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_buf[2]);
	piglit_check_gl_error(GL_NO_ERROR);

	/* Fetch the number of bind points */
	glGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_BUFFERS, &max_bind_points);
	PIGLIT_SUBTEST_ERROR(GL_NO_ERROR, pass, "fetch maximum number of bind "
			     "points");

	if (piglit_khr_no_error)
		goto valid_calls;

	/* bind a non-existing transform feedback BO */
	glTransformFeedbackBufferBase(1337, 0, 0);
	PIGLIT_SUBTEST_ERROR(GL_INVALID_OPERATION, pass,
			"bind non-existing transform feedback BO");

	/* bind a non-existing output BO */
	glTransformFeedbackBufferBase(0, 0, 1337);
	PIGLIT_SUBTEST_ERROR(GL_INVALID_VALUE, pass, "bind a non-existing "
			     "output BO");

	/* bind to a negative index */
	glTransformFeedbackBufferBase(0, -1, xfb_buf[2]);
	PIGLIT_SUBTEST_ERROR(GL_INVALID_VALUE, pass, "bind negative index");

	/* bind to an index == max */
	glTransformFeedbackBufferBase(0, max_bind_points, xfb_buf[2]);
	PIGLIT_SUBTEST_ERROR(GL_INVALID_VALUE, pass, "bind to index == "
			     "max_bind_points (%i)", max_bind_points);

valid_calls:
	/* Set up the transform feedback buffer */
	for (i = 0; i < 2; i++) {
		glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_buf[i]);
		glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER,
				 xfb_buf_size, NULL, GL_STREAM_READ);
		glTransformFeedbackBufferBase(0, i, xfb_buf[i]);
		piglit_check_gl_error(GL_NO_ERROR);
	}

	/* Set up the query that checks the # of primitives handled */
	glGenQueries(1, &q);
	glBeginQuery(GL_PRIMITIVES_GENERATED, q);
	piglit_check_gl_error(GL_NO_ERROR);

	/* do the transform feedback */
	glBeginTransformFeedback(GL_POINTS);
	glBindBuffer(GL_ARRAY_BUFFER, input_buf);
	glDrawArrays(GL_POINTS, 0, NUM_INPUTS);
	glEndTransformFeedback();

	glEndQuery(GL_PRIMITIVES_GENERATED);

	/* check the number of primitives */
	glGetQueryObjectuiv(q, GL_QUERY_RESULT, &num_prims);
	glDeleteQueries(1, &q);
	printf("%u primitives generated:\n", num_prims);
	if (num_prims != NUM_INPUTS) {
		printf("Incorrect number of prims generated.\n");
		printf("Found %u, expected %u\n", num_prims, NUM_INPUTS);
		pass = false;
		test = false;
	}

	/* check the result */
	glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_buf[0]);
	v = glMapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
	piglit_check_gl_error(GL_NO_ERROR);
	glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_buf[1]);
	w = glMapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
	piglit_check_gl_error(GL_NO_ERROR);

	for (i = 0; i < num_prims; i++) {
		printf("%2d: (%2.0g, %2.0g) : ", i, v[i], w[i]);
		if (!equal(v[i], out1_ret[i]) || !equal(w[i], out2_ret[i])) {
			printf("NOK, expected (%2.0g, %2.0g)\n",
			       out1_ret[i], out2_ret[i]);
			test = false;
		} else
			printf("OK\n");
	}
	PIGLIT_SUBTEST_CONDITION(test, pass, "general test");

	piglit_present_results();

	/* clean-up everything */
	glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_buf[0]);
	glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
	glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_buf[1]);
	glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
	glDeleteBuffers(3, xfb_buf);
	glDeleteBuffers(1, &input_buf);
	glDeleteVertexArrays(1, &vao);
	glDeleteProgram(prog);

	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
}