static bool
try_TexImage(GLenum internalFormat)
{
	bool pass = true;
	GLuint tex[4];

	GLenum expected_error = has_depth_texture
		? GL_NO_ERROR : GL_INVALID_VALUE;
	GLenum alt_error = GL_NO_ERROR;

	GLenum expected_3D_error = has_depth_texture
		? GL_INVALID_OPERATION : GL_INVALID_VALUE;
	GLenum alt_3D_error = GL_NO_ERROR;

	GLenum expected_cube_error = has_depth_texture_cube_map
		? GL_NO_ERROR : expected_3D_error;
	GLenum alt_cube_error = GL_NO_ERROR;

#if !defined PIGLIT_USE_OPENGL
	/* The OpenGL ES rules are non-obvious.
	 *
	 * In OpenGL ES 1.x and 2.x, the internal format and the format must
	 * be the same.  This even applies in OpenGL ES 2.0 when
	 * GL_OES_depth_texture is available.
	 *
	 * Section 3.7.1 (Texture Image Specification) of the OpenGL ES 1.1.12
	 * spec says:
	 *
	 *     "If internalformat does not match format, the error
	 *     INVALID_OPERATION is generated."
	 *
	 * Section 3.7.1 (Texture Image Specification) of the OpenGL ES 2.0.25
	 * spec says the same thing.
	 *
	 * As a result, in OpenGL ES 1.x or OpenGL ES 2.0 without
	 * GL_OES_depth_texture, glTexImage2D(..., GL_DEPTH24_STENCIL8, ...,
	 * GL_DEPTH_STENCIL, FLOAT_32_UNSIGNED_INT_24_8) may generate *either*
	 * GL_INVALID_VALUE or GL_INVALID_OPERATION depending on the order the
	 * implementation checks the errors.
	 *
	 * In OpenGL ES 3.0, the internal format must not be GL_DEPTH_STENCIL.
	 * Section 3.8.3 (Texture Image Specification) of the OpenGL ES 3.0.3
	 * spec says:
	 *
	 *     "Specifying a combination of values for format, type, and
	 *     internalformat that is not listed as a valid combination in
	 *     tables 3.2 or 3.3 generates the error INVALID_OPERATION."
	 *
	 * Table 3.2 contains the lines:
	 *
	 *     Format         Type                     External   Internal
	 *                                             Bytes      Format
	 *                                             Per Pixel
	 *     DEPTH_STENCIL  UNSIGNED_INT_24_8           4       DEPTH24_STENCIL8
	 *     DEPTH_STENCIL  FLOAT_32_UNSIGNED_INT_24_8  8       DEPTH32F_STENCIL8
	 *
	 * The GL_OES_packed_depth_stencil spec still says:
	 *
	 *     "Accepted by the <format> parameter of TexImage2D and
	 *     TexSubImage2D and by the <internalformat> parameter of
	 *     TexImage2D:
	 *
	 *         DEPTH_STENCIL_OES                              0x84F9"
	 *
	 * An OpenGL ES 3.0 implementation that advertises
	 * GL_OES_packed_depth_stencil should accepth both GL_DEPTH_STENCIL
	 * and GL_DEPTH24_STENCIL8 for internalformat.
	 */
	if (has_depth_texture) {
		if ((piglit_get_gl_version() < 30
		     && internalFormat != GL_DEPTH_STENCIL)
		    || (piglit_get_gl_version() >= 30
			&& internalFormat == GL_DEPTH_STENCIL
			&& !piglit_is_extension_supported("GL_OES_packed_depth_stencil"))) {

			expected_error = GL_INVALID_OPERATION;
			alt_error = GL_NO_ERROR;

			/* 3D depth textures are never supported.
			 * GL_INVALID_OPERATION is expected.  That
			 * error is already expected due to the
			 * mismatch of internalformat and format.
			 */
			expected_3D_error = GL_INVALID_OPERATION;
			alt_3D_error = GL_NO_ERROR;

			/* Cube map depth textures are only supported
			 * with GL_OES_depth_texture_cube_map.
			 * Without that extension,
			 * GL_INVALID_OPERATION is expected.  That
			 * error is already expected due to the
			 * mismatch of internalformat and format.
			 */
			expected_cube_error = GL_INVALID_OPERATION;
			alt_cube_error = GL_NO_ERROR;
		} else {
			expected_error = GL_NO_ERROR;
			alt_error = GL_NO_ERROR;

			/* 3D depth textures are never supported.
			 * GL_INVALID_OPERATION is expected.
			 */
			expected_3D_error = GL_INVALID_OPERATION;
			alt_3D_error = GL_NO_ERROR;

			/* Cube map depth textures are only supported
			 * with GL_OES_depth_texture_cube_map.
			 * Without that extension,
			 * GL_INVALID_OPERATION is expected.
			 */
			expected_cube_error = has_depth_texture_cube_map
				? GL_NO_ERROR : GL_INVALID_OPERATION;
			alt_cube_error = GL_NO_ERROR;
		}
	} else {
		assert(piglit_get_gl_version() < 30);

		if (internalFormat != GL_DEPTH_STENCIL) {
			/* For all of the cases either GL_INVALID_VALUE could
			 * be generated due to format being GL_DEPTH_STENCIL
			 * or GL_INVALID_OPERATION could be generated due to
			 * format not being the same as internalformat.
			 */
			expected_error = GL_INVALID_OPERATION;
			alt_error = GL_INVALID_VALUE;

			expected_3D_error = GL_INVALID_OPERATION;
			alt_3D_error = GL_INVALID_VALUE;

			expected_cube_error = GL_INVALID_OPERATION;
			alt_cube_error = GL_INVALID_VALUE;
		} else {
			/* For all of these cases, GL_INVALID_VALUE is the
			 * only acceptable error.  The OpenGL ES 1.x and 2.0
			 * specs make no mention of generating
			 * GL_INVALID_OPERATION for the 3D or cube map cases.
			 */
			expected_error = GL_INVALID_VALUE;
			alt_error = GL_NO_ERROR;

			expected_3D_error = GL_INVALID_VALUE;
			alt_3D_error = GL_NO_ERROR;

			expected_cube_error = GL_INVALID_VALUE;
			alt_cube_error = GL_NO_ERROR;
		}
	}
#endif /* !defined PIGLIT_USE_OPENGL */

	printf("Testing glTexImage with %s...\n",
	       piglit_get_gl_enum_name(internalFormat));

	glGenTextures(ARRAY_SIZE(tex), tex);

#if defined PIGLIT_USE_OPENGL
	glBindTexture(GL_TEXTURE_1D, tex[0]);
	glTexImage1D(GL_TEXTURE_1D, 0, internalFormat,
		     16, 0,
		     GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL);
	pass = check_gl_error2(expected_error, alt_error) && pass;
#endif

	glBindTexture(GL_TEXTURE_2D, tex[1]);
	glTexImage2D(GL_TEXTURE_2D, 0, internalFormat,
		     16, 16, 0,
		     GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL);
	pass = check_gl_error2(expected_error, alt_error) && pass;


	/* Section 3.8.1 (Texture Image Specification) of the OpenGL 2.1 spec
	 * says:
	 *
	 *     "Textures with a base internal format of DEPTH_COMPONENT are
	 *     supported by texture image specification commands only if
	 *     target is TEXTURE_1D, TEXTURE_2D, PROXY_TEXTURE_1D or
	 *     PROXY_TEXTURE_2D. Using this format in conjunction with any
	 *     other target will result in an INVALID_OPERATION error."
	 *
	 * The OpenGL 4.4 spec lists the same error, but it greatly expands
	 * the list of valid texture targets.
	 */
#if !defined PIGLIT_USE_OPENGL_ES1
	if (has_texture_3d) {
		glBindTexture(GL_TEXTURE_3D, tex[2]);
		glTexImage3D(GL_TEXTURE_3D, 0, internalFormat,
			     8, 8, 8, 0,
			     GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL);
		pass = check_gl_error2(expected_3D_error, alt_3D_error) && pass;
	}
#else
	/* Silence "variable ‘expected_3D_error’ set but not used" warnings.
	 */
	(void) expected_3D_error;
	(void) alt_3D_error;
#endif

	if (has_texture_cube_map) {
		unsigned i;

		glBindTexture(GL_TEXTURE_CUBE_MAP, tex[3]);

		for (i = 0; i < 6; i++) {
			glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i,
				     0, internalFormat,
				     16, 16, 0,
				     GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8,
				     NULL);
			pass = check_gl_error2(expected_cube_error,
					       alt_cube_error)
				&& pass;
		}
	}

#if defined PIGLIT_USE_OPENGL
	glBindTexture(GL_TEXTURE_1D, 0);
#endif
	glBindTexture(GL_TEXTURE_2D, 0);
	if (has_texture_3d)
		glBindTexture(GL_TEXTURE_3D, 0);
	if (has_texture_cube_map)
		glBindTexture(GL_TEXTURE_CUBE_MAP, 0);

	glDeleteTextures(ARRAY_SIZE(tex), tex);

	printf("Done.\n\n");

	return pass;
}
Beispiel #2
0
static bool
test_format(int width, int height, GLfloat *image, GLenum requested_format)
{
	GLubyte *compressed_image;
	GLenum format2;
	int x, y, w, h;
	GLuint tex;
	bool pass = true;
	GLuint expected_size;
	GLint is_compressed;
	GLint compressed_size;
	GLint format;

	glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
	glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
	glPixelStorei(GL_UNPACK_ROW_LENGTH, width);

	/* Setup initial texture */
	glGenTextures(1, &tex);
	glBindTexture(GL_TEXTURE_2D, tex);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexImage2D(GL_TEXTURE_2D, 0, requested_format, width, height, 0,
		     GL_RGBA, GL_FLOAT, image);

	pass = piglit_check_gl_error(GL_NO_ERROR) && pass;
	pass = check_rendering(width, height) && pass;

	glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED,
				 &is_compressed);
	glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT,
				 &format);
	glGetTexLevelParameteriv(GL_TEXTURE_2D, 0,
				 GL_TEXTURE_COMPRESSED_IMAGE_SIZE,
				 &compressed_size);

	pass = piglit_check_gl_error(GL_NO_ERROR) && pass;

	if (!is_compressed) {
		printf("Image was not compressed\n");
		pass = false;
	}

	if (format != requested_format) {
		printf("Internal Format mismatch. Found: 0x%04x Expected: 0x%04x\n",
		       format, requested_format);
		pass = false;
	}

	expected_size = piglit_compressed_image_size(requested_format, width,
			height);

	if (compressed_size != expected_size) {
		printf("Compressed image size mismatch. Found: %u Expected: %u\n",
		       compressed_size, expected_size);
		pass = false;
	}

	/* Use GL_TEXTURE_COMPRESSED_IMAGE_SIZE even if it wasn't what we
	 * expected to avoid corruption due to under-allocated buffer.
	 */
	compressed_image = malloc(compressed_size);

	/* Read back the compressed image data */
	glGetCompressedTexImage(GL_TEXTURE_2D, 0, compressed_image);

	/* Try texsubimage on 4-texel boundary - should work */
	x = 20;
	y = 12;
	w = 16;
	h = 8;
	glPixelStorei(GL_UNPACK_SKIP_PIXELS, x);
	glPixelStorei(GL_UNPACK_SKIP_ROWS, y);
	glTexSubImage2D(GL_TEXTURE_2D, 0,
			x, y, w, h,
			GL_RGBA, GL_FLOAT, image);

	pass = piglit_check_gl_error(GL_NO_ERROR) && pass;
	pass = check_rendering(width, height) && pass;

	/* Try texsubimage on non 4-texel boundary - should not work */
	x = 10;
	y = 11;
	glPixelStorei(GL_UNPACK_SKIP_PIXELS, x);
	glPixelStorei(GL_UNPACK_SKIP_ROWS, y);
	glTexSubImage2D(GL_TEXTURE_2D, 0,
			x, y, w, h,
			GL_RGBA, GL_FLOAT, image);

	pass = piglit_check_gl_error(GL_INVALID_OPERATION) && pass;

	/* Try compressed subimage on 4-texel boundary - should work */
	x = 12;
	y = 8;
	glPixelStorei(GL_UNPACK_SKIP_PIXELS, x);
	glPixelStorei(GL_UNPACK_SKIP_ROWS, y);
	glCompressedTexSubImage2D(GL_TEXTURE_2D, 0,
				  x, y, w, h,
				  format,
				  piglit_compressed_image_size(format, w, h),
				  compressed_image +
				  piglit_compressed_pixel_offset(format, width, x, y));

	pass = piglit_check_gl_error(GL_NO_ERROR) && pass;
	pass = check_rendering(width, height) && pass;

	/* Try compressed subimage on non 4-texel boundary - should not work */
	x = 14;
	y = 9;
	glPixelStorei(GL_UNPACK_SKIP_PIXELS, x);
	glPixelStorei(GL_UNPACK_SKIP_ROWS, y);
	glCompressedTexSubImage2D(GL_TEXTURE_2D, 0,
				  x, y, w, h,
				  format,
				  piglit_compressed_image_size(format, w, h),
				  compressed_image +
				  piglit_compressed_pixel_offset(format, width, 0, 0));

	pass = piglit_check_gl_error(GL_INVALID_OPERATION) && pass;

	/* Try compressed subimage with size not a multiple of 4 -
	 * should not work
	 */
	x = 8;
	y = 8;
	w = 14;
	h = 10;
	glPixelStorei(GL_UNPACK_SKIP_PIXELS, x);
	glPixelStorei(GL_UNPACK_SKIP_ROWS, y);
	glCompressedTexSubImage2D(GL_TEXTURE_2D, 0,
				  x, y, w, h,
				  format,
				  piglit_compressed_image_size(format, 4, 4),
				  compressed_image +
				  piglit_compressed_pixel_offset(format, width, x, y));
	/* Note, we can get either of these errors depending on the order
	 * in which glCompressedTexSubImage parameters are checked.
	 * INVALID_OPERATION for the bad size or INVALID_VALUE for the
	 * wrong compressed image size.
	 */
	pass = check_gl_error2(GL_INVALID_OPERATION, GL_INVALID_VALUE) && pass;

	/* Try compressed subimage with invalid offset - should not work */
	x = -3;
	y = 8;
	w = 4;
	h = 4;
	glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
	glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
	glCompressedTexSubImage2D(GL_TEXTURE_2D, 0,
				  x, y, w, h,
				  format,
				  piglit_compressed_image_size(format, w, h),
				  compressed_image +
				  piglit_compressed_pixel_offset(format, width, 0, 0));

	pass = piglit_check_gl_error(GL_INVALID_VALUE) && pass;

	/* Try compressed subimage with too large of image - should not work */
	x = 16;
	y = 8;
	w = width * 2;
	h = height * 2;
	glPixelStorei(GL_UNPACK_SKIP_PIXELS, x);
	glPixelStorei(GL_UNPACK_SKIP_ROWS, y);
	glCompressedTexSubImage2D(GL_TEXTURE_2D, 0,
				  x, y, w, h,
				  format,
				  piglit_compressed_image_size(format, w, h),
				  compressed_image +
				  piglit_compressed_pixel_offset(format, width, x, y));

	pass = piglit_check_gl_error(GL_INVALID_VALUE) && pass;

	/* Try compressed subimage with different format - should not work */
	if (format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT)
		format2 = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
	else
		format2 = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
	x = 4;
	y = 4;
	w = 4;
	h = 4;
	glPixelStorei(GL_UNPACK_SKIP_PIXELS, x);
	glPixelStorei(GL_UNPACK_SKIP_ROWS, y);
	glCompressedTexSubImage2D(GL_TEXTURE_2D, 0,
				  x, y, w, h,
				  format2,
				  piglit_compressed_image_size(format2, w, h),
				  compressed_image +
				  piglit_compressed_pixel_offset(format2, width, x, y));

	pass = piglit_check_gl_error(GL_INVALID_OPERATION) && pass;

	/* Try zero-sized subimage - should not be an error */
	x = 4;
	y = 4;
	w = 0;
	h = 0;
	glPixelStorei(GL_UNPACK_SKIP_PIXELS, x);
	glPixelStorei(GL_UNPACK_SKIP_ROWS, y);
	glCompressedTexSubImage2D(GL_TEXTURE_2D, 0,
				  x, y, w, h,
				  format,
				  piglit_compressed_image_size(format, w, h),
				  compressed_image +
				  piglit_compressed_pixel_offset(format, width, x, y));

	pass = piglit_check_gl_error(GL_NO_ERROR) && pass;


	/* Try CompressedTexSubImage into level 1 (which is missing) */
	x = 0;
	y = 0;
	w = 4;
	h = 4;
	glPixelStorei(GL_UNPACK_SKIP_PIXELS, x);
	glPixelStorei(GL_UNPACK_SKIP_ROWS, y);
	glCompressedTexSubImage2D(GL_TEXTURE_2D, 1,
				  x, y, w, h,
				  format,
				  piglit_compressed_image_size(format, w, h),
				  compressed_image +
				  piglit_compressed_pixel_offset(format, width, x, y));

	pass = piglit_check_gl_error(GL_INVALID_OPERATION) && pass;

	/* Try CompressedTexImage of size zero - should not be an erorr */
	w = 0;
	h = 0;
	glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0,
			       piglit_compressed_image_size(format, w, h),
			       compressed_image);

	pass = piglit_check_gl_error(GL_NO_ERROR) && pass;

	/* Try CompressedTexImage with size which is a not a multiple of the
         * block size - should not be an erorr
         */
	w = width - 1;
	h = height - 1;
	glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0,
			       piglit_compressed_image_size(format, w, h),
			       compressed_image);

	pass = piglit_check_gl_error(GL_NO_ERROR) && pass;
	pass = check_rendering(width, height) && pass;

	glDeleteTextures(1, &tex);

	free(compressed_image);

	return pass;
}