/** * 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; }