[Piglit] [PATCH] texturing: Add test unpack-teximage2d
Chad Versace
chad.versace at linux.intel.com
Thu Oct 11 20:13:13 PDT 2012
Add four tests for testing the unpacking state with glTexImage2D.
unpack-teximage2d pbo=0 format=GL_RGBA
unpack-teximage2d pbo=1 format=GL_RGBA
unpack-teximage2d pbo=0 format=GL_BGRA
unpack-teximage2d pbo=1 format=GL_BGRA
The tests randomly explore, with a fixed seed, the correctness of
glTexImage2D over the combinatorial space of pixel unpacking state.
On Intel gen6 with mesa-34c58ac, the RGBA tests pass and the BGRA tests
fail.
CC: Rob Bradford <rob at linux.intel.com>
CC: Neil Roberts <neil at linux.intel.com>
Signed-off-by: Chad Versace <chad.versace at linux.intel.com>
---
tests/all.tests | 5 +
tests/texturing/CMakeLists.gl.txt | 1 +
tests/texturing/unpack-teximage2d.c | 477 ++++++++++++++++++++++++++++++++++++
3 files changed, 483 insertions(+)
create mode 100644 tests/texturing/unpack-teximage2d.c
diff --git a/tests/all.tests b/tests/all.tests
index 964c84c..01b2c5f 100644
--- a/tests/all.tests
+++ b/tests/all.tests
@@ -765,6 +765,11 @@ add_plain_test(texturing, 'texture-al')
add_plain_test(texturing, 'texture-packed-formats')
add_plain_test(texturing, 'texture-rg')
add_plain_test(texturing, 'tex-srgb')
+texturing['unpack-teximage2d pbo=0 format=GL_RGBA'] = concurrent_test(texturing, 'unpack-teximage2d --pbo=0 --format=GL_RGBA')
+texturing['unpack-teximage2d pbo=1 format=GL_RGBA'] = concurrent_test(texturing, 'unpack-teximage2d --pbo=1 --format=GL_RGBA')
+texturing['unpack-teximage2d pbo=0 format=GL_BGRA'] = concurrent_test(texturing, 'unpack-teximage2d --pbo=0 --format=GL_BGRA')
+texturing['unpack-teximage2d pbo=1 format=GL_BGRA'] = concurrent_test(texturing, 'unpack-teximage2d --pbo=1 --format=GL_BGRA')
+add_concurrent_test(texturing, 'unpack-2d --pbo=0 --format=GL_RGBA')
# Note: the buffer sizes of 146, 292, 585, and 1024 hav been chosen to
# exercise all possible combinations of buffer alignments on i965.
diff --git a/tests/texturing/CMakeLists.gl.txt b/tests/texturing/CMakeLists.gl.txt
index 8567fa8..1cbd7b8 100644
--- a/tests/texturing/CMakeLists.gl.txt
+++ b/tests/texturing/CMakeLists.gl.txt
@@ -70,6 +70,7 @@ piglit_add_executable (texrect-many texrect-many.c)
piglit_add_executable (texredefine texredefine.c)
piglit_add_executable (texture-packed-formats texture-packed-formats.c)
piglit_add_executable (texwrap texwrap.c)
+piglit_add_executable (unpack-teximage2d unpack-teximage2d.c)
piglit_add_executable (depth-tex-modes depth-tex-modes.c depth-tex-modes-common.c)
piglit_add_executable (depth-tex-modes-rg depth-tex-modes-rg.c depth-tex-modes-common.c)
piglit_add_executable (depth-tex-modes-glsl depth-tex-modes-glsl.c)
diff --git a/tests/texturing/unpack-teximage2d.c b/tests/texturing/unpack-teximage2d.c
new file mode 100644
index 0000000..ade9f0f
--- /dev/null
+++ b/tests/texturing/unpack-teximage2d.c
@@ -0,0 +1,477 @@
+/*
+ * Copyright © 2012 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.
+ */
+
+/**
+ * \file
+ * \brief Tests pixel unpacking state with glTexImage2D.
+ *
+ * This test randomly explores, with a fixed seed, the correctness of
+ * glTexImage2D over the combinatorial space of pixel unpacking state. In
+ * addition to choosing random unpacking state, the test also chooses random
+ * texture dimensions (the former is not very interesting without the latter).
+ *
+ * There are two pieces of state chosen by command line arguments:
+ * - to upload the texture image from client memory or a pixel buffer
+ * - which texture format to use
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "piglit-util-gl-common.h"
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+
+ config.supports_gl_compat_version = 10;
+
+ config.window_width = 100;
+ config.window_height = 100;
+ config.window_visual = PIGLIT_GL_VISUAL_RGBA;
+
+PIGLIT_GL_TEST_CONFIG_END
+
+static const char *usage_text =
+ "usage:\n"
+ " unpack-teximage2d --pbo=<0|1> --format=<GL_RGBA|GL_BGRA>\n"
+ "\n"
+ "If pbo is 0, then glTexImage2D uploads client memory.\n"
+ "If pbo is 1, then glTexImage2D uploads a pixel buffer object.\n"
+ "\n"
+ "Set env var PIGLIT_DEBUG=1 to print debug info.\n"
+ ;
+
+static int rand_seed = 1;
+static bool use_pbo;
+static GLenum tex_format;
+
+static GLuint tex;
+static GLuint pbo;
+
+/* Assume GL_RGBA or GL_BGRA with GL_UNSIGNED_BYTE. */
+#define PIXEL_SIZE 4
+
+/* TEX_DATA_SIZE is significantly greater than PIXEL_SIZE*MAX_TEX_WIDTH^2 in order to
+ * allow room for GL_UNPACK_SKIP_* and subtest::tex_offset.
+ */
+#define MAX_TEX_WIDTH (1 << 6)
+#define TEX_DATA_SIZE (PIXEL_SIZE * (1 << 16))
+static uint8_t tex_data[TEX_DATA_SIZE];
+
+struct subtest {
+ int tex_width;
+ int tex_height;
+
+ /**
+ * Offset into tex_data or into the pbo.
+ */
+ intptr_t tex_offset;
+
+ /**
+ * See Table 4.5 of the GL 2.1 spec.
+ */
+ struct unpack_state {
+ bool swap_bytes;
+ bool lsb_first;
+ int row_length;
+ int skip_rows;
+ int skip_pixels;
+ int alignment;
+ } unpack;
+};
+
+static void
+usage_error(void)
+{
+ printf("%s", usage_text);
+ piglit_report_result(PIGLIT_FAIL);
+}
+
+static int
+randi(int min, int max)
+{
+ return (double) (max - min) * rand() / RAND_MAX + min;
+}
+
+static void
+logd(const char *format, ...)
+{
+ static int debug = -1;
+ va_list va;
+
+ if (debug == -1) {
+ const char *env = getenv("PIGLIT_DEBUG");
+ if (env == NULL) {
+ debug = 0;
+ } else if (strcmp(env, "0") == 0) {
+ debug = 0;
+ } else if (strcmp(env, "1") == 0) {
+ debug = 1;
+ } else {
+ printf("env var PIGLIT_DEBUG has bad value \"%s\"\n", env);
+ piglit_report_result(PIGLIT_FAIL);
+ }
+ }
+
+ if (debug == 0)
+ return;
+
+ va_start(va, format);
+ printf("piglit: debug: ");
+ vprintf(format, va);
+ va_end(va);
+}
+
+static void
+randomize_subtest(struct subtest *subtest)
+{
+ int row_length;
+
+ subtest->tex_width = randi(1, MAX_TEX_WIDTH);
+ subtest->tex_height = randi(1, MAX_TEX_WIDTH);
+
+ /* Assume that tex_format is GL_RGBA or GL_BGRA. Then tex_offset needs
+ * to be divisible by 4.
+ *
+ * From page 127 (141 of pdf) of the GL 2.1 spec:
+ * If a pixel unpack buffer object is bound and data is not evenly
+ * divisible by the number of basic machine units needed to store
+ * in memory the corresponding GL data type from table 3.5 for the
+ * type parameter, an INVALID OPERATION error results.
+ */
+ subtest->tex_offset = 4 * randi(0, MAX_TEX_WIDTH);
+
+ /* From page 131 (145 of pdf) of the GL 2.1 spec:
+ * If the value of UNPACK ROW LENGTH is not positive, then the
+ * number of groups in a row is width; otherwise the number of
+ * groups is UNPACK ROW LENGTH.
+ */
+ if (rand() % 17 == 0) {
+ subtest->unpack.row_length = 0;
+ row_length = subtest->tex_width;
+ } else {
+ subtest->unpack.row_length = randi(subtest->tex_width,
+ 4 * subtest->tex_width);
+ row_length = subtest->unpack.row_length;
+ }
+
+ subtest->unpack.skip_rows = randi(0, 4 * subtest->tex_height);
+ subtest->unpack.skip_pixels = randi(0, row_length - subtest->tex_width);
+ subtest->unpack.alignment = 1 << randi(0, 3);
+
+ /* This test does not yet support the following unpacking state. */
+ subtest->unpack.lsb_first = false;
+ subtest->unpack.swap_bytes = false;
+
+ /* Indent underneath "subtest %d:\n". */
+ logd(" tex_width: %d\n", subtest->tex_width);
+ logd(" tex_height: %d\n", subtest->tex_height);
+ logd(" tex_offset: %d\n", subtest->tex_offset);
+ logd(" unpack:\n");
+ logd(" row_length: %d\n", subtest->unpack.row_length);
+ logd(" skip_rows: %d\n", subtest->unpack.skip_rows);
+ logd(" skip_pixels: %d\n", subtest->unpack.skip_pixels);
+ logd(" alignment: %d\n", subtest->unpack.alignment);
+ logd(" lsb_first: %d\n", subtest->unpack.lsb_first);
+ logd(" swap_bytes: %d\n", subtest->unpack.swap_bytes);
+}
+
+static void
+set_unpack_state(const struct subtest *subtest)
+{
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, subtest->unpack.swap_bytes);
+ glPixelStorei(GL_UNPACK_LSB_FIRST, subtest->unpack.lsb_first);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, subtest->unpack.row_length);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, subtest->unpack.skip_rows);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, subtest->unpack.skip_pixels);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, subtest->unpack.alignment);
+
+ if (!piglit_check_gl_error(GL_NO_ERROR))
+ piglit_report_result(PIGLIT_FAIL);
+}
+
+static void
+load_tex_data(const struct subtest *subtest)
+{
+ const void *data;
+
+ if (use_pbo)
+ data = NULL;
+ else
+ data = tex_data;
+
+ data += subtest->tex_offset;
+
+ glTexImage2D(GL_TEXTURE_2D,
+ 0 /*level*/,
+ GL_RGBA,
+ subtest->tex_width,
+ subtest->tex_height,
+ 0 /*border*/,
+ tex_format /*format*/,
+ GL_UNSIGNED_BYTE,
+ data);
+
+ if (!piglit_check_gl_error(GL_NO_ERROR))
+ piglit_report_result(PIGLIT_FAIL);
+}
+
+static void
+tex_pixel_to_rgba(const GLubyte *tex_pixel, GLfloat rgba_pixel[4])
+{
+ switch (tex_format) {
+ case GL_RGBA:
+ rgba_pixel[0] = tex_pixel[0] / 255.0;
+ rgba_pixel[1] = tex_pixel[1] / 255.0;
+ rgba_pixel[2] = tex_pixel[2] / 255.0;
+ rgba_pixel[3] = tex_pixel[3] / 255.0;
+ break;
+ case GL_BGRA:
+ rgba_pixel[0] = tex_pixel[2] / 255.0;
+ rgba_pixel[1] = tex_pixel[1] / 255.0;
+ rgba_pixel[2] = tex_pixel[0] / 255.0;
+ rgba_pixel[3] = tex_pixel[3] / 255.0;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+}
+
+static bool
+probe_texels(const struct subtest *subtest)
+{
+ /* The base address of the total image in Figure 3.8 of the GL 2.1
+ * spec.
+ */
+ const void *tex_base;
+
+ /* The texel currently being probed. */
+ int y;
+ int x;
+
+ /* The single-letter variable names below are those found in equations
+ * 3.12 and 3.13 on page 131 (145 of pdf) of the GL 2.1 spec.
+ */
+
+ /* Size of an element, in GLubytes. That is, the number of bytes in
+ * one channel of the pixel. Assume that the texture data type is
+ * GL_UNSIGNED_BYTE.
+ */
+ const int s = 1;
+
+ /* Number of elements in a group. That is, the number of channels in
+ * a pixel. Assume that the texture format is GL_RGBA or GL_BGRA.
+ */
+ const int n = 4;
+
+ const int a = subtest->unpack.alignment;
+
+ /* Row length, in pixels. */
+ int l;
+
+ /* Stride, defined by equation 3.13. */
+ int k;
+
+ /* Location of first element in first row. That is, the base
+ * address of the subimage in Figure 3.8.
+ */
+ const void *p;
+
+ const int pixel_size = n * s;
+
+ /* The test does not yet support the following unpacking state. */
+ assert(!subtest->unpack.swap_bytes);
+ assert(!subtest->unpack.lsb_first);
+
+ tex_base = (const void*) tex_data + subtest->tex_offset;
+
+ /* From page 131 (145 of pdf) of the GL 2.1 spec:
+ * If the value of UNPACK ROW LENGTH is not positive, then the
+ * number of groups in a row is width; otherwise the number of
+ * groups is UNPACK ROW LENGTH.
+ */
+ if (subtest->unpack.row_length <= 0)
+ l = subtest->tex_width;
+ else
+ l = subtest->unpack.row_length;
+
+ for (y = 0; y < subtest->tex_height; ++y) {
+ /* Location of first element in the current row. Defined by equation 3.12. */
+ const void *row_base;
+
+ p = tex_base
+ + pixel_size * l * subtest->unpack.skip_rows
+ + pixel_size * subtest->unpack.skip_pixels;
+
+ /* Equation 3.13 from the GL 2.1 spec.
+ *
+ * This equation does not apply to all texture formats. From
+ * the same page as the equation:
+ * If the number of bits per element is not 1, 2, 4, or
+ * 8 times the number of bits in a GL ubyte, then k = nl
+ * for all values of a.
+ */
+ if (s >= subtest->unpack.alignment) {
+ k = n * l;
+ } else {
+ k = (a / s) * (int) ceilf((float) s * n * l / a);
+ }
+
+ /* Equation 3.12 from the GL 2.1 spec. */
+ row_base = p + y * k;
+
+ for (x = 0; x < subtest->tex_width; ++x) {
+ const int image_x = (double) piglit_width * (x + 0.5) / subtest->tex_width;
+ const int image_y = (double) piglit_height * (y + 0.5) / subtest->tex_height;
+ const GLubyte *tex_pixel = row_base + pixel_size * x;
+ float rgba_pixel[4];
+
+ tex_pixel_to_rgba(tex_pixel, rgba_pixel);
+
+ if (!piglit_probe_pixel_rgba(image_x, image_y,
+ rgba_pixel)) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+static bool
+run_subtest(void)
+{
+ bool pass = true;
+ struct subtest subtest;
+
+ randomize_subtest(&subtest);
+ set_unpack_state(&subtest);
+ load_tex_data(&subtest);
+ glClear(GL_COLOR_BUFFER_BIT);
+ piglit_draw_rect_tex(-1, -1, 2, 2,
+ 0, 0, 1, 1);
+ pass = probe_texels(&subtest);
+ piglit_present_results();
+
+ if (!piglit_check_gl_error(GL_NO_ERROR))
+ piglit_report_result(PIGLIT_FAIL);
+
+ return pass;
+}
+
+static void
+parse_args(int argc, char *argv[])
+{
+ int i;
+
+ bool found_pbo = false;
+ bool found_format = false;
+
+ for (i = 1; i < argc; ++i) {
+ const char *arg = argv[i];
+
+ if (strcmp(arg, "--pbo=0") == 0) {
+ found_pbo = true;
+ use_pbo = false;
+ } else if (strcmp(arg, "--pbo=1") == 0) {
+ found_pbo = true;
+ use_pbo = true;
+ } else if (strcmp(arg, "--format=GL_RGBA") == 0) {
+ found_format = true;
+ tex_format = GL_RGBA;
+ } else if (strcmp(arg, "--format=GL_BGRA") == 0) {
+ found_format= true;
+ tex_format = GL_BGRA;
+ } else if (strncmp(arg, "--seed=", 7) == 0) {
+ rand_seed = strtod(arg + 7, NULL);
+ } else {
+ printf("unrecognized argument: %s\n", arg);
+ usage_error();
+ }
+ }
+
+ if (!found_pbo || !found_format) {
+ usage_error();
+ }
+}
+
+void
+piglit_init(int argc, char *argv[])
+{
+ int i;
+
+ parse_args(argc, argv);
+
+ srand(rand_seed);
+ piglit_require_gl_version(21);
+ glClearColor(0.5, 0.5, 0.5, 1.0);
+
+ glGenTextures(1, &tex);
+ glBindTexture(GL_TEXTURE_2D, tex);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0);
+ glEnable(GL_TEXTURE_2D);
+
+ /* Fill tex_data with random pixels. */
+ for (i = 0; i < TEX_DATA_SIZE; ++i) {
+ if (i % 4 == 3) {
+ /* alpha channel */
+ tex_data[i] = 0xff;
+ } else {
+ /* rgb channels */
+ tex_data[i] = randi(0, 255);
+ }
+ }
+
+ if (use_pbo) {
+ glGenBuffers(1, &pbo);
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
+ glBufferData(GL_PIXEL_UNPACK_BUFFER, TEX_DATA_SIZE, tex_data,
+ GL_STATIC_DRAW);
+ }
+
+ if (!piglit_check_gl_error(GL_NO_ERROR))
+ piglit_report_result(PIGLIT_FAIL);
+}
+
+enum piglit_result
+piglit_display(void)
+{
+ bool pass = true;
+ const int num_subtests = 256;
+ int i;
+
+ /* We reset the random seed for each call to piglit_display() so that
+ * the testrun is consistent.
+ */
+ srand(rand_seed);
+
+ for (i = 0; i < num_subtests; ++i) {
+ logd("subtest %d:\n", i);
+ pass &= run_subtest();
+ }
+
+ return pass ? PIGLIT_PASS : PIGLIT_FAIL;
+}
--
1.7.11.7
More information about the Piglit
mailing list