Beispiel #1
0
/**
 * Create two textures with different reference values. Draw both of
 * the textures to the framebuffer and save the reference images with
 * glReadPixels.
 *
 * Loop:
 *  - Create another texture with the same initial values as the first
 *    texture
 *  - replace a random sub-region of the texture image with values from
 *    the 2nd texture
 *  - draw the texture to the framebuffer and read back with glReadPixels
 *  - compare reference images to test image choosing either the first
 *    or second reference image for each pixel depending on whether it
 *    is within the updated region
 * \param target  GL_TEXTURE_1D/2D/3D
 * \param intFormat  the internal texture format
 */
static GLboolean
test_format(GLenum target, GLenum intFormat)
{
	const GLenum srcFormat = GL_RGBA;
	GLuint w = DEFAULT_TEX_WIDTH;
	GLuint h = DEFAULT_TEX_HEIGHT;
	GLuint d = DEFAULT_TEX_DEPTH;
	GLuint tex, i, j, k, n, t;
	GLubyte *original_img, *original_ref;
	GLubyte *updated_img, *updated_ref;
	GLubyte *testImg;
	GLboolean pass = GL_TRUE;
	GLuint bw, bh, bb, wMask, hMask, dMask;
	GLuint pbo = 0;
	piglit_get_compressed_block_size(intFormat, &bw, &bh, &bb);
	wMask = ~(bw-1);
	hMask = ~(bh-1);
	dMask = ~0;

	if (target == GL_TEXTURE_CUBE_MAP_ARRAY_ARB) {
		w = h;
		d *= 6;
	} else if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY) {
		d = 1;
	}

	if (target == GL_TEXTURE_1D)
		h = 1;

	original_img = (GLubyte *) malloc(w * h * d * 4);
	original_ref = (GLubyte *) malloc(w * h * d * 4);
	updated_img = (GLubyte *) malloc(w * h * d * 4);
	updated_ref = (GLubyte *) malloc(w * h * d * 4);
	testImg = (GLubyte *) malloc(w * h * d * 4);

	/* fill source tex images */
	n = 0;
	for (i = 0; i < d; i++) {
		for (j = 0; j < h; j++) {
			for (k = 0; k < w; k++) {
				original_img[n + 0] = j * 4;
				original_img[n + 1] = k * 2;
				original_img[n + 2] = i * 128 / d;
				original_img[n + 3] = 255;

				/* Swizzle the components in the
				 * updated image
				 */
				updated_img[n + 0] = original_img[n + 1];
				updated_img[n + 1] = original_img[n + 2];
				updated_img[n + 2] = original_img[n + 0];
				updated_img[n + 3] = original_img[n + 3];

				n += 4;
			}
		}
	}

	if (use_pbo) {
		glGenBuffers(1, &pbo);
		glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
		glBufferData(GL_PIXEL_UNPACK_BUFFER,
			     w * h * d * 4,
			     updated_img,
			     GL_STATIC_DRAW);
		glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
	}

	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);


	/* draw original reference image */
	tex = create_texture(target, intFormat, w, h, d,
			     srcFormat, original_img);
	glClear(GL_COLOR_BUFFER_BIT);
	draw_and_read_texture(w, h, d, original_ref);
	glDeleteTextures(1, &tex);

	/* draw updated reference image */
	tex = create_texture(target, intFormat, w, h, d,
			     srcFormat, updated_img);
	glClear(GL_COLOR_BUFFER_BIT);
	draw_and_read_texture(w, h, d, updated_ref);
	glDeleteTextures(1, &tex);

	for (t = 0; t < 10; t++) {
		/* Choose random region of texture to update.
		 * Use sizes and positions that are multiples of
		 * the compressed block size.
		 */
		GLint tw = (rand() % w) & wMask;
		GLint th = (rand() % h) & hMask;
		GLint td = (rand() % d) & dMask;
		GLint tx = (rand() % (w - tw)) & wMask;
		GLint ty = (rand() % (h - th)) & hMask;
		GLint tz = (rand() % (d - td)) & dMask;

		/* Recreate the original texture */
		tex = create_texture(target, intFormat, w, h, d,
				     srcFormat, original_img);

		assert(tx + tw <= w);
		assert(ty + th <= h);
		assert(tz + td <= d);

		if (use_pbo)
			glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);

		/* replace texture region with data from updated image */
		glPixelStorei(GL_UNPACK_SKIP_PIXELS, tx);
		glPixelStorei(GL_UNPACK_SKIP_ROWS, ty);
		glPixelStorei(GL_UNPACK_SKIP_IMAGES, tz);
		if (d > 1) {
			glTexSubImage3D(target, 0, tx, ty, tz, tw, th, td,
					srcFormat, GL_UNSIGNED_BYTE,
					use_pbo ? NULL : updated_img);
		} else if (h > 1) {
			glTexSubImage2D(target, 0, tx, ty, tw, th,
					srcFormat, GL_UNSIGNED_BYTE,
					use_pbo ? NULL : updated_img);
		} else if (w > 1) {
			glTexSubImage1D(target, 0, tx, tw,
					srcFormat, GL_UNSIGNED_BYTE,
					use_pbo ? NULL : updated_img);
		} else {
			assert(!"Unknown image dimensions");
		}

		if (use_pbo)
			glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);

		/* draw test image */
		glClear(GL_COLOR_BUFFER_BIT);
		draw_and_read_texture(w, h, d, testImg);

		glDeleteTextures(1, &tex);

		piglit_present_results();

		if (!equal_images(target,
				  original_ref, updated_ref, testImg,
				  w, h, d,
				  tx, ty, tz, tw, th, td)) {
			printf("texsubimage failed\n");
			printf("  target: %s\n", piglit_get_gl_enum_name(target));
			printf("  internal format: %s\n", piglit_get_gl_enum_name(intFormat));
			printf("  region: %d, %d  %d x %d\n", tx, ty, tw, th);
			pass = GL_FALSE;
			break;
		}
	}

	free(original_img);
	free(original_ref);
	free(updated_img);
	free(updated_ref);
	free(testImg);
	if (use_pbo)
		glDeleteBuffers(1, &pbo);

	return pass;
}
enum piglit_result
piglit_display(void)
{
	GLuint tex, tex_src;
	bool pass;
	int level;
	unsigned bw, bh, bs;

	piglit_get_compressed_block_size(format->token, &bw, &bh, &bs);
	glClearColor(0.5, 0.5, 0.5, 0.5);
	glClear(GL_COLOR_BUFFER_BIT);

	tex_src = piglit_rgbw_texture(format->token, SIZE, SIZE,
				      true, false,
				      GL_UNSIGNED_NORMALIZED);
	glCreateTextures(GL_TEXTURE_2D, 1, &tex);

	for (level = 0; (SIZE >> level) > 0; level++) {
		int w, h;
		int expected_size, size;
		void *compressed;

		w = SIZE >> level;
		h = SIZE >> level;
		expected_size = piglit_compressed_image_size(format->token, w, h);

		glBindTexture(GL_TEXTURE_2D, tex_src);
		glGetTexLevelParameteriv(GL_TEXTURE_2D, level,
					 GL_TEXTURE_COMPRESSED_IMAGE_SIZE,
					 &size);

		if (size != expected_size) {
			fprintf(stderr, "Format %s level %d (%dx%d) size %d "
				"doesn't match expected size %d\n",
				piglit_get_gl_enum_name(format->token),
				level, w, h, size, expected_size);
			piglit_report_result(PIGLIT_FAIL);
		}

		compressed = malloc(size);

		glGetCompressedTextureImage(tex_src, level, size, compressed);

		glBindTexture(GL_TEXTURE_2D, tex);
		glCompressedTexImage2D(GL_TEXTURE_2D, level, format->token,
				       w, h, 0, size, compressed);
		if (!piglit_check_gl_error(GL_NO_ERROR))
			piglit_report_result(PIGLIT_FAIL);

		free(compressed);
	}

	glDeleteTextures(1, &tex_src);
	glBindTextureUnit(tex, 0);

	display_mipmaps(10, 10);
	pass = check_resulting_mipmaps(10, 10);

	piglit_present_results();

	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
}