[Piglit] [PATCH] Porting arb occlusion query conformance tests from Glean to Piglit.

Brian Paul brianp at vmware.com
Wed Sep 9 13:58:29 PDT 2015


On 09/08/2015 05:28 PM, Juliet Fru wrote:
> ---
>   tests/all.py                                       |   1 +
>   tests/spec/arb_occlusion_query/CMakeLists.gl.txt   |   1 +
>   .../arb_occlusion_query/occlusion_query_conform.c  | 609 +++++++++++++++++++++
>   3 files changed, 611 insertions(+)
>   create mode 100644 tests/spec/arb_occlusion_query/occlusion_query_conform.c
>
> diff --git a/tests/all.py b/tests/all.py
> index fe088f5..748165f 100644
> --- a/tests/all.py
> +++ b/tests/all.py
> @@ -2115,6 +2115,7 @@ with profile.group_manager(
>           PiglitGLTest,
>           grouptools.join('spec', 'ARB_occlusion_query')) as g:
>       g(['occlusion_query'])
> +    g(['occlusion_query_conformance'])
>       g(['occlusion_query_lifetime'])
>       g(['occlusion_query_meta_fragments'])
>       g(['occlusion_query_meta_no_fragments'])
> diff --git a/tests/spec/arb_occlusion_query/CMakeLists.gl.txt b/tests/spec/arb_occlusion_query/CMakeLists.gl.txt
> index 01a499d..23a19e4 100644
> --- a/tests/spec/arb_occlusion_query/CMakeLists.gl.txt
> +++ b/tests/spec/arb_occlusion_query/CMakeLists.gl.txt
> @@ -10,6 +10,7 @@ link_libraries (
>   )
>
>   piglit_add_executable (occlusion_query occlusion_query.c)
> +piglit_add_executable (occlusion_query_conformance occlusion_query_conform.c)
>   piglit_add_executable (occlusion_query_lifetime occlusion_query_lifetime.c)
>   piglit_add_executable (occlusion_query_meta_no_fragments occlusion_query_meta_no_fragments.c)
>   piglit_add_executable (occlusion_query_meta_fragments occlusion_query_meta_fragments.c)
> diff --git a/tests/spec/arb_occlusion_query/occlusion_query_conform.c b/tests/spec/arb_occlusion_query/occlusion_query_conform.c
> new file mode 100644
> index 0000000..94da232
> --- /dev/null
> +++ b/tests/spec/arb_occlusion_query/occlusion_query_conform.c
> @@ -0,0 +1,609 @@
> +/*  BEGIN_COPYRIGHT -*- glean -*-
> + *
> + *  Copyright (C) 1999  Allen Akin   All Rights Reserved.
> + *  Copyright (C) 2015  Intel Corporation.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> + * DEALINGS IN THE SOFTWARE.
> + *
> + * END_COPYRIGHT
> + */
> +
> +/** @file occlusion_query_conform.c
> + *
> + *	Conformance test on ARB_occlusion_query extension.
> + *
> + *	Authors:
> + *	Wei Wang <wei.z.wang at intel.com>
> + *	Adapted to Piglit by Juliet Fru <julietfru at gmail.com>, September 2015
> + */
> +
> +#include "piglit-util-gl.h"
> +#include <stdlib.h>
> +#include <assert.h>
> +#include <string.h>
> +#include <stdio.h>
> +#include <math.h>
> +#include <time.h>
> +
> +PIGLIT_GL_TEST_CONFIG_BEGIN config.supports_gl_compat_version = 10;
> +
> +
> +config.window_width = 160;
> +config.window_height = 160;

Is that window size a requirement?  We've been trying to avoid 
specifying a specific window size in most tests.


> +config.window_visual =
> +	PIGLIT_GL_VISUAL_RGB | PIGLIT_GL_VISUAL_DOUBLE |
> +	PIGLIT_GL_VISUAL_DEPTH;
> +
> +PIGLIT_GL_TEST_CONFIG_END

Insert a blank line or two here.


> +/* Generate a box which will be occluded by the occluder */
> +	static void
> +gen_box(GLfloat left, GLfloat right, GLfloat top, GLfloat btm)
> +{
> +	piglit_draw_rect(right, top, left + right, top + btm);
> +}

How about just replacing all the calls to gen_box() with calls to 
piglit_draw_rect() instead?


> +
> +static GLuint
> +find_unused_id(void)
> +{
> +	GLuint id;
> +	glGenQueries(1, &id);
> +	return id;
> +
> +}
> +
> +/* If multiple queries are issued on the same target and id prior to calling
> + * GetQueryObject[u]iVARB, the result returned will always be from the last
> + * query issued.  The results from any queries before the last one will be lost
> + * if the results are not retrieved before starting a new query on the same
> + * target and id.
> + */
> +bool
> +conformOQ_GetObjivAval_multi1(GLuint id)

This function and the rest can be declared static.


> +{
> +	GLint ready;
> +	GLuint passed = 0;
> +
> +	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
> +
> +	glMatrixMode(GL_PROJECTION);
> +	glPushMatrix();
> +	glLoadIdentity();
> +	glOrtho(-1.0, 1.0, -1.0, 1.0, 0.0, 25.0);
> +
> +	glMatrixMode(GL_MODELVIEW);
> +	glPushMatrix();
> +	glLoadIdentity();
> +	glTranslatef(0.0, 0.0, -10.0);
> +
> +	/* draw the occluder (red) */
> +	glColorMask(1, 1, 1, 1);
> +	glDepthMask(GL_TRUE);
> +	glColor3f(1, 0, 0);
> +	gen_box(-0.5, 0.5, 0.5, -0.5);
> +
> +	glPushMatrix();
> +	glTranslatef(0.0, 0.0, -5.0);
> +	glColorMask(0, 0, 0, 0);
> +	glDepthMask(GL_FALSE);
> +
> +	/* draw the 1st box (gren) which is occluded by the occluder partly */
> +	START_QUERY(id);

Looks like you removed the START_QUERY and TERM_QUERY macros, so how can 
these macro calls work??


> +	glColor3f(0, 1, 0);
> +	gen_box(-0.51, 0.51, 0.51, -0.51);
> +	TERM_QUERY();
> +
> +	/* draw the 2nd box (blue) which is occluded by the occluder throughly */
> +	START_QUERY(id);
> +	glColor3f(0, 0, 1);
> +	gen_box(-0.4, 0.4, 0.4, -0.4);
> +	TERM_QUERY();
> +
> +	glPopMatrix();
> +
> +	glPopMatrix();
> +	glMatrixMode(GL_PROJECTION);
> +	glPopMatrix();
> +
> +	do {
> +		glGetQueryObjectivARB(id, GL_QUERY_RESULT_AVAILABLE_ARB,
> +				      &ready);
> +	} while (!ready);
> +	glGetQueryObjectuivARB(id, GL_QUERY_RESULT_ARB, &passed);
> +
> +	/* 'passed' should be zero */
> +	return passed > 0 ? false : true;
> +}
> +
> +/* If mutiple queries are issued on the same target and diff ids prior
> + * to calling GetQueryObject[u]iVARB, the results should be
> + * corresponding to those queries (ids) respectively.
> + */
> +bool
> +conformOQ_GetObjivAval_multi2(void)
> +{
> +	GLuint passed1 = 0, passed2 = 0, passed3 = 0;
> +	GLuint id1, id2, id3;
> +
> +	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
> +
> +	glMatrixMode(GL_PROJECTION);
> +	glPushMatrix();
> +	glLoadIdentity();
> +	glOrtho(-1.0, 1.0, -1.0, 1.0, 0.0, 25.0);
> +
> +	glMatrixMode(GL_MODELVIEW);
> +	glPushMatrix();
> +	glLoadIdentity();
> +	glTranslatef(0.0, 0.0, -10.0);
> +
> +
> +	/* draw the occluder (red) */
> +	glColorMask(1, 1, 1, 1);
> +	glDepthMask(GL_TRUE);
> +	glColor3f(1, 0, 0);
> +	gen_box(-0.5, 0.5, 0.5, -0.5);
> +
> +	glPushMatrix();
> +	glTranslatef(0.0, 0.0, -5.0);
> +	glColorMask(0, 0, 0, 0);
> +	glDepthMask(GL_FALSE);
> +
> +	id1 = find_unused_id();
> +	START_QUERY(id1);
> +	/* draw green quad, much larger than occluder */
> +	glColor3f(0, 1, 0);
> +	gen_box(-0.7, 0.7, 0.7, -0.7);
> +	TERM_QUERY();
> +
> +	id2 = find_unused_id();
> +	START_QUERY(id2);
> +	/* draw blue quad, slightly larger than occluder */
> +	glColor3f(0, 0, 1);
> +	gen_box(-0.53, 0.53, 0.53, -0.53);
> +	TERM_QUERY();
> +
> +	id3 = find_unused_id();
> +	START_QUERY(id3);
> +	/* draw white quad, smaller than occluder (should not be visible) */
> +	glColor3f(1, 1, 1);
> +	gen_box(-0.4, 0.4, 0.4, -0.4);
> +	TERM_QUERY();
> +
> +	glPopMatrix();
> +
> +	glGetQueryObjectuivARB(id1, GL_QUERY_RESULT_ARB, &passed1);
> +	glGetQueryObjectuivARB(id2, GL_QUERY_RESULT_ARB, &passed2);
> +	glGetQueryObjectuivARB(id3, GL_QUERY_RESULT_ARB, &passed3);
> +
> +	glDepthMask(GL_TRUE);
> +
> +
> +	glDeleteQueriesARB(1, &id1);
> +	glDeleteQueriesARB(1, &id2);
> +	glDeleteQueriesARB(1, &id3);
> +
> +	glPopMatrix();
> +	glMatrixMode(GL_PROJECTION);
> +	glPopMatrix();
> +
> +	if (passed1 > passed2 && passed2 > passed3 && passed3 == 0)
> +		return true;
> +	else
> +		return false;
> +}
> +
> +/*
> + * void GetQueryivARB(enum target, enum pname, int *params);
> + *
> + * If <pname> is QUERY_COUNTER_BITS_ARB, the number of bits in the counter
> + * for <target> will be placed in <params>.  The minimum number of query
> + * counter bits allowed is a function of the implementation's maximum
> + * viewport dimensions (MAX_VIEWPORT_DIMS).  If the counter is non-zero,
> + * then the counter must be able to represent at least two overdraws for
> + * every pixel in the viewport using only one sample buffer.  The formula to
> + * compute the allowable minimum value is below (where n is the minimum
> + * number of bits):
> + *   n = (min (32, ceil (log2 (maxViewportWidth x maxViewportHeight x 2) ) ) ) or 0
> + */
> +bool
> +conformOQ_GetQry_CnterBit(void)
> +{
> +	int bit_num, dims[2];
> +	GLenum err;
> +	float min_impl, min_bit_num;
> +
> +	/* get the minimum bit number supported by the implementation,
> +	 * and check the legality of result of GL_QUERY_COUNTER_BITS_ARB
> +	 */
> +	glGetQueryivARB(GL_SAMPLES_PASSED_ARB, GL_QUERY_COUNTER_BITS_ARB,
> +			&bit_num);
> +	glGetIntegerv(GL_MAX_VIEWPORT_DIMS, dims);
> +	err = glGetError();
> +	if (err == GL_INVALID_OPERATION || err == GL_INVALID_ENUM)
> +		return false;
> +
> +	min_impl =
> +		ceil(logf((float) dims[0] * (float) dims[1] * 1.0 * 2.0) /
> +		     logf(2.0));
> +	min_bit_num = 32.0 > min_impl ? min_impl : 32.0;
> +
> +	if ((float) bit_num < min_bit_num)
> +		return false;
> +
> +	return true;
> +}
> +
> +/* If BeginQueryARB is called with an unused <id>, that name is marked as used
> + * and associated with a new query object.
> + */
> +bool
> +conformOQ_Begin_unused_id(void)
> +{
> +	unsigned int id;
> +	bool pass = true;
> +
> +	id = find_unused_id();
> +
> +	if (id == 0)
> +		return false;
> +
> +	glBeginQuery(GL_SAMPLES_PASSED_ARB, id);
> +
> +	if (glIsQueryARB(id) == GL_FALSE) {
> +		printf("Error : Begin with a unused id failed.");
> +		pass = false;
> +	}
> +
> +	glEndQuery(GL_SAMPLES_PASSED_ARB);
> +
> +	return pass;
> +}
> +
> +/* if EndQueryARB is called while no query with the same target is in progress,
> + * an INVALID_OPERATION error is generated.
> + */
> +bool
> +conformOQ_EndAfter(GLuint id)
> +{
> +	START_QUERY(id);
> +	TERM_QUERY();
> +
> +	glEndQueryARB(GL_SAMPLES_PASSED_ARB);
> +
> +	piglit_check_gl_error();
> +
> +	return true;
> +}
> +
> +/* Calling either GenQueriesARB while any query of any target is active
> + * should not cause any error to be generated.
> + */
> +bool
> +conformOQ_GenIn(GLuint id)
> +{
> +	int pass = true;
> +
> +	START_QUERY(id);
> +
> +	glGenQueriesARB(1, &id);
> +	if (glGetError() != GL_NO_ERROR) {

piglit_check_gl_error()


> +		printf(" Error: Error generated when GenQueries called "
> +		       "in the progress of another.\n");
> +		pass = false;
> +	}
> +
> +	TERM_QUERY();
> +
> +	return pass;
> +}
> +
> +/* Calling either DeleteQueriesARB while any query of any target is active
> + * should not cause any error to be generated.
> + */
> +bool
> +conformOQ_DeleteIn(GLuint id)
> +{
> +	int pass = true;
> +	unsigned int another_id;
> +
> +	START_QUERY(id);
> +
> +	if (id > 0) {
> +		glGenQueriesARB(1, &another_id);
> +		glDeleteQueriesARB(1, &another_id);
> +
> +		piglit_check_gl_error();
> +	}
> +
> +	TERM_QUERY();
> +
> +	return pass;
> +}
> +
> +/* If BeginQueryARB is called while another query is already in progress with
> + * the same target, an INVALID_OPERATION error should be generated.
> + */
> +bool
> +conformOQ_BeginIn(GLuint id)
> +{
> +	int pass = true;
> +
> +	START_QUERY(id);
> +
> +	/* Issue another BeginQueryARB while another query is already in progress */
> +	glBeginQueryARB(GL_SAMPLES_PASSED_ARB, id);
> +
> +	piglit_check_gl_error();
> +
> +	TERM_QUERY();
> +	return pass;
> +}
> +
> +/* if the query object named by <id> is currently active, then an
> + * INVALID_OPERATION error is generated.
> + */
> +bool
> +conformOQ_GetObjAvalIn(GLuint id)
> +{
> +	int pass = true;
> +	GLint param;
> +
> +	START_QUERY(id);
> +
> +	glGetQueryObjectivARB(id, GL_QUERY_RESULT_AVAILABLE_ARB, &param);
> +	piglit_check_gl_error();
> +
> +	glGetQueryObjectuivARB(id, GL_QUERY_RESULT_AVAILABLE_ARB,
> +			       (GLuint *) & param);
> +	piglit_check_gl_error();

That should be something like:

	if (!piglit_check_gl_error(GL_INVALID_OPERATION)) {
		pass = false;

Similar for all the other calls below.

Didn't you compile the program?  Didn't the compiler show a warning at 
least?


> +
> +	if (pass == false) {
> +		printf(" Error: No GL_INVALID_OPERATION generated if "
> +		       "GetQueryObjectuiv with GL_QUERY_RESULT_AVAILABLE_ARB "
> +		       "in the active progress.\n");
> +	}
> +
> +	TERM_QUERY();
> +
> +	return pass;
> +}
> +
> +/* if the query object named by <id> is currently active, then an
> + * INVALID_OPERATION error is generated. */
> +bool
> +conformOQ_GetObjResultIn(GLuint id)
> +{
> +	int pass = true;
> +	GLint param;
> +
> +	START_QUERY(id);
> +
> +	glGetQueryObjectivARB(id, GL_QUERY_RESULT_ARB, &param);
> +	piglit_check_gl_error();
> +
> +	glGetQueryObjectuivARB(id, GL_QUERY_RESULT_ARB, (GLuint *) & param);
> +	piglit_check_gl_error();
> +
> +	if (pass == false) {
> +		printf(" Error: No GL_INVALID_OPERATION generated if "
> +		       "GetQueryObject[u]iv with GL_QUERY_RESULT_ARB "
> +		       "in the active progress.\n");
> +	}
> +	TERM_QUERY();
> +
> +	return pass;
> +}
> +
> +/* If <id> is not the name of a query object, then an INVALID_OPERATION error
> + * is generated.
> + */
> +bool
> +conformOQ_GetObjivAval(GLuint id)
> +{
> +	GLuint id_tmp;
> +	GLint param;
> +
> +	START_QUERY(id);
> +	TERM_QUERY();
> +
> +	id_tmp = find_unused_id();
> +
> +	if (id_tmp == 0)
> +		return false;
> +
> +	glGetQueryObjectivARB(id_tmp, GL_QUERY_RESULT_AVAILABLE_ARB, &param);
> +
> +	piglit_check_gl_error();
> +
> +	return true;
> +}
> +
> +/* Basic tests on query id generation and deletion */
> +bool
> +conformOQ_Gen_Delete(unsigned int id_n)
> +{
> +	GLuint *ids1 = NULL, *ids2 = NULL;
> +	unsigned int i, j;
> +	bool pass = true;
> +
> +	ids1 = (GLuint *) malloc(id_n * sizeof(GLuint));
> +	ids2 = (GLuint *) malloc(id_n * sizeof(GLuint));
> +
> +	if (!ids1 || !ids2) {
> +		printf(" Error: Cannot alloc memory to pointer ids[12].\n");
> +		if (ids1)
> +			free(ids1);
> +		if (ids2)
> +			free(ids2);
> +		return false;
> +	}
> +
> +	glGenQueriesARB(id_n, ids1);
> +	glGenQueriesARB(id_n, ids2);
> +
> +	/* compare whether <id> generated during the previous 2 rounds are
> +	 * duplicated */
> +	for (i = 0; i < id_n; i++) {
> +		for (j = 0; j < id_n; j++) {
> +			if (ids1[i] == ids2[j]) {
> +				char str[1000];
> +				sprintf(str, "ids1[%d] == ids2[%d] == %u.", i,
> +					j, ids1[i]);
> +				printf(" Error:  %s\n", str);
> +				pass = false;
> +			}
> +		}
> +	}
> +
> +	/* Note: the spec seems to indicate that glGenQueries reserves query
> +	 * IDs but doesn't create query objects for those IDs.  A query object
> +	 * isn't created until they are used by glBeginQuery.  So this part
> +	 * of the test is invalid.
> +	 */
> +#if 0
> +	/* Checkout whether the Query ID just generated is valid */
> +	for (i = 0; i < id_n; i++) {
> +		if (glIsQueryARB(ids1[i]) == GL_FALSE) {
> +			char str[1000];
> +			sprintf(str, "id [%d] just generated is not valid.",
> +				ids1[i]);
> +			printf(" Error: %s\n", str);
> +			pass = false;
> +		}
> +	}
> +#endif
> +
> +	/* if <id> is a non-zero value that is not the name of a query object,
> +	 * IsQueryARB returns FALSE.
> +	 */
> +	glDeleteQueriesARB(id_n, ids1);
> +	for (i = 0; i < id_n; i++) {
> +		if (glIsQueryARB(ids1[i]) == GL_TRUE) {
> +			char str[1000];
> +			sprintf(str, "id [%d] just deleted is still valid.",
> +				ids1[i]);
> +			printf(" Error: %s\n", str);
> +			pass = false;
> +		}
> +	}
> +
> +	/* Delete only for sanity purpose */
> +	glDeleteQueriesARB(id_n, ids2);
> +
> +	if (ids1)
> +		free(ids1);
> +	if (ids2)
> +		free(ids2);
> +
> +
> +	ids1 = (GLuint *) malloc(id_n * sizeof(GLuint));
> +	if (ids1 == NULL)
> +		return false;
> +
> +	for (i = 0; i < id_n; i++) {
> +		glGenQueriesARB(1, ids1 + i);
> +		for (j = 0; j < i; j++) {
> +			if (ids1[i] == ids1[j]) {
> +				char str[1000];
> +				sprintf(str, "duplicated id generated [%u]",
> +					ids1[i]);
> +				printf(" Error: %s\n", str);
> +				pass = false;
> +			}
> +		}
> +	}
> +
> +	glDeleteQueriesARB(id_n, ids1);
> +	if (ids1)
> +		free(ids1);
> +
> +	return pass;
> +}
> +
> +/* If <id> is zero, IsQueryARB should return FALSE.*/
> +bool
> +conformOQ_IsIdZero(void)
> +{
> +	if (glIsQueryARB(0) == GL_TRUE) {
> +		printf(" Error: zero is treated as a valid id by glIsQueryARB().\n");
> +		return false;
> +	}
> +
> +	return true;
> +}
> +
> +/* If BeginQueryARB is called with an <id> of zero, an INVALID_OPERATION error
> + * should be generated.
> + */
> +bool
> +conformOQ_BeginIdZero(void)
> +{
> +	glBeginQueryARB(GL_SAMPLES_PASSED_ARB, 0);
> +	piglit_check_gl_error();
> +
> +	return true;
> +}
> +
> +void
> +piglit_init(int argc, char **argv)
> +{
> +	glClearColor(0.0, 0.2, 0.3, 0.0);
> +	glClearDepth(1.0);
> +
> +	glEnable(GL_DEPTH_TEST);
> +	glDepthFunc(GL_LESS);
> +
> +	piglit_require_extension("GL_ARB_occlusion_query");
> +	piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE);
> +	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
> +}
> +
> +enum piglit_result
> +piglit_display(void)
> +{
> +	bool pass = true;
> +	GLuint queryId;
> +
> +	glEnable(GL_DEPTH_TEST);
> +	glGenQueriesARB(1, &queryId);
> +
> +	if (queryId == 0)
> +		return PIGLIT_FAIL;
> +
> +	pass = conformOQ_GetQry_CnterBit() && pass;

All the following lines should use the style of the line above.


> +	pass &= conformOQ_GetObjivAval_multi1(queryId);
> +	pass &= conformOQ_GetObjivAval_multi2();
> +	pass &= conformOQ_Begin_unused_id();
> +	pass &= conformOQ_EndAfter(queryId);
> +	pass &= conformOQ_GenIn(queryId);
> +	pass &= conformOQ_BeginIn(queryId);
> +	pass &= conformOQ_DeleteIn(queryId);
> +	pass &= conformOQ_GetObjAvalIn(queryId);
> +	pass &= conformOQ_GetObjResultIn(queryId);
> +	pass &= conformOQ_GetObjivAval(queryId);
> +	pass &= conformOQ_Gen_Delete(64);
> +	pass &= conformOQ_IsIdZero();
> +	pass &= conformOQ_BeginIdZero();
> +	glDeleteQueriesARB(1, &queryId);
> +
> +	piglit_present_results();
> +
> +	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
> +}
>



More information about the Piglit mailing list