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

Reply via email to