Specification doesn't define behaviour for rotation of 0-vector. In https://github.com/KhronosGroup/OpenGL-API/issues/41 said that behaviour is undefined and agreed that it would be fine for implementation to do something useful for this. Windows and Nvidia drivers have a workaround for that. For compatibility proposed optimized version of computations. Specification defines a formula of rotation (see "OpenGL 4.6 (Compatibility Profile) - May 14, 2018", paragraph "12.1.1 Matrices").
Optimized formula will look so: R = cos(angle) * I That is equivalent to logic that magnitude of (0,0,0)-vector is 1.0. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=100960 Signed-off-by: Sergii Romantsov <sergii.romant...@globallogic.com> CC: Brian Paul <bri...@vmware.com> CC: Timothy Arceri <tarc...@itsqueeze.com> --- tests/general/CMakeLists.gl.txt | 1 + tests/general/zero-vector-rotate.c | 252 +++++++++++++++++++++++++++++++++++++ tests/opengl.py | 1 + 3 files changed, 254 insertions(+) create mode 100644 tests/general/zero-vector-rotate.c diff --git a/tests/general/CMakeLists.gl.txt b/tests/general/CMakeLists.gl.txt index ceec9f0..c713f63 100644 --- a/tests/general/CMakeLists.gl.txt +++ b/tests/general/CMakeLists.gl.txt @@ -122,6 +122,7 @@ piglit_add_executable (vbo-map-unsync vbo-map-unsync.c) piglit_add_executable (vbo-bufferdata vbo-bufferdata.c) piglit_add_executable (vbo-subdata-zero vbo-subdata-zero.c) piglit_add_executable (vbo-subdata-sync vbo-subdata-sync.c) +piglit_add_executable (zero-vector-rotate zero-vector-rotate.c) piglit_add_executable (object_purgeable-api-pbo object_purgeable-api-pbo.c object_purgeable.c) piglit_add_executable (object_purgeable-api-texture object_purgeable-api-texture.c object_purgeable.c) piglit_add_executable (object_purgeable-api-vbo object_purgeable-api-vbo.c object_purgeable.c) diff --git a/tests/general/zero-vector-rotate.c b/tests/general/zero-vector-rotate.c new file mode 100644 index 0000000..7b1b605 --- /dev/null +++ b/tests/general/zero-vector-rotate.c @@ -0,0 +1,252 @@ +/* + * Copyright © 2018 Sergii Romantsov (sergii.romant...@gmail.com) + * + * 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. + */ + + +#include "piglit-util-gl.h" + +/* + * Specification doesn't define behaviour for rotation of 0-vector. + * In https://github.com/KhronosGroup/OpenGL-API/issues/41 said that + * behaviour is undefined and agreed that it would be fine for + * implementation to do something useful for this. + * Windows and Nvidia drivers have a workaround for that. + * For compatibility proposed optimized version of computations. + * Specification defines a formula of rotation (see "OpenGL 4.6 + * (Compatibility Profile) - May 14, 2018", paragraph "12.1.1 Matrices"). + * + * Optimized formula will look so: + * + * R = cos(angle) * I + * + * That is equivalent to logic that magnitude of (0,0,0)-vector is 1.0. + * + * Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=100960 + */ + +const float g_inconsistency_x = 2.0; +const float g_inconsistency_y = 3.0; + +PIGLIT_GL_TEST_CONFIG_BEGIN + + config.supports_gl_compat_version = 10; + config.window_width = 1008; + config.window_height = 1008; + + config.window_visual = PIGLIT_GL_VISUAL_RGBA | PIGLIT_GL_VISUAL_DOUBLE; + +PIGLIT_GL_TEST_CONFIG_END + +void +piglit_init(int argc, char **argv) +{ + piglit_gen_ortho_projection(0, piglit_width, 0, piglit_height, -piglit_height, piglit_height, false); + + glEnable(GL_CULL_FACE); + glFrontFace(GL_CW); +} + +static inline int +above_zero(float value) +{ + return value > 0.000001; +} + +static inline int +below_zero(float value) +{ + return value < -0.000001; +} + +static void +get_color(int step, float color[3]) +{ + const static int g_colors = 8; + switch(step) { + case 0: + color[0] = 0.0, color[1] = 0.0, color[2] = 0.0; + break; + case 1: + color[0] = 0.0, color[1] = 0.0, color[2] = 1.0; + break; + case 2: + color[0] = 0.0, color[1] = 1.0, color[2] = 0.0; + break; + case 3: + color[0] = 0.0, color[1] = 1.0, color[2] = 1.0; + break; + case 4: + color[0] = 1.0, color[1] = 0.0, color[2] = 0.0; + break; + case 5: + color[0] = 1.0, color[1] = 0.0, color[2] = 1.0; + break; + case 6: + color[0] = 1.0, color[1] = 1.0, color[2] = 0.0; + break; + case 7: + color[0] = 1.0, color[1] = 1.0, color[2] = 1.0; + break; + default: + get_color(step % g_colors, color); + } +} + +static int +draw_triangles(float pos_x, float pos_y, float base_angle) +{ + /* A number of draws for each base angle */ + const int steps = 24; + /* Size of triangle edge */ + const float size = piglit_width / steps; + const float size_half = size / 2; + const float angle_shift = 360 / steps; + /* Rotation is similar to scaling for 0-vector */ + const float scale = cos(base_angle * M_PI / 180.0); + + /* Triangle coordinates */ + float x1 = 0, y1 = 0; + float x2 = x1 + size_half, y2 = y1 + size; + float x3 = x2 + size_half, y3 = y1; + + int step = steps; + float angle = 0; + int is_failed = 0; + + glTranslatef(pos_x, pos_y, 0); + glRotatef(base_angle, 0.0, 0.0, 0.0); + + while (step--) { + const float scale2 = cos(angle * M_PI / 180.0); + float color[3]; + + glPushMatrix(); + get_color(step, color); + glColor3f(color[0], color[1], color[2]); + glRotatef(angle, 1.0, 0.0, 0.0); + piglit_draw_triangle(x1, y1, x2, y2, x3, y3); + + /* Checking correctness of drawing */ + if (pos_x + x3 * scale < piglit_width && pos_y + y3 * scale < piglit_height + && above_zero(scale2)) { /* a triangle is in scope of the window */ + /* Get approximal position of x1,y1, scaled according to base_angle */ + const float scaled_x1 = roundf(x1 * scale) + (above_zero(scale) ? g_inconsistency_x : -g_inconsistency_x); + const float scaled_y1 = roundf(y1 * scale) + (below_zero(scale) ? -1.0 : 0.0); + + /* Get approximal position of x2,y2, scaled according to base_angle and additional x-axis angle */ + const float scaled_x2 = roundf(x2 * scale); + float scaled_y2 = roundf(y2 * scale * scale2); + scaled_y2 = fabs(scaled_y2) > g_inconsistency_y + ? scaled_y2 + (below_zero(scale) + ? g_inconsistency_y : -g_inconsistency_y) + : below_zero(scaled_y2) ? -1.0 : 1.0; + + /* Get approximal position of x3,y3, scaled according to base_angle */ + const float scaled_x3 = roundf(x3 * scale) + (above_zero(scale) ? -g_inconsistency_x : g_inconsistency_x); + const float scaled_y3 = roundf(y3 * scale) + (below_zero(scale) ? -1.0 : 0.0); + + const float pos_x1 = (pos_x) + scaled_x1; + const float pos_y1 = (pos_y) + scaled_y1; + const float pos_x2 = (pos_x) + scaled_x2; + const float pos_y2 = (pos_y) + scaled_y2; + const float pos_x3 = (pos_x) + scaled_x3; + const float pos_y3 = (pos_y) + scaled_y3; + + if (pos_x1 < piglit_width && pos_x1 >= 0 && pos_y1 < piglit_height) { + int res = piglit_probe_pixel_rgb(pos_x1, pos_y1, color); + if (!res) { + is_failed |= 1; + fprintf(stderr, "Failed x1,y1 [%f,%f][%f,%f][%f,%f] base_angle: %f scale: %f: [%f,%f] cos(%f): %f \n", + pos_x + x1, pos_y + y1, pos_x + x2, pos_y + y2, pos_x + x3, pos_y + y3, + base_angle, scale, + pos_x1, pos_y1, + angle, scale2); + } + } + if (pos_x2 < piglit_width && pos_x2 >= 0 && pos_y2 < piglit_height) { + int res = piglit_probe_pixel_rgb(pos_x2, pos_y2, color); + if (!res) { + is_failed |= 1; + fprintf(stderr, "Failed x2,y2 [%f,%f][%f,%f][%f,%f] base_angle: %f scale: %f: [%f,%f] cos(%f): %f \n", + pos_x + x1, pos_y + y1, pos_x + x2, pos_y + y2, pos_x + x3, pos_y + y3, + base_angle, scale, + pos_x2, pos_y2, + angle, scale2); + } + } + if (pos_x3 < piglit_width && pos_x3 >= 0 && pos_y3 < piglit_height) { + int res = piglit_probe_pixel_rgb(pos_x3, pos_y3, color); + if (!res) { + is_failed |= 1; + fprintf(stderr, "Failed x3,y3 [%f,%f][%f,%f][%f,%f] base_angle: %f scale: %f: [%f,%f] cos(%f): %f \n", + pos_x + x1, pos_y + y1, pos_x + x2, pos_y + y2, pos_x + x3, pos_y + y3, + base_angle, scale, + pos_x3, pos_y3, + angle, scale2); + } + } + } + + glPopMatrix(); + angle += angle_shift; + x1 += size; + x2 += size; + x3 += size; + } + return is_failed; +} + +enum piglit_result +piglit_display() +{ + int is_failed = 0; + + /* Angle-step to rotate 0-vector */ + const float angle_shift = 20.0; + const int steps = 360 / angle_shift; + /* Initial positions to start drawing */ + const float pos_x_initial = piglit_width / 2; + const float pos_y_initial = piglit_height; + /* Max height of triangle */ + const int size = piglit_height / steps; + + float pos_x = pos_x_initial; + float pos_y = pos_y_initial - size; + float angle = 0.0; + /* We are drawing 'steps'-times going by y-axis */ + const float pos_y_shift = -size; + + glClearColor(0.5, 0.5, 0.5, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + + while(angle < 360.0) { + glPushMatrix(); + is_failed |= draw_triangles(pos_x, pos_y, angle); + glPopMatrix(); + angle += angle_shift; + pos_y += pos_y_shift; + } + + piglit_present_results(); + + return is_failed ? PIGLIT_FAIL : PIGLIT_PASS; +} diff --git a/tests/opengl.py b/tests/opengl.py index c599eb1..63afead 100644 --- a/tests/opengl.py +++ b/tests/opengl.py @@ -684,6 +684,7 @@ with profile.test_list.group_manager( g(['two-sided-lighting']) g(['user-clip']) g(['varray-disabled']) + g(['zero-vector-rotate']) g(['windowoverlap']) g(['copyteximage-border']) g(['copyteximage-clipping']) -- 2.7.4 _______________________________________________ Piglit mailing list Piglit@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/piglit