Test for image from texture extension. Currently testing KHR_gl_texture_2D_image, KHR KHR_gl_texture_cubemap_image.
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 | 403 ++++++++++++++++++++ 5 files changed, 427 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 4581edf..c6cf2bd 100644 --- a/tests/all.tests +++ b/tests/all.tests @@ -2674,6 +2674,11 @@ egl_khr_create_context['3.2 core profile required'] = plain_test('egl-create-con egl_khr_create_context['pre-GL3.2 profile'] = plain_test('egl-create-context-pre-GL32-profile') egl_khr_create_context['verify GL flavor'] = plain_test('egl-create-context-verify-gl-flavor') +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 46a91bd..0168d00 100644 --- a/tests/spec/CMakeLists.txt +++ b/tests/spec/CMakeLists.txt @@ -62,3 +62,4 @@ add_subdirectory (arb_draw_buffers) add_subdirectory (oes_draw_texture) add_subdirectory (arb_blend_func_extended) add_subdirectory (ext_unpack_subimage) +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..3fdf7ff --- /dev/null +++ b/tests/spec/khr_gl_texture_image/khr_gl_texture_image.c @@ -0,0 +1,403 @@ +/* + * 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 WIDTH 448 +#define HEIGHT 448 +#define TEXTURE_SIZE 64 + +PIGLIT_GL_TEST_CONFIG_BEGIN + + config.supports_gl_es_version = 20; + + config.window_width = WIDTH; + config.window_height = HEIGHT; + 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[][3] = { + {1.0, 1.0, 1.0}, + {1.0, 1.0, 0.0}, + {1.0, 0.0, 0.0}, + {1.0, 0.0, 1.0}, + {0.0, 0.0, 1.0}, + {0.0, 1.0, 1.0}, + {0.0, 1.0, 0.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); + piglit_link_check_status(program); + + 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) { + printf("Warning EGL_NO_IMAGE_KHR 0x%x\n", + eglGetError()); + } + + 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)]; + GLfloat *tex; + int x, y; + + tex = malloc(size * size * 3 * sizeof(GLfloat)); + + 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) * 3 + 0] = chosen_color[0]; + tex[(y * size + x) * 3 + 1] = chosen_color[1]; + tex[(y * size + x) * 3 + 2] = chosen_color[2]; + } + } + + glTexImage2D(face, level, GL_RGB, size, size, 0, GL_RGB, GL_FLOAT, tex); + + 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); + + for (level = 0, sz = size; sz > 0; level++, sz >>= 1) { + for (f = 0; f < 6; ++f) { + set_face_image(level, cube_face_targets[f], sz, color); + color = (color + 1) % ARRAY_SIZE(colors); + } + } + + return texture; +} + +static GLuint +make_2d_texture(int size) +{ + GLuint texture; + int level, sz, 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 (level = 0, sz = size; sz > 0; level++, sz >>= 1) { + set_face_image(level, GL_TEXTURE_2D, sz, color); + color = (color + 1) % ARRAY_SIZE(colors); + } + + 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; + int x1 = x + size / 4, x2 = x + size * 3 / 4; + int y1 = y + size / 4, y2 = y + size * 3 / 4; + + if (size == 1) { + pass = pass && piglit_probe_pixel_rgb(x1, y1, color1); + } else { + pass = pass && piglit_probe_pixel_rgb(x1, y1, color2); + pass = pass && piglit_probe_pixel_rgb(x2, y1, color1); + pass = pass && piglit_probe_pixel_rgb(x2, y2, color1); + pass = pass && piglit_probe_pixel_rgb(x1, y2, color1); + } + + return pass; +} + +static bool +test_2d_texture(int texture_size) +{ + int color = ARRAY_SIZE(colors) - 1; + int level, layout_pos = 0, size = 1; + bool pass = true; + + for (level = texture_size; level > 0; color--, level >>= 1) { + pass = test_results(0, layout_pos, size, color) && pass; + layout_pos += TEXTURE_SIZE; + size *=2; + } + + return pass; +} +/** + * Test if cubemap faces from all miplevels are rendered correctly. + * We reverse the order in which face colors are retrieved due to + * glReadPixels reading data from Y-bottom and we originally render + * from top to bottom. + */ +static bool +test_cubemap_texture(int texture_size, int num_level) +{ + static int sz = ARRAY_SIZE(colors); + int color = sz - 1; + int face, size, dim, r = 0, mip_level = num_level; + int vert_pos, horiz_pos = 0; + int fail_score = 0; + + for (size = 1, dim = texture_size; dim > 0; size *= 2, dim >>= 1) { + mip_level--; + for (vert_pos = piglit_width - texture_size, face = 5; + face >= 0; face--, vert_pos -= texture_size) { + if (!test_results(vert_pos, horiz_pos, size, color)) { + printf("Cube map failed at " + "miplevel %d, face %s\n", + mip_level, cube_face_names[face]); + fail_score++; + } + r = (r + 1) % sz; + color = sz - r - 1; + } + horiz_pos += texture_size; + } + + return (!fail_score); +} + +/** + * Draws all faces of cubemap texture from top to bottom and returns + * the number of miplevels + */ +static int +draw_cubemap_textures(GLuint texture, int tex_sz, float tex_box) +{ + float layout_pos, size; + float vert_pos = -1.0 + tex_box; + int tex_size, face, level = 0; + + for (face = 0; face < 6; face++) { + for (level = 0, tex_size = tex_sz, layout_pos = 1.0, size = tex_box; + tex_size > 0; level++, size /=2, tex_size >>= 1) { + layout_pos -= tex_box; + glBindTexture(GL_TEXTURE_2D, + create_egl_image_target(egl_cube_face_targets[face], + texture, level)); + piglit_draw_rect_tex(vert_pos, layout_pos, size, size, 0, 0, 1, 1); + } + vert_pos += tex_box; + } + + return level; +} + +static void +draw_2d_texture(GLuint texture, int tex_sz, float tex_box) +{ + float size, layout_pos = 1.0; + int tex_size, level = 0; + + for (tex_size = tex_sz, size = tex_box; tex_size > 0; + size /=2, level++, tex_size >>= 1) { + layout_pos -= tex_box; + + glBindTexture(GL_TEXTURE_2D, + create_egl_image_target(EGL_GL_TEXTURE_2D_KHR, + texture, level)); + piglit_draw_rect_tex(-1, layout_pos, size, size, 0, 0, 1, 1); + } +} + +enum piglit_result +piglit_display(void) +{ + const float tex_box = 2.0 * (1.0 / 7.0); + + EGLDisplay dpy = eglGetCurrentDisplay(); + EGLSurface draw = eglGetCurrentSurface(EGL_DRAW); + GLuint tex_2d; + GLuint tex_cubemap; + bool pass = true; + int levels; + + glViewport(0, 0, piglit_width, piglit_height); + glClearColor(0,0, 0, 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; + + eglSwapBuffers(dpy, draw); + + /* 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; + + for (i = 1; i < argc; ++i) { + if (!strcmp(argv[i], "-2d")) { + test_2d = true; + break; + } + if (!strcmp(argv[i], "-cubemap")) { + test_cubemap = true; + break; + } + } + + test_2d = test_2d && piglit_is_egl_extension_supported(eglGetCurrentDisplay(), + "EGL_KHR_gl_texture_2D_image"); + test_cubemap = test_cubemap && piglit_is_egl_extension_supported(eglGetCurrentDisplay(), + "KHR_gl_texture_cubemap_image"); +} -- 1.7.9.5 _______________________________________________ Piglit mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/piglit
