From: Abdiel Janulgue <[email protected]> Actual V4. Discard the previous V3. I made another stupid mistake of forgetting to rebase from latest master. This one should be good, I hope.
Changes since v3: -Use TEXTURE_SIZE * 7 in test window width and height -Fix missed array element initialization in set_face_image(). -Use GL_UNSIGNED_BYTE instead of GL_FLOAT (which is unsupported in GLES2 texImage2D) -Fixed further issues found by Eric. Signed-off-by: Abdiel Janulgue <[email protected]> --- tests/all.tests | 5 + tests/spec/CMakeLists.txt | 1 + .../spec/khr_gl_texture_image/CMakeLists.gles2.txt | 17 + tests/spec/khr_gl_texture_image/CMakeLists.txt | 1 + .../khr_gl_texture_image/khr_gl_texture_image.c | 416 ++++++++++++++++++++ 5 files changed, 440 insertions(+) create mode 100644 tests/spec/khr_gl_texture_image/CMakeLists.gles2.txt create mode 100644 tests/spec/khr_gl_texture_image/CMakeLists.txt create mode 100644 tests/spec/khr_gl_texture_image/khr_gl_texture_image.c diff --git a/tests/all.tests b/tests/all.tests index 2e88de4..5b0c9e8 100644 --- a/tests/all.tests +++ b/tests/all.tests @@ -3264,6 +3264,11 @@ add_concurrent_test(gles20, 'minmax_gles2') add_concurrent_test(gles20, 'multiple-shader-objects_gles2') add_concurrent_test(gles20, 'fbo_discard_gles2') +egl_khr_gl_image = Group() +spec['EGL_KHR_gl_image'] = egl_khr_gl_image +egl_khr_gl_image['EGL_KHR_gl_texture_2D_image'] = plain_test('khr_gl_texture_image_gles2 -2d') +egl_khr_gl_image['EGL_KHR_gl_texture_cubemap_image'] = plain_test('khr_gl_texture_image_gles2 -cubemap') + gles30 = Group() spec['!OpenGL ES 3.0'] = gles30 for tex_format in ('rgb8', 'srgb8', 'rgba8', 'srgb8-alpha8', 'r11', 'rg11', 'rgb8-punchthrough-alpha1', 'srgb8-punchthrough-alpha1'): diff --git a/tests/spec/CMakeLists.txt b/tests/spec/CMakeLists.txt index 18b846d..2874314 100644 --- a/tests/spec/CMakeLists.txt +++ b/tests/spec/CMakeLists.txt @@ -88,3 +88,4 @@ add_subdirectory (ext_image_dma_buf_import) add_subdirectory (arb_blend_func_extended) add_subdirectory (ext_unpack_subimage) add_subdirectory (arb_vertex_array_object) +add_subdirectory (khr_gl_texture_image) diff --git a/tests/spec/khr_gl_texture_image/CMakeLists.gles2.txt b/tests/spec/khr_gl_texture_image/CMakeLists.gles2.txt new file mode 100644 index 0000000..d1887a1 --- /dev/null +++ b/tests/spec/khr_gl_texture_image/CMakeLists.gles2.txt @@ -0,0 +1,17 @@ +#add_definitions(-DSOURCE_DIR="${piglit_SOURCE_DIR}/") + +include_directories( + ${OPENGL_INCLUDE_PATH} + ) + +link_libraries( + ${OPENGL_gles2_LIBRARY} + ${OPENGL_egl_LIBRARY} + piglitutil_gles2 + ) + +piglit_add_executable(khr_gl_texture_image_gles2 + khr_gl_texture_image.c + ) + +# vim: ft=cmake: diff --git a/tests/spec/khr_gl_texture_image/CMakeLists.txt b/tests/spec/khr_gl_texture_image/CMakeLists.txt new file mode 100644 index 0000000..144a306 --- /dev/null +++ b/tests/spec/khr_gl_texture_image/CMakeLists.txt @@ -0,0 +1 @@ +piglit_include_target_api() diff --git a/tests/spec/khr_gl_texture_image/khr_gl_texture_image.c b/tests/spec/khr_gl_texture_image/khr_gl_texture_image.c new file mode 100644 index 0000000..ff24766 --- /dev/null +++ b/tests/spec/khr_gl_texture_image/khr_gl_texture_image.c @@ -0,0 +1,416 @@ +/* + * Copyright © 2012-2013 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. + * + * Authors: + * Abdiel Janulgue <[email protected]> + * + */ + +#define EGL_EGLEXT_PROTOTYPES 1 +#define GL_GLEXT_PROTOTYPES 1 +#include "piglit-util-gl-common.h" +#include "piglit-util-egl.h" + +#include <EGL/eglext.h> + +#define TEXTURE_SIZE 64 + +PIGLIT_GL_TEST_CONFIG_BEGIN + + config.supports_gl_es_version = 20; + + config.window_width = TEXTURE_SIZE * 7; + config.window_height = TEXTURE_SIZE * 7; + config.window_visual = PIGLIT_GL_VISUAL_RGB | PIGLIT_GL_VISUAL_DOUBLE; + +PIGLIT_GL_TEST_CONFIG_END + +const GLenum egl_cube_face_targets[6] = { + EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR, + EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR, + EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR, + EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR, + EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR, + EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR, +}; + +static GLfloat colors[][4] = { + {1.0, 1.0, 1.0, 1.0}, + {1.0, 1.0, 0.0, 1.0}, + {1.0, 0.0, 0.0, 1.0}, + {1.0, 0.0, 1.0, 1.0}, + {0.0, 0.0, 1.0, 1.0}, + {0.0, 1.0, 1.0, 1.0}, + {0.0, 1.0, 0.0, 1.0}, +}; + +static bool test_cubemap = false; +static bool test_2d = false; + +static const char +vertex_shader[] = + "attribute vec4 pos_attrib;\n" + "attribute vec2 tex_attrib;\n" + "varying vec2 tex_coord;\n" + "void main () {\n" + "gl_Position = pos_attrib;\n" + "tex_coord = tex_attrib;\n" + "}\n"; + +static const char +fragment_shader[] = + "uniform sampler2D tex;\n" + "varying vec2 tex_coord;\n" + "void main () {\n" + "gl_FragColor = texture2D(tex, tex_coord);\n" + "}\n"; + +static void +make_program(const char *vertex_source, + const char *fragment_source) +{ + GLuint program, shader; + GLuint uniform; + + program = glCreateProgram(); + shader = piglit_compile_shader_text(GL_VERTEX_SHADER, vertex_source); + glAttachShader(program, shader); + shader = piglit_compile_shader_text(GL_FRAGMENT_SHADER, fragment_source); + glAttachShader(program, shader); + + glBindAttribLocation(program, PIGLIT_ATTRIB_POS, "pos_attrib"); + glBindAttribLocation(program, PIGLIT_ATTRIB_TEX, "tex_attrib"); + + glLinkProgram(program); + if (!piglit_link_check_status(program)) + piglit_report_result(PIGLIT_FAIL); + + uniform = glGetUniformLocation(program, "tex"); + glUseProgram(program); + glUniform1i(uniform, 0); +} + +static GLuint +create_egl_image_target(EGLenum target, GLuint texture, GLuint level) +{ + GLuint target_texture; + EGLint attribs[] = { + EGL_GL_TEXTURE_LEVEL_KHR, level, + EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, + EGL_NONE + }; + + EGLDisplay dpy = eglGetCurrentDisplay(); + EGLContext ctx = eglGetCurrentContext(); + EGLImageKHR image = eglCreateImageKHR(dpy, ctx, target, + (EGLClientBuffer)(uintptr_t)texture, + attribs); + if (image == EGL_NO_IMAGE_KHR) + piglit_report_result(PIGLIT_FAIL); + + glGenTextures(1, &target_texture); + glBindTexture(GL_TEXTURE_2D, target_texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, + GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_LINEAR); + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); + + return target_texture; +} + +static void +set_face_image(int level, GLenum face, int size, int color) +{ + GLfloat *color1 = colors[color]; + GLfloat *color2 = colors[(color + 1) % ARRAY_SIZE(colors)]; + GLubyte *tex; + int x, y; + + tex = malloc(size * size * 4 * sizeof(GLubyte)); + + for (y = 0; y < size; y++) { + for (x = 0; x < size; x++) { + GLfloat *chosen_color; + + if (y >= (size / 2) || x >= (size / 2)) + chosen_color = color1; + else + chosen_color = color2; + + tex[(y * size + x) * 4 + 0] = chosen_color[0] * 255; + tex[(y * size + x) * 4 + 1] = chosen_color[1] * 255; + tex[(y * size + x) * 4 + 2] = chosen_color[2] * 255; + tex[(y * size + x) * 4 + 3] = 255; + } + } + + glTexImage2D(face, level, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex); + piglit_check_gl_error(GL_NO_ERROR); + + free(tex); +} + +static GLuint +make_cubemap_texture(int size) +{ + GLuint texture; + int f, sz, level = 0, color = 0; + + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_CUBE_MAP, texture); + glTexParameteri(GL_TEXTURE_CUBE_MAP, + GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); + glTexParameteri(GL_TEXTURE_CUBE_MAP, + GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_CUBE_MAP, + GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, + GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + /* Generate colors in miplevel-major ordering to avoid repeating + * the same sequence of miplevel colors per face; + */ + for (sz = size; sz > 0; sz >>= 1) { + for (f = 0; f < 6; ++f) { + set_face_image(level, cube_face_targets[f], sz, color); + color = (color + 1) % ARRAY_SIZE(colors); + } + level++; + } + + return texture; +} + +static GLuint +make_2d_texture(int size) +{ + GLuint texture; + int sz, level = 0, color = 0; + + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, + GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_LINEAR_MIPMAP_NEAREST); + + for (sz = size; sz > 0; sz >>= 1) { + set_face_image(level, GL_TEXTURE_2D, sz, color); + color = (color + 1) % ARRAY_SIZE(colors); + level++; + } + + return texture; +} + +static bool +test_results(int x, int y, int size, int color) +{ + GLfloat *color1 = colors[color]; + GLfloat *color2 = colors[(color + 1) % ARRAY_SIZE(colors)]; + bool pass = true; + + if (size == 1) { + pass = pass && piglit_probe_rect_rgba(x, y, + size/2, size/2, color1); + } else { + pass = pass && piglit_probe_rect_rgba(x, y, + size/2, size/2, + color2); + pass = pass && piglit_probe_rect_rgba(x + size/2, y, + size/2, size, color1); + pass = pass && piglit_probe_rect_rgba(x, y + size/2, + size/2,size/2,color1); + } + + return pass; +} + +static bool +test_2d_texture(int texture_size) +{ + int color = ARRAY_SIZE(colors) - 1; + int level, y = 0, size = 1; + bool pass = true; + + for (level = texture_size; level > 0; level >>= 1) { + pass = test_results(0, y, size, color) && pass; + y += TEXTURE_SIZE; + size *=2; + color--; + } + + return pass; +} + +/** + * Test if cubemap faces from all miplevels are rendered correctly. + */ +static bool +test_cubemap_texture(int texture_size, int num_level) +{ + static int sz = ARRAY_SIZE(colors); + int color = sz - 1; + int face, dim, size = 1, r = 0, mip_level = num_level; + int x, y = 0; + + x = piglit_width - texture_size; + for (dim = texture_size; dim > 0; dim >>= 1) { + mip_level--; + y = texture_size; + for (face = 5; face >= 0; face--) { + if (!test_results(x, y, size, color)) { + printf("Cube map failed at " + "miplevel %d, face %s\n", + mip_level, cube_face_names[face]); + return false; + } + y += texture_size; + r = (r + 1) % sz; + color = sz - r - 1; + } + x -= texture_size; + size *= 2; + } + + return true; +} + +/** + * Draws all cubemap face textures in miplevel-major notation + */ +static int +draw_cubemap_textures(GLuint texture, int tex_sz, float tex_box) +{ + float x, y, size; + int tex_size, face, level = 0; + + x = -1.0; + level = 0; + size = tex_box; + for (tex_size = tex_sz; tex_size > 0; tex_size >>= 1) { + y = 1.0; + for (face = 0; face < 6; face++) { + y -= tex_box; + glBindTexture(GL_TEXTURE_2D, + create_egl_image_target(egl_cube_face_targets[face], + texture, level)); + piglit_draw_rect_tex(x, y, size, size, 0, 0, 1, 1); + } + x += tex_box; + size /=2; + level++; + } + + return level; +} + +static void +draw_2d_texture(GLuint texture, int tex_sz, float tex_box) +{ + float size = tex_box, y = 1.0; + int tex_size, level = 0; + + for (tex_size = tex_sz; tex_size > 0; tex_size >>= 1) { + y -= tex_box; + glBindTexture(GL_TEXTURE_2D, + create_egl_image_target(EGL_GL_TEXTURE_2D_KHR, + texture, level)); + piglit_draw_rect_tex(-1, y, size, size, 0, 0, 1, 1); + size /=2; + level++; + } +} + +enum piglit_result +piglit_display(void) +{ + /* Bounding box size for each test image to layout + nicely within our test window + */ + const float tex_box = 2.0 * (1.0 / (piglit_width/TEXTURE_SIZE)); + + EGLDisplay dpy = eglGetCurrentDisplay(); + EGLSurface draw = eglGetCurrentSurface(EGL_DRAW); + GLuint tex_2d; + GLuint tex_cubemap; + bool pass = true; + int levels; + + glClearColor(0,0, 0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + + /* Set up a source texture object with mipmap generation */ + tex_2d = make_2d_texture(TEXTURE_SIZE); + tex_cubemap = make_cubemap_texture(TEXTURE_SIZE); + + glActiveTexture(GL_TEXTURE0); + make_program(vertex_shader, fragment_shader); + if (!piglit_check_gl_error(GL_NO_ERROR)) + pass = false; + + /* Generate EGLImage target textures from source texture + and render all miplevels */ + if (test_2d) + draw_2d_texture(tex_2d, TEXTURE_SIZE, tex_box); + if (test_cubemap) + levels = draw_cubemap_textures(tex_cubemap, TEXTURE_SIZE, tex_box); + + if (!piglit_check_gl_error(GL_NO_ERROR)) + pass = false; + piglit_present_results(); + + /* Check if we have rendered correctly */ + if (test_2d) + pass = pass && test_2d_texture(TEXTURE_SIZE); + if (test_cubemap) + pass = pass && test_cubemap_texture(TEXTURE_SIZE, levels); + + return pass ? PIGLIT_PASS : PIGLIT_FAIL; +} + +void +piglit_init(int argc, char **argv) +{ + int i; + EGLDisplay dpy = eglGetCurrentDisplay(); + + for (i = 1; i < argc; ++i) { + if (!strcmp(argv[i], "-2d")) { + if (!piglit_is_egl_extension_supported(dpy, + "EGL_KHR_gl_texture_2D_image")) + piglit_report_result(PIGLIT_SKIP); + test_2d = true; + break; + } + if (!strcmp(argv[i], "-cubemap")) { + if (!piglit_is_egl_extension_supported(dpy, + "KHR_gl_texture_cubemap_image")) + piglit_report_result(PIGLIT_SKIP); + test_cubemap = true; + break; + } + } +} -- 1.7.9.5 _______________________________________________ Piglit mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/piglit
