/*
 * Copyright © 2011 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.
 */

#include "piglit-util-gl.h"

PIGLIT_GL_TEST_CONFIG_BEGIN

	config.supports_gl_es_version = 10;

	config.window_width = 100;
	config.window_height = 100;
	config.window_visual = PIGLIT_GL_VISUAL_RGB | PIGLIT_GL_VISUAL_DOUBLE;

PIGLIT_GL_TEST_CONFIG_END

struct test_vector {
	GLenum internal_format;
	GLenum format;
	GLenum type;
	unsigned shift;
	unsigned palette_size;
};

static const struct test_vector t[] = {
	{ GL_PALETTE4_RGB8_OES,     GL_RGB,  GL_UNSIGNED_BYTE, 1, 3 * 16 },
	{ GL_PALETTE4_RGBA8_OES,    GL_RGBA, GL_UNSIGNED_BYTE, 1, 4 * 16 },
	{ GL_PALETTE4_R5_G6_B5_OES, GL_RGB,  GL_UNSIGNED_BYTE, 1, 2 * 16 },
	{ GL_PALETTE4_RGBA4_OES,    GL_RGBA, GL_UNSIGNED_BYTE, 1, 2 * 16 },
	{ GL_PALETTE4_RGB5_A1_OES,  GL_RGBA, GL_UNSIGNED_BYTE, 1, 2 * 16 },
	{ GL_PALETTE8_RGB8_OES,     GL_RGB,  GL_UNSIGNED_BYTE, 0, 3 * 256 },
	{ GL_PALETTE8_RGBA8_OES,    GL_RGBA, GL_UNSIGNED_BYTE, 0, 4 * 256 },
	{ GL_PALETTE8_R5_G6_B5_OES, GL_RGB,  GL_UNSIGNED_BYTE, 0, 2 * 256 },
	{ GL_PALETTE8_RGBA4_OES,    GL_RGBA, GL_UNSIGNED_BYTE, 0, 2 * 256 },
	{ GL_PALETTE8_RGB5_A1_OES,  GL_RGBA, GL_UNSIGNED_BYTE, 0, 2 * 256 },
};

enum piglit_result
piglit_display(void)
{
	return PIGLIT_FAIL;
}

void
piglit_init(int argc, char **argv)
{
	GLubyte buffer[512 + (16 * 16)];
	GLuint tex;
	GLsizei size;
	unsigned i;

	piglit_require_extension("GL_OES_compressed_paletted_texture");

	glGenTextures(1, &tex);
	glBindTexture(GL_TEXTURE_2D, tex);

	/* The OES_compressed_paletted_texture spec says:
	 *
	 *     "INVALID_OPERATION is generated by TexImage2D,
	 *     CompressedTexSubImage2D, CopyTexSubImage2D if <internalformat>
	 *     is PALETTE4_RGB8_OES, PALETTE4_RGBA8_OES,
	 *     PALETTE4_R5_G6_B5_OES, PALETTE4_RGBA4_OES,
	 *     PALETTE4_RGB5_A1_OES, PALETTE8_RG8_OES, PALETTE8_RGBA8_OES,
	 *     PALETTE8_R5_G6_B5_OES, PALETTE8_RGBA4_OES, or
	 *     PALETTE8_RGB5_A1_OES."
	 *
	 * However, page 73 (page 83 of the PDF) of the OpenGL ES 1.1
	 * spec says:
	 *
	 *     "Specifying a value for internalformat that is not one of the
	 *     above values generates the error INVALID_VALUE. If
	 *     internalformat does not match format, the error
	 *     INVALID_OPERATION is generated."
	 *
	 * The OES_compressed_paletted_texture spec doesn't add any entries to
	 * table 3.8.  It seems logical to expect the core behavior to take
	 * precedence over the extension error.
	 */
	printf("Trying glTexImage2D...\n");
	for (i = 0; i < ARRAY_SIZE(t); i++) {
		glTexImage2D(GL_TEXTURE_2D, 0, t[i].internal_format,
			     16, 16, 0,
			     t[i].internal_format, t[i].type, buffer);
#if defined(PIGLIT_USE_OPENGL_ES1) || defined(PIGLIT_USE_OPENGL_ES2)
		{
			GLenum error = glGetError();
			if (error != GL_INVALID_VALUE && error != GL_INVALID_OPERATION) {
				printf("Unexpected GL error: %s 0x%x\n",
				       piglit_get_gl_error_name(error), error);
				printf("(Error at %s:%u)\n", __func__, __LINE__);
				printf("Expected GL error: %s 0x%x or %s 0x%x\n",
				       piglit_get_gl_error_name(GL_INVALID_VALUE), GL_INVALID_VALUE,
				       piglit_get_gl_error_name(GL_INVALID_OPERATION), GL_INVALID_OPERATION);
				piglit_report_result(PIGLIT_FAIL);
			}
		}
#else
		if (!piglit_check_gl_error(GL_INVALID_OPERATION))
			piglit_report_result(PIGLIT_FAIL);
#endif
	}


	printf("Trying glCompressedTexImage2D...\n");
	for (i = 0; i < ARRAY_SIZE(t); i++) {
		size = (16 * 16) >> t[i].shift;

		/* The GL_ARB_texture_compression spec says:
		 *
		 *     "If the <imageSize> parameter is not consistent with
		 *     the format, dimensions, and contents of the compressed
		 *     image, an INVALID_VALUE error results."
		 */
		glCompressedTexImage2D(GL_TEXTURE_2D, 0, t[i].internal_format,
					  16, 16, 0,
					  size + t[i].palette_size - 1, buffer);
		if (!piglit_check_gl_error(GL_INVALID_VALUE))
			piglit_report_result(PIGLIT_FAIL);

		glCompressedTexImage2D(GL_TEXTURE_2D, 0, t[i].internal_format,
					  16, 16, 0,
					  size + t[i].palette_size, buffer);
		if (!piglit_check_gl_error(GL_NO_ERROR))
			piglit_report_result(PIGLIT_FAIL);

		/* The OES_compressed_paletted_texture spec says:
		 *
		 *     "INVALID_VALUE is generated by CompressedTexImage2D if
		 *     if <internalformat> is PALETTE4_RGB8_OES,
		 *     PALETTE4_RGBA8_OES, PALETTE4_R5_G6_B5_OES,
		 *     PALETTE4_RGBA4_OES, PALETTE4_RGB5_A1_OES,
		 *     PALETTE8_RGB8_OES, PALETTE8_RGBA8_OES,
		 *     PALETTE8_R5_G6_B5_OES, PALETTE8_RGBA4_OES, or
		 *     PALETTE8_RGB5_A1_OES and <level> value is neither zero
		 *     or a negative value."
		 */
		size = (8 * 8) >> t[i].shift;
		glCompressedTexImage2D(GL_TEXTURE_2D, 1, t[i].internal_format,
				       8, 8, 0,
				       size + t[i].palette_size, buffer);
		if (!piglit_check_gl_error(GL_INVALID_VALUE))
			piglit_report_result(PIGLIT_FAIL);

		/* The OES_compressed_paletted_texture spec says:
		 *
		 *     "Compressed paletted textures support only 2D images
		 *     without borders. CompressedTexImage2D will produce an
		 *     INVALID_OPERATION error if <border> is non-zero."
		 *
		 * However, page 74 (page 84 of the PDF) of the OpenGL ES 1.1
		 * spec says:
		 *
		 *     "If the border argument to TexImage2D is not zero, then
		 *     the error INVALID_VALUE is generated."
		 *
		 * Even though this is for glTexImage2D, page 78 (page 88 of
		 * the PDF) of the OpenGL ES 1.1 spec says:
		 *
		 *     "The target, level, internalformat, width, height, and
		 *     border parameters have the same meaning as in
		 *     TexImage2D."
		 *
		 * It seems logical to expect the core behavior to take
		 * precedence over the extension error.
		 */
		size = (17 * 17) >> t[i].shift;
		glCompressedTexImage2D(GL_TEXTURE_2D, 0, t[i].internal_format,
				       16, 16, 1,
				       size + t[i].palette_size, buffer);
#if defined(PIGLIT_USE_OPENGL_ES1) || defined(PIGLIT_USE_OPENGL_ES2)
		if (!piglit_check_gl_error(GL_INVALID_VALUE))
			piglit_report_result(PIGLIT_FAIL);
#else
		if (!piglit_check_gl_error(GL_INVALID_OPERATION))
			piglit_report_result(PIGLIT_FAIL);
#endif
	}

	printf("Done.\n");
	piglit_report_result(PIGLIT_PASS);
}
