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 <r...@linux.intel.com>
CC: Neil Roberts <n...@linux.intel.com>
Signed-off-by: Chad Versace <chad.vers...@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

_______________________________________________
Piglit mailing list
Piglit@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/piglit

Reply via email to