Put the surface translation (absolute position) into the surface
transformations list. This allows to set additional transformations
before and after the global translation.
Having the translation cached, changing the surface x,y now requires to
set the geometry.dirty flag.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
Previously, if a surface was transformed, it repainted as a whole,
regardless of the computed repaint region. As damage regions determine
repaint regions and whether a surface is considered for drawing at all,
this lead to disappearing surfaces if all surfaces were considered
transformed. Also transparent transformed surfaces were redrawn without
the surfaces below being properly redrawn, leading to alpha-saturation.
Fix that by making texture_region() use the proper global-to-surface
coordinate transformation for texture coordinates. This makes it
possible to call texture_region() also for transformed surfaces.
As texture coordinates may now lie outside the valid texture image, the
fragment shader is modified to check the fragment texture coordinates.
The special path texture_transformed_surface() is no longer used and is
removed.
This change fixes many of the rendering artifacts related to transformed
surfaces.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
For unifying the coordinate system handling, introduce functions for
converting explicitly between the global and the surface local
coordinate systems.
Use these functions in the input path, replacing
weston_surface_transform().
In the draw path, rewrite transform_vertex() to take in surface local
coordinates.
As shell now uses the new functions, the rotation origin is properly
placed in the middle of the surface.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
Add the key binding Super+Alt+MouseLeftButton to start rotating a
surface by dragging. The rotation is removed, when the drag is near the
rotation origin.
Rotated surface are a stress test for input event coordinate
transformations, damage region tracking, draw transformations, and
window move and resize orientation.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
When converting input coordinates from global to surface-local system,
apply the full inverse surface transformation instead of just
translation.
Move weston_surface_update_transform() implementation realier in the
file, no changes.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
The compositor will likely do an order of magnitude less matrix
inversions than point transformations with an inverse, hence we do not
really need the optimised path for single-shot invert-and-transform.
Expose only the computing of the explicit inverse matrix in the API.
However, the matrix inversion tests need access to the internal
functions. Designate a unit test build by #defining UNIT_TEST, and
export the internal functions in that case.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
Add a new directory tests/ for unit test applications. This directory
will be built only if --enable-tests is given to ./configure.
Add matrix-test application. It excercises especially the
weston_matrix_invert() and weston_matrix_inverse_transform() functions.
It has one test for correctness and precision, and other tests for
measuring the speed of various matrix operations.
For the record, the correctness test prints:
a random matrix:
1.112418e-02 2.628150e+00 8.205844e+02 -1.147526e-04
4.943677e-04 -1.117819e-04 -9.158849e-06 3.678122e-02
7.915063e-03 -3.093254e-04 -4.376583e+02 3.424706e-02
-2.504038e+02 2.481788e+03 -7.545445e+01 1.752909e-03
The matrix multiplied by its inverse, error:
0.000000e+00 -0.000000e+00 -0.000000e+00 -0.000000e+00
0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00
-0.000000e+00 -0.000000e+00 0.000000e+00 -0.000000e+00
0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00
max abs error: 0, original determinant 11595.2
Running a test loop for 10 seconds...
test fail, det: -0.00464805, error sup: inf
test fail, det: -0.0424053, error sup: 1.30787e-06
test fail, det: 5.15191, error sup: 1.15956e-06
tests: 6791767 ok, 1 not invertible but ok, 3 failed.
Total: 6791771 iterations.
These results are expected with the current precision thresholds in
src/matrix.c and tests/matrix-test.c. The random number generator is
seeded with a constant, so the random numbers should be the same on
every run. Machine speed and scheduling affect how many iterations are
run.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
Implement 4x4 matrix inversion based on LU-decomposition with partial
pivoting.
Instead of simply computing the inverse matrix explicitly, introduce the
type struct weston_inverse_matrix for storing the LU-decomposition and
the permutation from pivoting. Using doubles, this struct has greater
precision than struct weston_matrix.
If you need only few (less than 5, presumably) multiplications with the
inverse matrix, is it cheaper to use weston_inverse_matrix, and not
compute the inverse matrix explicitly into a weston_matrix.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
Remove the inverse matrix member from struct weston_transform. It is
easier (and probably faster, too) to create and store only forward
transformation matrices in a list, multiply them once, and then invert
the final matrix, rather than creating both forward and inverse
matrices, and multiplying both.
Add a stub for the 4x4 matrix inversion function.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
Add comments explaining the matrix storage and multiplication, so that
no-one else needs to decipher them again.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
Having at most one transformation object attached to a surface is not
enough anymore. If we have a surface that needs to be scaled to
fullscreen, and then we have the zoom animation, we already need two
transformations combined.
Implement support for multiple transformations by adding a transformation
list. The final transformation is the ordered composite of those in the
list. To avoid traversing the list every single time, add a dirty flag,
and cache the final transformation.
The existing transformation users (only zoom) are converted.
Note: surface drawing should honour all kinds of transformations, but
not damage region code nor input event translating code take
transformations into account, AFAICT. Therefore anything but translation
will probably behave badly until they are fixed.
Cc: Juan Zhao <juan.j.zhao@linux.intel.com>
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
This removes more special cases from weston_output_repaint() and we
avoid creating and destroying the surface for each animation frame.
We gain another special case in weston_compositor_top(), but that's
less of a problem, and we'll fix that later.
We've trimmed down the actual repaint loop to just iterating through the
surface list and calling weston_surface_draw(), so we push that to the
backend without too much code duplication.
This was supposed to draw black borders around a fullscreen surface that
was smaller than the output. We don't want to special case that in the
repaint loop, but may use a different shader or such. And we want the
surface to have an opaque region that covers the output so that that
will eliminate overdraw of lower surfaces.
This reverts commit fc6ccb868f.
We still need root permissions for drmDrop/SetMaster. Without
integration with ConsoleKit or systemd we also don't have access
to /dev/dri/cardX in the case where we open a new VT.
==30224== Conditional jump or move depends on uninitialised value(s)
==30224== at 0x40EE3A0: evdev_flush_motion (evdev.c:284)
==30224== by 0x40EE6DC: evdev_input_device_data (evdev.c:352)
==30224== by 0x4034710: wl_event_source_fd_dispatch (event-loop.c:76)
==30224== by 0x4035171: wl_event_loop_dispatch (event-loop.c:462)
==30224== by 0x4032F76: wl_display_run (wayland-server.c:785)
==30224== by 0x8050972: main (compositor.c:2183)
Signed-off-by: Tiago Vignatti <tiago.vignatti@intel.com>
I could crash Weston by trying to open another menu from a panel while
one menu from it was already showing.
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff40a9872 in popup_grab_focus (grab=0x761968, time=4130706528, surface=0x0, x=-227, y=15) at shell.c:440
440 if (surface->resource.client == client) {
(gdb) bt
0 0x00007ffff40a9872 in popup_grab_focus (grab=0x761968, time=4130706528, surface=0x0, x=-227, y=15) at shell.c:440
1 0x0000000000406977 in weston_device_repick (device=0x70b4e0, time=4130706528) at compositor.c:360
2 0x0000000000406a36 in weston_compositor_repick (compositor=0x619960) at compositor.c:382
3 0x0000000000406ac8 in destroy_surface (resource=0x6fc6f0) at compositor.c:397
4 0x00007ffff7bd33d8 in destroy_resource (element=0x6fc6f0, data=0x7fffffffd9fc) at wayland-server.c:355
5 0x00007ffff7bd8d98 in for_each_helper (entries=0x757808, func=0x7ffff7bd332c <destroy_resource>, data=0x7fffffffd9fc)
at wayland-util.c:264
6 0x00007ffff7bd8dd4 in wl_map_for_each (map=0x757808, func=0x7ffff7bd332c <destroy_resource>, data=0x7fffffffd9fc)
at wayland-util.c:270
7 0x00007ffff7bd34dc in wl_client_destroy (client=0x7577d0) at wayland-server.c:385
8 0x00007ffff7bd2e36 in wl_client_connection_data (fd=17, mask=1, data=0x7577d0) at wayland-server.c:187
9 0x00007ffff7bd5bde in wl_event_source_fd_dispatch (source=0x74cda0, ep=0x7fffffffdae0) at event-loop.c:76
10 0x00007ffff7bd665b in wl_event_loop_dispatch (loop=0x618900, timeout=-1) at event-loop.c:462
11 0x00007ffff7bd42a9 in wl_display_run (display=0x6188b0) at wayland-server.c:785
12 0x000000000040b1e1 in main (argc=1, argv=0x7fffffffdef8) at compositor.c:2182
Modify popup_grab_focus() to deal with a NULL surface.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
When we destroy a surface, we damage the surface below so that the area
exposed by the disappearing surface will be repainted. However, if that
surface also is destroyed, the damage information is lost and we fail to
repaint that area.
This commit introduces weston_surface_flush_damage(), which flushes the
surface damage the the surface below when a surface is destroyed. When
multiple surfaces are destroyed at the same time, the damage now accumulates
and sinks down through the surface stack as it should.
gbm_bo_create_from_egl_image() should catch this based on the
GBM_BO_USE_CURSOR_64X64 flag. It currently doesn't so we end up with
a cursor buffer with invalid stride.
If we don't cancel the repaint, we end up pointlessly redrawing the output.
What's worse is that pageflipping to the new buffer eventually fails and
we miss the finish_frame callback, leaving the compositor stuck when we
re-enter the vt.
Normally the repaint will trigger a pageflip, which flips back to our
fb, but that doesn't work if the kms output has been turned off or
set to a different mode.