On 11/02/2015 05:24 PM, Dave Airlie wrote:
From: Dave Airlie <[email protected]>for every supported target for all the depth/stencil formats this creates a texture, and then uses glGetTexImage to read it back. --- tests/texturing/CMakeLists.gl.txt | 1 + tests/texturing/getteximage-depth.c | 628 ++++++++++++++++++++++++++++++++++++ 2 files changed, 629 insertions(+) create mode 100644 tests/texturing/getteximage-depth.c diff --git a/tests/texturing/CMakeLists.gl.txt b/tests/texturing/CMakeLists.gl.txt index 68afa16..704ea6d 100644 --- a/tests/texturing/CMakeLists.gl.txt +++ b/tests/texturing/CMakeLists.gl.txt @@ -34,6 +34,7 @@ piglit_add_executable (getteximage-formats getteximage-formats.c) piglit_add_executable (getteximage-simple getteximage-simple.c) piglit_add_executable (getteximage-luminance getteximage-luminance.c) piglit_add_executable (getteximage-targets getteximage-targets.c) +piglit_add_executable (getteximage-depth getteximage-depth.c) piglit_add_executable (incomplete-texture incomplete-texture.c) piglit_add_executable (generatemipmap-cubemap generatemipmap-cubemap.c) piglit_add_executable (fragment-and-vertex-texturing fragment-and-vertex-texturing.c) diff --git a/tests/texturing/getteximage-depth.c b/tests/texturing/getteximage-depth.c new file mode 100644 index 0000000..71311bc --- /dev/null +++ b/tests/texturing/getteximage-depth.c @@ -0,0 +1,628 @@ +/* + * Copyright (c) 2015 Red Hat + * + * 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 + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, 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 + * NON-INFRINGEMENT. IN NO EVENT SHALL VMWARE AND/OR THEIR SUPPLIERS + * 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 getteximage-depth + * + * Test glGetTexImage for depth/stencil format/target combinations in a roundtrip. + * i.e. don't draw the textures, just create and readback. + * this was due to a bug in mesa's handling of 1D array depth textures. + */ + +#include "piglit-util-gl.h" +#include "../fbo/fbo-formats.h" + +PIGLIT_GL_TEST_CONFIG_BEGIN + + config.supports_gl_compat_version = 10; + + config.window_visual = PIGLIT_GL_VISUAL_RGBA | PIGLIT_GL_VISUAL_DOUBLE; + +PIGLIT_GL_TEST_CONFIG_END + +enum piglit_result +piglit_display(void) +{ + /* UNREACHABLE */ + return PIGLIT_FAIL; +} + +#define IMAGE_WIDTH 32 +#define IMAGE_HEIGHT 32 + +static GLenum target_list[] = { GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_ARRAY, GL_TEXTURE_CUBE_MAP_ARRAY };
Can you wrap that line, maybe one target per line? Could be const too.
+
+static int test_target_bitmap;
+
+static int get_test_height(GLenum target)
+{
+ switch (target) {
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_1D_ARRAY:
+ return 1;
+ default:
+ return IMAGE_HEIGHT;
+ }
+}
+
+static int get_test_depth(GLenum target)
+{
+ switch (target) {
+ case GL_TEXTURE_3D:
+ return 16;
+ case GL_TEXTURE_1D_ARRAY:
+ case GL_TEXTURE_2D_ARRAY:
+ return 7;
+ case GL_TEXTURE_CUBE_MAP_ARRAY:
+ return 12;
+ case GL_TEXTURE_CUBE_MAP:
+ return 6;
+ default:
+ return 1;
+ }
+}
+
+static float get_depth_value(int w, int x)
+{
+ if (w == 1)
+ return 1.0;
+ else
+ return (float)(x) / (w - 1);
+}
+
+static int get_stencil_value(int w, int x)
+{
+ if (w == 1)
+ return 255;
+ else
+ return (x * 255) / (w - 1);
+}
+
+static GLuint
+get_depth_texture(const struct format_desc *format, GLenum target, int w, int
h, int d, GLboolean mip)
How about create_depth_texture()? From the function name, it thought the code was going to get/read depth texture data.
Can you wrap to 78 columns? Could use 'bool' instead of GLboolean.
+{
+ void *data;
+ float *f = NULL;
+ unsigned int *i = NULL;
+ int size, x, y, level, layer;
+ GLuint tex;
+ GLuint extra = 0;
+ GLenum datatype, dataformat;
+ int mul = 1;
+
+ glGenTextures(1, &tex);
+ glBindTexture(target, tex);
+ glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ if (mip) {
+ glTexParameteri(target, GL_TEXTURE_MAG_FILTER,
+ GL_LINEAR);
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
+ GL_LINEAR_MIPMAP_NEAREST);
+ } else {
+ glTexParameteri(target, GL_TEXTURE_MAG_FILTER,
+ GL_NEAREST);
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
+ GL_NEAREST);
+ }
I don't think you have to make any glTexParameter calls since there's no rendering/sampling in this test.
+ if (format->internalformat == GL_DEPTH32F_STENCIL8) {
+ mul = 2;
+ }
+ extra = d * sizeof(GLfloat) * mul;
+
+ data = calloc(1, w * h * sizeof(GLfloat) * mul + extra);
+
+ if (format->internalformat == GL_DEPTH_STENCIL_EXT ||
+ format->internalformat == GL_DEPTH24_STENCIL8_EXT) {
+ dataformat = GL_DEPTH_STENCIL_EXT;
+ datatype = GL_UNSIGNED_INT_24_8_EXT;
+ i = data;
+ } else if (format->internalformat == GL_DEPTH32F_STENCIL8) {
+ dataformat = GL_DEPTH_STENCIL;
+ datatype = GL_FLOAT_32_UNSIGNED_INT_24_8_REV;
+ f = data;
+ } else {
+ dataformat = GL_DEPTH_COMPONENT;
+ datatype = GL_FLOAT;
+ f = data;
+ }
+
+ for (level = 0, size = w > h ? w : h; size > 0; level++, size >>= 1) {
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++) {
+ float val = get_depth_value(w, x);
+
+ if (f)
+ f[(y * w + x)*mul] = val;
+ else
+ i[y * w + x] = 0xffffff00 * val;
+ }
+ }
+
+ for (x = 0; x < d; x++) {
+ float val = get_depth_value(w, x % w);
+
+ if (f)
+ f[(h * w + x)*mul] = val;
+ else
+ i[h * w + x] = 0xffffff00 * val;
+ }
+
+ switch (target) {
+ case GL_TEXTURE_1D:
+ glTexImage1D(target, level,
+ format->internalformat,
+ w, 0,
+ dataformat, datatype, data);
+ break;
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_RECTANGLE:
+ glTexImage2D(target, level,
+ format->internalformat,
+ w, h, 0,
+ dataformat, datatype, data);
+ break;
+ case GL_TEXTURE_CUBE_MAP:
+ assert(d == 6);
+ for (layer = 0; layer < d; layer++) {
+ char *ptr = data;
+ ptr += layer * 4 * mul;
+ glTexImage2D(cube_face_targets[layer],
+ level, format->internalformat,
+ w, h, 0,
+ dataformat, datatype, ptr);
+ }
+ break;
+ case GL_TEXTURE_1D_ARRAY:
+ glTexImage2D(target, level,
+ format->internalformat,
+ w, d, 0,
+ dataformat, datatype, NULL);
+ for (layer = 0; layer < d; layer++) {
+ char *ptr = data;
+ ptr += layer * (4 * mul);
+ glTexSubImage2D(target, level,
+ 0, layer, w, 1,
+ dataformat, datatype, ptr);
+ }
+ break;
+ case GL_TEXTURE_2D_ARRAY:
+ case GL_TEXTURE_CUBE_MAP_ARRAY:
+ glTexImage3D(target, level,
+ format->internalformat,
+ w, h, d, 0,
+ dataformat, datatype, NULL);
+ for (layer = 0; layer < d; layer++) {
+ char *ptr = data;
+ ptr += layer * (4 * mul);
+ glTexSubImage3D(target, level,
+ 0, 0, layer, w, h, 1,
+ dataformat, datatype, ptr);
+ }
+ break;
+
+ default:
+ assert(0);
+ }
+
+ if (!mip)
+ break;
+
+ if (w > 1)
+ w >>= 1;
+ if (target != GL_TEXTURE_1D &&
+ target != GL_TEXTURE_1D_ARRAY &&
+ h > 1)
+ h >>= 1;
+ }
+ free(data);
+ return tex;
+}
+
+static GLuint
+get_stencil_texture(const struct format_desc *format, GLenum target, int w,
int h, int d, GLboolean mip)
+{
+ void *data;
+ unsigned char *u;
+ int size, x, y, level, layer;
+ GLuint tex;
+ GLenum datatype, dataformat;
+
+ glGenTextures(1, &tex);
+ glBindTexture(target, tex);
+ glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ if (mip) {
+ glTexParameteri(target, GL_TEXTURE_MAG_FILTER,
+ GL_LINEAR);
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
+ GL_LINEAR_MIPMAP_NEAREST);
+ } else {
+ glTexParameteri(target, GL_TEXTURE_MAG_FILTER,
+ GL_NEAREST);
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
+ GL_NEAREST);
+ }
+ data = malloc(w * h * sizeof(GLubyte) + d * sizeof(GLubyte));
+
+ dataformat = GL_STENCIL_INDEX;
+ datatype = GL_UNSIGNED_BYTE;
+ u = data;
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ for (level = 0, size = w > h ? w : h; size > 0; level++, size >>= 1) {
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++) {
+ GLuint val = get_stencil_value(w, x);
+
+ u[y * w + x] = val;
+ }
+ }
+
+ for (x = 0; x < d; x++) {
+ GLuint val = get_stencil_value(w, x % w);
+ u[h * w + x] = val;
+ }
+
+ switch (target) {
+ case GL_TEXTURE_1D:
+ glTexImage1D(target, level,
+ format->internalformat,
+ w, 0,
+ dataformat, datatype, data);
+ break;
+
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_RECTANGLE:
+ glTexImage2D(target, level,
+ format->internalformat,
+ w, h, 0,
+ dataformat, datatype, data);
+ break;
+ case GL_TEXTURE_CUBE_MAP:
+ assert(d == 6);
+ for (layer = 0; layer < d; layer++) {
+ char *ptr = data;
+ ptr += layer;
+ glTexImage2D(cube_face_targets[layer],
+ level, format->internalformat,
+ w, h, 0,
+ dataformat, datatype, ptr);
+ }
+ break;
+ case GL_TEXTURE_1D_ARRAY:
+ glTexImage2D(target, level,
+ format->internalformat,
+ w, d, 0,
+ dataformat, datatype, NULL);
+ for (layer = 0; layer < d; layer++) {
+ char *ptr = data;
+ ptr += layer;
+ glTexSubImage2D(target, level,
+ 0, layer, w, 1,
+ dataformat, datatype, ptr);
+ }
+ break;
+ case GL_TEXTURE_CUBE_MAP_ARRAY:
+ case GL_TEXTURE_2D_ARRAY:
+ glTexImage3D(target, level,
+ format->internalformat,
+ w, h, d, 0,
+ dataformat, datatype, NULL);
+ for (layer = 0; layer < d; layer++) {
+ char *ptr = data;
+ ptr += layer;
+ glTexSubImage3D(target, level,
+ 0, 0, layer, w, h, 1,
+ dataformat, datatype, ptr);
+ }
+ break;
+
+ default:
+ assert(0);
+ }
+
+ if (!mip)
+ break;
+
+ if (w > 1)
+ w >>= 1;
+ if (target != GL_TEXTURE_1D &&
+ target != GL_TEXTURE_1D_ARRAY &&
+ h > 1)
+ h >>= 1;
+ }
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+ free(data);
+ return tex;
+}
+
+static bool
+verify_depth_data(const struct format_desc *format, GLenum target,
+ int w, int h, int d, GLboolean mip)
+{
+ int x, y, layer, level;
+ GLfloat *f;
+ unsigned *i = NULL;
+ int size;
+ GLenum datatype = format->base_internal_format;
+ GLenum dataformat;
+ int layer_size;
+ int mul = 1;
+ void *data, *ptr;
+ if (format->internalformat == GL_DEPTH32F_STENCIL8) {
+ dataformat = GL_FLOAT_32_UNSIGNED_INT_24_8_REV;
+ mul = 2;
+ }
+ else if (format->base_internal_format == GL_DEPTH_STENCIL)
+ dataformat = GL_UNSIGNED_INT_24_8_EXT;
+ else
+ dataformat = GL_FLOAT;
+
+ ptr = calloc(mul * 4, w * h * d);
+ if (!ptr)
+ return false;
+
+ for (level = 0, size = w > h ? w : h; size > 0; level++, size >>= 1) {
+ data = ptr;
+ layer_size = w * h * 4 * mul;
+
+ if (target == GL_TEXTURE_CUBE_MAP) {
+ int idx;
+ for (idx = 0; idx < 6; idx++)
+ glGetTexImage(cube_face_targets[idx], level,
datatype, dataformat,
+ (char *)data + layer_size * idx);
+ } else
+ glGetTexImage(target, level, datatype, dataformat,
+ data);
+
+ for (layer = 0; layer < d; layer++) {
+ f = data;
+ if (format->internalformat == GL_DEPTH_STENCIL_EXT ||
+ format->internalformat == GL_DEPTH24_STENCIL8_EXT)
+ i = data;
+
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++) {
+ int offset = (x + layer) % w;
+ float exp_val = get_depth_value(w,
offset);
+ float got_val;
+
+ if (i)
+ got_val = (float)(i[y * w + x]
>> 8) / (float)0xffffff;
+ else
+ got_val = f[(y * w + x) * mul];
+ if (fabs(got_val - exp_val) >= 1e-4) {
+ fprintf(stderr, "mismatch at %d %d
%d %d %g vs %g: %d %dx%d\n", level, x, y, layer, got_val, exp_val, layer_size, w, h);
+ if (0){
+ uint32_t *myptr = data;
+ int myx;
+ for (myx = 0; myx < w *
h; myx++){
+ fprintf(stderr,
"%08x ", myptr[myx]);
+ }
+ fprintf(stderr, "\n");
+ }
+ free(ptr);
+ return false;
+ }
+ }
+ }
+ data = (char *)data + layer_size;
+ }
+
+ if (!mip)
+ break;
+ if (w > 1)
+ w >>= 1;
+ if (target != GL_TEXTURE_1D &&
+ target != GL_TEXTURE_1D_ARRAY &&
+ h > 1)
+ h >>= 1;
+ }
+ free(ptr);
+ return true;
+}
+
+static bool
+verify_stencil_data(const struct format_desc *format,
+ GLenum target, int w, int h, int d, GLboolean mip)
+{
+ int x, y, layer, level, size;
+ GLubyte *ub;
+ GLenum datatype = format->base_internal_format;
+ GLenum dataformat = GL_UNSIGNED_BYTE;
+ void *data, *ptr;
+ int layer_size;
+
+ ptr = calloc(1, w * h * d);
+ if (!ptr)
+ return false;
+
+ for (level = 0, size = w > h ? w : h; size > 0; level++, size >>= 1) {
+ data = ptr;
+ layer_size = w * h;
+ glPixelStorei(GL_PACK_ALIGNMENT, 1);
+ if (target == GL_TEXTURE_CUBE_MAP) {
+ int idx;
+ for (idx = 0; idx < 6; idx++)
+ glGetTexImage(cube_face_targets[idx], level,
datatype, dataformat,
+ (char *)data + layer_size * idx);
+ } else
+ glGetTexImage(target, level, datatype, dataformat,
+ data);
+ glPixelStorei(GL_PACK_ALIGNMENT, 4);
+ for (layer = 0; layer < d; layer++) {
+ ub = data;
+
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++) {
+ int offset = (x + layer) % w;
+ GLubyte got_val;
+ GLubyte exp_val = get_stencil_value(w,
offset);
+
+ got_val = ub[y * w + x];
+ if (exp_val != got_val) {
+ fprintf(stderr, "mismatch at %d %d
%d %d %d vs %d: %d %dx%d\n", level, x, y, layer, got_val, exp_val, layer_size, w, h);
+ free(ptr);
+ return false;
+ }
+ }
+ }
+ data = (char *)data + layer_size;
+ }
+
+ if (!mip)
+ break;
+ if (w > 1)
+ w >>= 1;
+ if (target != GL_TEXTURE_1D &&
+ target != GL_TEXTURE_1D_ARRAY &&
+ h > 1)
+ h >>= 1;
+ }
+ free(ptr);
+ return true;
+}
+
+bool test_depth_format(GLenum target, const struct format_desc *format)
static bool test_depth_format(...) Same thing below. There seems to be a mix of function declaration styles.
+{
+ GLuint tex;
+ int height, num_layers;
+ bool ret;
+
+ /* 3D depth textures don't occur */
+ if (target == GL_TEXTURE_3D)
+ return true;
+
+ height = get_test_height(target);
+ num_layers = get_test_depth(target);
+
+ tex = get_depth_texture(format, target, IMAGE_WIDTH, height, num_layers,
+ target == GL_TEXTURE_RECTANGLE ? false : true);
+
+ ret = verify_depth_data(format, target, IMAGE_WIDTH, height, num_layers,
+ target == GL_TEXTURE_RECTANGLE ? false : true);
+
+ piglit_report_subtest_result(ret ? PIGLIT_PASS : PIGLIT_FAIL,
+ "%s-%s",
+ piglit_get_gl_enum_name(target),
+
piglit_get_gl_enum_name(format->internalformat));
+ glDeleteTextures(1, &tex);
+ return ret;
+}
+
+bool test_stencil_format(GLenum target, const struct format_desc *format)
+{
+ GLuint tex;
+ int height, num_layers;
+ bool ret;
+ /* 3D depth textures don't occur */
+ if (target == GL_TEXTURE_3D)
+ return true;
+
+ height = get_test_height(target);
+ num_layers = get_test_depth(target);
+
+ tex = get_stencil_texture(format, target, IMAGE_WIDTH, height,
num_layers,
+ target == GL_TEXTURE_RECTANGLE ? false :
true);
+
+ ret = verify_stencil_data(format, target, IMAGE_WIDTH, height,
num_layers,
+ target == GL_TEXTURE_RECTANGLE ? false :
true);
+ piglit_report_subtest_result(ret ? PIGLIT_PASS : PIGLIT_FAIL,
+ "%s-%s",
+ piglit_get_gl_enum_name(target),
+
piglit_get_gl_enum_name(format->internalformat));
+ glDeleteTextures(1, &tex);
+ return ret;
+}
+
+bool test_target_format(GLenum target, const struct format_desc *format)
+{
+ if (format->base_internal_format == GL_DEPTH_COMPONENT ||
+ format->base_internal_format == GL_DEPTH_STENCIL) {
+ return test_depth_format(target, format);
+ } else if (format->base_internal_format == GL_STENCIL_INDEX) {
+ return test_stencil_format(target, format);
+ }
+ return true;
+}
+
+bool test_target(GLenum target)
+{
+ int fmt_idx;
+ int set_idx;
+ int ext_idx;
+ bool do_test_set;
+ bool result = true, ret;
+
+ for (set_idx = 0; set_idx < ARRAY_SIZE(test_sets); set_idx++) {
+ do_test_set = true;
+ for (ext_idx = 0; ext_idx < 3; ext_idx++) {
+ if (test_sets[set_idx].ext[ext_idx])
+ if
(!piglit_is_extension_supported(test_sets[set_idx].ext[ext_idx])) {
+ do_test_set = false;
+ break;
+ }
+ }
+ if (!do_test_set)
+ continue;
+
+ for (fmt_idx = 0; fmt_idx < test_sets[set_idx].num_formats;
fmt_idx++) {
+ ret = test_target_format(target,
&test_sets[set_idx].format[fmt_idx]);
+ if (ret == false)
+ result = false;
+ }
+ }
+ return result;
+}
+
+void
+piglit_init(int argc, char **argv)
+{
+ int i;
+ enum piglit_result status = PIGLIT_PASS;
+ bool ret;
+
+ for (i = 0; i < 3; i++)
+ test_target_bitmap |= (1 << i);
+ if (piglit_is_extension_supported("GL_ARB_texture_rectangle"))
+ test_target_bitmap |= (1 << 3);
+ if (piglit_is_extension_supported("GL_ARB_texture_cube_map"))
+ test_target_bitmap |= (1 << 4);
+ if (piglit_is_extension_supported("GL_EXT_texture_array"))
+ test_target_bitmap |= (1 << 5) | (1 << 6);
+ if (piglit_is_extension_supported("GL_ARB_texture_cube_map_array"))
+ test_target_bitmap |= (1 << 7);
+
+ for (i = 0; i < ARRAY_SIZE(target_list); i++) {
+ if (!(test_target_bitmap & (1 << i)))
+ continue;
+
+ ret = test_target(target_list[i]);
+ if (ret == false)
+ status = PIGLIT_FAIL;
+ }
The bitmap logic seems a little brittle. How about something like this:
for (i = 0; i < ARRAY_SIZE(target_list); i++) {
switch (target_list[i]) {
case GL_TEXTURE_1D_ARRAY:
case GL_TEXTURE_2D_ARRAY:
if
(!piglit_is_extension_supported("GL_EXT_texture_array"))
continue;
break;
...
}
ret = test_target(target_list[i]);
...
}
Thanks for writing this test though!
-Brian
+ + piglit_report_result(status); + (void)fbo_formats_display; +}
_______________________________________________ Piglit mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/piglit
