void
piglit_init(int argc, char **argv)
{
    bool pass = true;
    GLuint tex;
    int i, c;

    if (piglit_get_gl_version() < 30) {
        printf("Requires GL 3.0\n");
        piglit_report_result(PIGLIT_SKIP);
    }

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

    for (i = 0; required_formats[i].token != GL_NONE; i++) {
        GLint sizes[CHANNELS];
        GLint types[CHANNELS];
        bool format_pass = true;
        GLenum format, type;
        const struct sized_internalformat *f;

        /* FINISHME: Add support for future GL versions. */
        if (required_formats[i].version != 30)
            continue;

        f = get_sized_internalformat(required_formats[i].token);

        if (f->token == GL_DEPTH24_STENCIL8 ||
                f->token == GL_DEPTH32F_STENCIL8) {
            format = GL_DEPTH_STENCIL;
            type = GL_UNSIGNED_INT_24_8;
        } else if (get_channel_size(f, D)) {
            format = GL_DEPTH_COMPONENT;
            type = GL_FLOAT;
        } else {
            format = GL_RGBA;
            type = GL_FLOAT;

            /* Have to specify integer data for integer textures. */
            for (c = R; c <= I; c++) {
                if (get_channel_type(f, c) == GL_UNSIGNED_INT ||
                        get_channel_type(f, c) == GL_INT) {
                    format = GL_RGBA_INTEGER;
                    type = GL_UNSIGNED_INT;
                    break;
                }
            }
        }

        glTexImage2D(GL_TEXTURE_2D, 0, f->token,
                     1, 1, 0,
                     format, type, NULL);

        if (glGetError() != 0) {
            printf("Unexpected error creating %s texture\n",
                   f->name);
            pass = false;
            continue;
        }

        for (c = 0; c < CHANNELS; c++) {
            glGetTexLevelParameteriv(GL_TEXTURE_2D, 0,
                                     size_queries[c], &sizes[c]);
            if (c != S) {
                glGetTexLevelParameteriv(GL_TEXTURE_2D, 0,
                                         type_queries[c],
                                         &types[c]);
            } else {
                /* For stencil, there's no query for
                 * the type, so our table above
                 * records a type/size of unorm 8, and
                 * we'll just set the query result
                 * here to unorm so that we only look
                 * at the size.
                 */
                if (sizes[c] != 0)
                    types[c] = GL_UNSIGNED_NORMALIZED;
                else
                    types[c] = GL_NONE;
            }

            /* We use ~0 as the signal for the compressed
             * texture formats.  While the colors being
             * interpolated across the 4x4 blocks have 8
             * bits in them, the spec suggests reporting
             * some approximate value less than that.
             * From page 319 of the GL 3.0 spec:
             *
             *     "Queries of value of TEXTURE RED SIZE,
             *      TEXTURE GREEN SIZE, [...] return the
             *      actual resolutions of the stored image
             *      array components, not the resolutions
             *      specified when the image array was
             *      defined. For texture images with a
             *      compressed internal format, the
             *      resolutions returned specify the
             *      component resolution of an
             *      uncompressed internal format that
             *      produces an image of roughly the same
             *      quality as the compressed image in
             *      question. Since the quality of the
             *      implementation’s compression algorithm
             *      is likely data-dependent, the returned
             *      component sizes should be treated only
             *      as rough approximations.
             */
            if (f->bits[c] == SCMP ||
                    f->bits[c] == UCMP) {
                if (sizes[c] <= 0 || sizes[c] > 8)
                    format_pass = false;
            } else {
                if (sizes[c] != get_channel_size(f, c)) {
                    format_pass = false;
                }
            }

            if (types[c] != get_channel_type(f, c))
                format_pass = false;
        }

        if (!format_pass) {
            printf("format %s:\n",
                   f->name);

            printf("  expected: ");
            for (c = 0; c < CHANNELS; c++) {
                print_bits(get_channel_size(f, c),
                           get_channel_type(f, c));
                printf(" ");
            }
            printf("\n");

            printf("  observed: ");
            for (c = 0; c < CHANNELS; c++) {
                print_bits(sizes[c], types[c]);
                printf(" ");
            }
            printf("\n");

            pass = false;
        }
    }

    glDeleteTextures(1, &tex);

    piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL);
}
void
piglit_init(int argc, char **argv)
{
	bool pass = true;
	GLuint tex, fbo;
	int i, c;

	piglit_require_gl_version(30);

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

	for (i = 0; required_formats[i].token != GL_NONE; i++) {
		GLenum format, type, attachment, status;
		const struct sized_internalformat *f;

		if (!valid_for_gl_version(&required_formats[i], target_version))
			continue;

		if (!required_formats[i].rb_required)
			continue;

		f = get_sized_internalformat(required_formats[i].token);

		if (f->token == GL_DEPTH24_STENCIL8 ||
		    f->token == GL_DEPTH32F_STENCIL8) {
			format = GL_DEPTH_STENCIL;
			type = GL_UNSIGNED_INT_24_8;
			attachment = GL_DEPTH_STENCIL_ATTACHMENT;
		} else if (get_channel_size(f, D)) {
			format = GL_DEPTH_COMPONENT;
			type = GL_FLOAT;
			attachment = GL_DEPTH_ATTACHMENT;
		} else {
			format = GL_RGBA;
			type = GL_FLOAT;
			attachment = GL_COLOR_ATTACHMENT0;

			/* Have to specify integer data for integer textures. */
			for (c = R; c <= I; c++) {
				if (get_channel_type(f, c) == GL_UNSIGNED_INT ||
				    get_channel_type(f, c) == GL_INT) {
					format = GL_RGBA_INTEGER;
					type = GL_UNSIGNED_INT;
					break;
				}
			}
		}

		glTexImage2D(GL_TEXTURE_2D, 0, f->token,
			     1, 1, 0,
			     format, type, NULL);

		if (glGetError() != 0) {
			printf("Unexpected error creating %s texture\n",
			       f->name);
			pass = false;
			continue;
		}

		/* Testing of the sizes/types of the channels is left
		 * up to the required-sized-texture-formats test.
		 */

		glGenFramebuffers(1, &fbo);
		glBindFramebuffer(GL_FRAMEBUFFER, fbo);

		glFramebufferTexture2D(GL_FRAMEBUFFER,
				       attachment,
				       GL_TEXTURE_2D,
				       tex, 0);

		if (glGetError() != 0) {
			printf("Unexpected error binding %s texture\n",
			       f->name);
			pass = false;
			continue;
		}

		if (attachment == GL_COLOR_ATTACHMENT0) {
			glDrawBuffer(GL_COLOR_ATTACHMENT0);
		} else {
			glDrawBuffer(GL_NONE);
		}

		status = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
		if (status != GL_FRAMEBUFFER_COMPLETE) {
			fprintf(stderr, "%s fbo incomplete (status = 0x%04x)\n",
				f->name, status);
			pass = false;
		} else {
			printf("%s: fbo complete\n", f->name);
		}

		glDeleteFramebuffers(1, &fbo);
	}

	glDeleteTextures(1, &tex);

	piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL);
}