Merge remote-tracking branch 'pq/transform-v1'
This commit is contained in:
+1
-1
@@ -1 +1 @@
|
|||||||
SUBDIRS = shared src clients data protocol
|
SUBDIRS = shared src clients data protocol tests
|
||||||
|
|||||||
+4
-2
@@ -1,3 +1,4 @@
|
|||||||
|
clickdot
|
||||||
desktop-shell-client-protocol.h
|
desktop-shell-client-protocol.h
|
||||||
desktop-shell-protocol.c
|
desktop-shell-protocol.c
|
||||||
dnd
|
dnd
|
||||||
@@ -12,11 +13,12 @@ screenshooter-protocol.c
|
|||||||
screenshot
|
screenshot
|
||||||
simple-egl
|
simple-egl
|
||||||
simple-shm
|
simple-shm
|
||||||
|
simple-touch
|
||||||
smoke
|
smoke
|
||||||
tablet-shell-client-protocol.h
|
tablet-shell-client-protocol.h
|
||||||
tablet-shell-protocol.c
|
tablet-shell-protocol.c
|
||||||
terminal
|
terminal
|
||||||
view
|
view
|
||||||
wayland-desktop-shell
|
weston-desktop-shell
|
||||||
wayland-tablet-shell
|
weston-tablet-shell
|
||||||
wscreensaver
|
wscreensaver
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ clients_programs = \
|
|||||||
smoke \
|
smoke \
|
||||||
resizor \
|
resizor \
|
||||||
eventdemo \
|
eventdemo \
|
||||||
|
clickdot \
|
||||||
$(full_gl_client_programs)
|
$(full_gl_client_programs)
|
||||||
|
|
||||||
desktop_shell = weston-desktop-shell
|
desktop_shell = weston-desktop-shell
|
||||||
@@ -83,6 +84,9 @@ resizor_LDADD = $(toolkit_libs)
|
|||||||
eventdemo_SOURCES = eventdemo.c
|
eventdemo_SOURCES = eventdemo.c
|
||||||
eventdemo_LDADD = $(toolkit_libs)
|
eventdemo_LDADD = $(toolkit_libs)
|
||||||
|
|
||||||
|
clickdot_SOURCES = clickdot.c
|
||||||
|
clickdot_LDADD = $(toolkit_libs)
|
||||||
|
|
||||||
weston_desktop_shell_SOURCES = \
|
weston_desktop_shell_SOURCES = \
|
||||||
desktop-shell.c \
|
desktop-shell.c \
|
||||||
desktop-shell-client-protocol.h \
|
desktop-shell-client-protocol.h \
|
||||||
|
|||||||
@@ -0,0 +1,181 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2010 Intel Corporation
|
||||||
|
* Copyright © 2012 Collabora, Ltd.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
|
* that the name of the copyright holders not be used in advertising or
|
||||||
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
|
* OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <cairo.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <linux/input.h>
|
||||||
|
#include <wayland-client.h>
|
||||||
|
|
||||||
|
#include "window.h"
|
||||||
|
|
||||||
|
#include <X11/keysym.h>
|
||||||
|
|
||||||
|
struct clickdot {
|
||||||
|
struct display *display;
|
||||||
|
struct window *window;
|
||||||
|
struct widget *widget;
|
||||||
|
|
||||||
|
int32_t x, y;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
redraw_handler(struct widget *widget, void *data)
|
||||||
|
{
|
||||||
|
static const double r = 10.0;
|
||||||
|
struct clickdot *clickdot = data;
|
||||||
|
cairo_surface_t *surface;
|
||||||
|
cairo_t *cr;
|
||||||
|
struct rectangle allocation;
|
||||||
|
|
||||||
|
widget_get_allocation(clickdot->widget, &allocation);
|
||||||
|
|
||||||
|
surface = window_get_surface(clickdot->window);
|
||||||
|
|
||||||
|
cr = cairo_create(surface);
|
||||||
|
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
|
||||||
|
cairo_rectangle(cr,
|
||||||
|
allocation.x,
|
||||||
|
allocation.y,
|
||||||
|
allocation.width,
|
||||||
|
allocation.height);
|
||||||
|
cairo_set_source_rgba(cr, 0, 0, 0, 0.8);
|
||||||
|
cairo_fill(cr);
|
||||||
|
|
||||||
|
cairo_translate(cr, clickdot->x + 0.5, clickdot->y + 0.5);
|
||||||
|
cairo_set_line_width(cr, 1.0);
|
||||||
|
cairo_set_source_rgb(cr, 0.1, 0.9, 0.9);
|
||||||
|
cairo_move_to(cr, 0.0, -r);
|
||||||
|
cairo_line_to(cr, 0.0, r);
|
||||||
|
cairo_move_to(cr, -r, 0.0);
|
||||||
|
cairo_line_to(cr, r, 0.0);
|
||||||
|
cairo_arc(cr, 0.0, 0.0, r, 0.0, 2.0 * M_PI);
|
||||||
|
cairo_stroke(cr);
|
||||||
|
|
||||||
|
cairo_destroy(cr);
|
||||||
|
|
||||||
|
cairo_surface_destroy(surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
keyboard_focus_handler(struct window *window,
|
||||||
|
struct input *device, void *data)
|
||||||
|
{
|
||||||
|
struct clickdot *clickdot = data;
|
||||||
|
|
||||||
|
window_schedule_redraw(clickdot->window);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
key_handler(struct window *window, struct input *input, uint32_t time,
|
||||||
|
uint32_t key, uint32_t sym, uint32_t state, void *data)
|
||||||
|
{
|
||||||
|
struct clickdot *clickdot = data;
|
||||||
|
|
||||||
|
if (state == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (sym) {
|
||||||
|
case XK_Escape:
|
||||||
|
display_exit(clickdot->display);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
button_handler(struct widget *widget,
|
||||||
|
struct input *input, uint32_t time,
|
||||||
|
int button, int state, void *data)
|
||||||
|
{
|
||||||
|
struct clickdot *clickdot = data;
|
||||||
|
|
||||||
|
if (state && button == BTN_LEFT)
|
||||||
|
input_get_position(input, &clickdot->x, &clickdot->y);
|
||||||
|
|
||||||
|
widget_schedule_redraw(widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct clickdot *
|
||||||
|
clickdot_create(struct display *display)
|
||||||
|
{
|
||||||
|
struct clickdot *clickdot;
|
||||||
|
|
||||||
|
clickdot = malloc(sizeof *clickdot);
|
||||||
|
if (clickdot == NULL)
|
||||||
|
return clickdot;
|
||||||
|
memset(clickdot, 0, sizeof *clickdot);
|
||||||
|
|
||||||
|
clickdot->window = window_create(display, 500, 400);
|
||||||
|
clickdot->widget = frame_create(clickdot->window, clickdot);
|
||||||
|
window_set_title(clickdot->window, "Wayland ClickDot");
|
||||||
|
clickdot->display = display;
|
||||||
|
|
||||||
|
window_set_key_handler(clickdot->window, key_handler);
|
||||||
|
window_set_user_data(clickdot->window, clickdot);
|
||||||
|
window_set_keyboard_focus_handler(clickdot->window,
|
||||||
|
keyboard_focus_handler);
|
||||||
|
|
||||||
|
widget_set_redraw_handler(clickdot->widget, redraw_handler);
|
||||||
|
widget_set_button_handler(clickdot->widget, button_handler);
|
||||||
|
|
||||||
|
widget_schedule_resize(clickdot->widget, 500, 400);
|
||||||
|
clickdot->x = 250;
|
||||||
|
clickdot->y = 200;
|
||||||
|
|
||||||
|
return clickdot;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clickdot_destroy(struct clickdot *clickdot)
|
||||||
|
{
|
||||||
|
widget_destroy(clickdot->widget);
|
||||||
|
window_destroy(clickdot->window);
|
||||||
|
free(clickdot);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct display *display;
|
||||||
|
struct clickdot *clickdot;
|
||||||
|
|
||||||
|
display = display_create(&argc, &argv, NULL);
|
||||||
|
if (display == NULL) {
|
||||||
|
fprintf(stderr, "failed to create display: %m\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
clickdot = clickdot_create(display);
|
||||||
|
|
||||||
|
display_run(display);
|
||||||
|
|
||||||
|
clickdot_destroy(clickdot);
|
||||||
|
display_destroy(display);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
+5
-1
@@ -148,6 +148,9 @@ AC_ARG_ENABLE(tablet-shell, [ --enable-tablet-shell],,
|
|||||||
AM_CONDITIONAL(ENABLE_TABLET_SHELL,
|
AM_CONDITIONAL(ENABLE_TABLET_SHELL,
|
||||||
test x$enable_tablet_shell == xyes)
|
test x$enable_tablet_shell == xyes)
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(tests, [ --enable-tests],,enable_tests=yes)
|
||||||
|
AM_CONDITIONAL(BUILD_TESTS, test x$enable_tests == xyes)
|
||||||
|
|
||||||
if test "x$GCC" = "xyes"; then
|
if test "x$GCC" = "xyes"; then
|
||||||
GCC_CFLAGS="-Wall -g -Wstrict-prototypes -Wmissing-prototypes -fvisibility=hidden"
|
GCC_CFLAGS="-Wall -g -Wstrict-prototypes -Wmissing-prototypes -fvisibility=hidden"
|
||||||
fi
|
fi
|
||||||
@@ -160,7 +163,8 @@ AC_CONFIG_FILES([Makefile
|
|||||||
src/Makefile
|
src/Makefile
|
||||||
clients/Makefile
|
clients/Makefile
|
||||||
data/Makefile
|
data/Makefile
|
||||||
protocol/Makefile])
|
protocol/Makefile
|
||||||
|
tests/Makefile])
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
|
|
||||||
if test "x$enable_setuid_install" == xyes; then
|
if test "x$enable_setuid_install" == xyes; then
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
wayland-compositor
|
weston
|
||||||
screenshooter-protocol.c
|
screenshooter-protocol.c
|
||||||
screenshooter-server-protocol.h
|
screenshooter-server-protocol.h
|
||||||
tablet-shell-protocol.c
|
tablet-shell-protocol.c
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ weston_SOURCES = \
|
|||||||
screenshooter-protocol.c \
|
screenshooter-protocol.c \
|
||||||
screenshooter-server-protocol.h \
|
screenshooter-server-protocol.h \
|
||||||
util.c \
|
util.c \
|
||||||
|
matrix.c \
|
||||||
|
matrix.h \
|
||||||
$(xserver_launcher_sources)
|
$(xserver_launcher_sources)
|
||||||
|
|
||||||
if ENABLE_SETUID_INSTALL
|
if ENABLE_SETUID_INSTALL
|
||||||
|
|||||||
+15
-10
@@ -97,16 +97,18 @@ drm_output_prepare_scanout_surface(struct drm_output *output)
|
|||||||
struct weston_surface, link);
|
struct weston_surface, link);
|
||||||
|
|
||||||
if (es->visual != WESTON_RGB_VISUAL ||
|
if (es->visual != WESTON_RGB_VISUAL ||
|
||||||
es->x != output->base.x ||
|
es->geometry.x != output->base.x ||
|
||||||
es->y != output->base.y ||
|
es->geometry.y != output->base.y ||
|
||||||
es->width != output->base.current->width ||
|
es->geometry.width != output->base.current->width ||
|
||||||
es->height != output->base.current->height ||
|
es->geometry.height != output->base.current->height ||
|
||||||
|
es->transform.enabled ||
|
||||||
es->image == EGL_NO_IMAGE_KHR)
|
es->image == EGL_NO_IMAGE_KHR)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
bo = gbm_bo_create_from_egl_image(c->gbm,
|
bo = gbm_bo_create_from_egl_image(c->gbm,
|
||||||
c->base.display, es->image,
|
c->base.display, es->image,
|
||||||
es->width, es->height,
|
es->geometry.width,
|
||||||
|
es->geometry.height,
|
||||||
GBM_BO_USE_SCANOUT);
|
GBM_BO_USE_SCANOUT);
|
||||||
|
|
||||||
handle = gbm_bo_get_handle(bo).s32;
|
handle = gbm_bo_get_handle(bo).s32;
|
||||||
@@ -231,8 +233,10 @@ drm_output_set_cursor(struct weston_output *output_base,
|
|||||||
}
|
}
|
||||||
|
|
||||||
pixman_region32_init_rect(&cursor_region,
|
pixman_region32_init_rect(&cursor_region,
|
||||||
eid->sprite->x, eid->sprite->y,
|
eid->sprite->geometry.x,
|
||||||
eid->sprite->width, eid->sprite->height);
|
eid->sprite->geometry.y,
|
||||||
|
eid->sprite->geometry.width,
|
||||||
|
eid->sprite->geometry.height);
|
||||||
|
|
||||||
pixman_region32_intersect_rect(&cursor_region, &cursor_region,
|
pixman_region32_intersect_rect(&cursor_region, &cursor_region,
|
||||||
output->base.x, output->base.y,
|
output->base.x, output->base.y,
|
||||||
@@ -245,7 +249,8 @@ drm_output_set_cursor(struct weston_output *output_base,
|
|||||||
if (eid->sprite->image == EGL_NO_IMAGE_KHR)
|
if (eid->sprite->image == EGL_NO_IMAGE_KHR)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (eid->sprite->width > 64 || eid->sprite->height > 64)
|
if (eid->sprite->geometry.width > 64 ||
|
||||||
|
eid->sprite->geometry.height > 64)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
bo = gbm_bo_create_from_egl_image(c->gbm,
|
bo = gbm_bo_create_from_egl_image(c->gbm,
|
||||||
@@ -272,8 +277,8 @@ drm_output_set_cursor(struct weston_output *output_base,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = drmModeMoveCursor(c->drm.fd, output->crtc_id,
|
ret = drmModeMoveCursor(c->drm.fd, output->crtc_id,
|
||||||
eid->sprite->x - output->base.x,
|
eid->sprite->geometry.x - output->base.x,
|
||||||
eid->sprite->y - output->base.y);
|
eid->sprite->geometry.y - output->base.y);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
fprintf(stderr, "failed to move cursor: %s\n", strerror(-ret));
|
fprintf(stderr, "failed to move cursor: %s\n", strerror(-ret));
|
||||||
goto out;
|
goto out;
|
||||||
|
|||||||
+280
-125
@@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2010-2011 Intel Corporation
|
* Copyright © 2010-2011 Intel Corporation
|
||||||
* Copyright © 2008-2011 Kristian Høgsberg
|
* Copyright © 2008-2011 Kristian Høgsberg
|
||||||
|
* Copyright © 2012 Collabora, Ltd.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, distribute, and sell this software and
|
* Permission to use, copy, modify, distribute, and sell this software and
|
||||||
* its documentation for any purpose is hereby granted without fee, provided
|
* its documentation for any purpose is hereby granted without fee, provided
|
||||||
@@ -189,10 +190,10 @@ weston_surface_create(struct weston_compositor *compositor,
|
|||||||
surface->compositor = compositor;
|
surface->compositor = compositor;
|
||||||
surface->visual = WESTON_NONE_VISUAL;
|
surface->visual = WESTON_NONE_VISUAL;
|
||||||
surface->image = EGL_NO_IMAGE_KHR;
|
surface->image = EGL_NO_IMAGE_KHR;
|
||||||
surface->x = x;
|
surface->geometry.x = x;
|
||||||
surface->y = y;
|
surface->geometry.y = y;
|
||||||
surface->width = width;
|
surface->geometry.width = width;
|
||||||
surface->height = height;
|
surface->geometry.height = height;
|
||||||
surface->alpha = 255;
|
surface->alpha = 255;
|
||||||
|
|
||||||
surface->fullscreen_output = NULL;
|
surface->fullscreen_output = NULL;
|
||||||
@@ -205,7 +206,12 @@ weston_surface_create(struct weston_compositor *compositor,
|
|||||||
|
|
||||||
surface->buffer_destroy_listener.func = surface_handle_buffer_destroy;
|
surface->buffer_destroy_listener.func = surface_handle_buffer_destroy;
|
||||||
|
|
||||||
surface->transform = NULL;
|
wl_list_init(&surface->geometry.transformation_list);
|
||||||
|
wl_list_insert(&surface->geometry.transformation_list,
|
||||||
|
&surface->transform.position.link);
|
||||||
|
weston_matrix_init(&surface->transform.position.matrix);
|
||||||
|
pixman_region32_init(&surface->transform.boundingbox);
|
||||||
|
surface->geometry.dirty = 1;
|
||||||
|
|
||||||
return surface;
|
return surface;
|
||||||
}
|
}
|
||||||
@@ -226,25 +232,189 @@ weston_surface_set_color(struct weston_surface *surface,
|
|||||||
surface->shader = &surface->compositor->solid_shader;
|
surface->shader = &surface->compositor->solid_shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
surface_compute_bbox(struct weston_surface *surface, int32_t sx, int32_t sy,
|
||||||
|
int32_t width, int32_t height,
|
||||||
|
pixman_region32_t *bbox)
|
||||||
|
{
|
||||||
|
int min_x = INT_MAX, min_y = INT_MAX, max_x = INT_MIN, max_y = INT_MIN;
|
||||||
|
int32_t s[4][2] = {
|
||||||
|
{ sx, sy },
|
||||||
|
{ sx, sy + height },
|
||||||
|
{ sx + width, sy },
|
||||||
|
{ sx + width, sy + height }
|
||||||
|
};
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 4; ++i) {
|
||||||
|
int32_t x, y;
|
||||||
|
weston_surface_to_global(surface, s[i][0], s[i][1], &x, &y);
|
||||||
|
if (x < min_x)
|
||||||
|
min_x = x;
|
||||||
|
if (x > max_x)
|
||||||
|
max_x = x;
|
||||||
|
if (y < min_y)
|
||||||
|
min_y = y;
|
||||||
|
if (y > max_y)
|
||||||
|
max_y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* weston_surface_to_global rounds with floor(), add the
|
||||||
|
* minimum required safety margin.
|
||||||
|
*/
|
||||||
|
pixman_region32_init_rect(bbox, min_x, min_y,
|
||||||
|
max_x - min_x + 1, max_y - min_y + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
WL_EXPORT void
|
||||||
|
weston_surface_update_transform(struct weston_surface *surface)
|
||||||
|
{
|
||||||
|
struct weston_matrix *matrix = &surface->transform.matrix;
|
||||||
|
struct weston_matrix *inverse = &surface->transform.inverse;
|
||||||
|
struct weston_transform *tform;
|
||||||
|
|
||||||
|
if (!surface->geometry.dirty)
|
||||||
|
return;
|
||||||
|
|
||||||
|
surface->geometry.dirty = 0;
|
||||||
|
|
||||||
|
pixman_region32_fini(&surface->transform.boundingbox);
|
||||||
|
|
||||||
|
/* transform.position is always in transformation_list */
|
||||||
|
if (surface->geometry.transformation_list.next ==
|
||||||
|
&surface->transform.position.link &&
|
||||||
|
surface->geometry.transformation_list.prev ==
|
||||||
|
&surface->transform.position.link) {
|
||||||
|
surface->transform.enabled = 0;
|
||||||
|
|
||||||
|
pixman_region32_init_rect(&surface->transform.boundingbox,
|
||||||
|
surface->geometry.x,
|
||||||
|
surface->geometry.y,
|
||||||
|
surface->geometry.width,
|
||||||
|
surface->geometry.height);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
surface->transform.enabled = 1;
|
||||||
|
|
||||||
|
surface->transform.position.matrix.d[12] = surface->geometry.x;
|
||||||
|
surface->transform.position.matrix.d[13] = surface->geometry.y;
|
||||||
|
|
||||||
|
weston_matrix_init(matrix);
|
||||||
|
wl_list_for_each(tform, &surface->geometry.transformation_list, link)
|
||||||
|
weston_matrix_multiply(matrix, &tform->matrix);
|
||||||
|
|
||||||
|
if (weston_matrix_invert(inverse, matrix) < 0) {
|
||||||
|
/* Oops, bad total transformation, not invertible */
|
||||||
|
surface->transform.enabled = 0;
|
||||||
|
fprintf(stderr, "error: weston_surface %p"
|
||||||
|
" transformation not invertible.\n", surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
surface_compute_bbox(surface, 0, 0, surface->geometry.width,
|
||||||
|
surface->geometry.height,
|
||||||
|
&surface->transform.boundingbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
WL_EXPORT void
|
||||||
|
weston_surface_to_global(struct weston_surface *surface,
|
||||||
|
int32_t sx, int32_t sy, int32_t *x, int32_t *y)
|
||||||
|
{
|
||||||
|
weston_surface_update_transform(surface);
|
||||||
|
|
||||||
|
if (surface->transform.enabled) {
|
||||||
|
struct weston_vector v = { { sx, sy, 0.0f, 1.0f } };
|
||||||
|
|
||||||
|
weston_matrix_transform(&surface->transform.matrix, &v);
|
||||||
|
|
||||||
|
if (fabsf(v.f[3]) < 1e-6) {
|
||||||
|
fprintf(stderr, "warning: numerical instability in "
|
||||||
|
"weston_surface_to_global(), divisor = %g\n",
|
||||||
|
v.f[3]);
|
||||||
|
*x = 0;
|
||||||
|
*y = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*x = floorf(v.f[0] / v.f[3]);
|
||||||
|
*y = floorf(v.f[1] / v.f[3]);
|
||||||
|
} else {
|
||||||
|
*x = sx + surface->geometry.x;
|
||||||
|
*y = sy + surface->geometry.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
surface_from_global_float(struct weston_surface *surface,
|
||||||
|
int32_t x, int32_t y, GLfloat *sx, GLfloat *sy)
|
||||||
|
{
|
||||||
|
if (surface->transform.enabled) {
|
||||||
|
struct weston_vector v = { { x, y, 0.0f, 1.0f } };
|
||||||
|
|
||||||
|
weston_matrix_transform(&surface->transform.inverse, &v);
|
||||||
|
|
||||||
|
if (fabsf(v.f[3]) < 1e-6) {
|
||||||
|
fprintf(stderr, "warning: numerical instability in "
|
||||||
|
"weston_surface_from_global(), divisor = %g\n",
|
||||||
|
v.f[3]);
|
||||||
|
*sx = 0;
|
||||||
|
*sy = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*sx = v.f[0] / v.f[3];
|
||||||
|
*sy = v.f[1] / v.f[3];
|
||||||
|
} else {
|
||||||
|
*sx = x - surface->geometry.x;
|
||||||
|
*sy = y - surface->geometry.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WL_EXPORT void
|
||||||
|
weston_surface_from_global(struct weston_surface *surface,
|
||||||
|
int32_t x, int32_t y, int32_t *sx, int32_t *sy)
|
||||||
|
{
|
||||||
|
GLfloat sxf, syf;
|
||||||
|
|
||||||
|
weston_surface_update_transform(surface);
|
||||||
|
|
||||||
|
surface_from_global_float(surface, x, y, &sxf, &syf);
|
||||||
|
*sx = floorf(sxf);
|
||||||
|
*sy = floorf(syf);
|
||||||
|
}
|
||||||
|
|
||||||
WL_EXPORT void
|
WL_EXPORT void
|
||||||
weston_surface_damage_rectangle(struct weston_surface *surface,
|
weston_surface_damage_rectangle(struct weston_surface *surface,
|
||||||
int32_t x, int32_t y,
|
int32_t sx, int32_t sy,
|
||||||
int32_t width, int32_t height)
|
int32_t width, int32_t height)
|
||||||
{
|
{
|
||||||
struct weston_compositor *compositor = surface->compositor;
|
weston_surface_update_transform(surface);
|
||||||
|
|
||||||
pixman_region32_union_rect(&surface->damage,
|
if (surface->transform.enabled) {
|
||||||
&surface->damage,
|
pixman_region32_t box;
|
||||||
surface->x + x, surface->y + y,
|
surface_compute_bbox(surface, sx, sy, width, height, &box);
|
||||||
width, height);
|
pixman_region32_union(&surface->damage, &surface->damage,
|
||||||
weston_compositor_schedule_repaint(compositor);
|
&box);
|
||||||
|
pixman_region32_fini(&box);
|
||||||
|
} else {
|
||||||
|
int32_t x, y;
|
||||||
|
weston_surface_to_global(surface, sx, sy, &x, &y);
|
||||||
|
pixman_region32_union_rect(&surface->damage, &surface->damage,
|
||||||
|
x, y, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
weston_compositor_schedule_repaint(surface->compositor);
|
||||||
}
|
}
|
||||||
|
|
||||||
WL_EXPORT void
|
WL_EXPORT void
|
||||||
weston_surface_damage(struct weston_surface *surface)
|
weston_surface_damage(struct weston_surface *surface)
|
||||||
{
|
{
|
||||||
weston_surface_damage_rectangle(surface, 0, 0,
|
weston_surface_update_transform(surface);
|
||||||
surface->width, surface->height);
|
|
||||||
|
pixman_region32_union(&surface->damage, &surface->damage,
|
||||||
|
&surface->transform.boundingbox);
|
||||||
|
|
||||||
|
weston_compositor_schedule_repaint(surface->compositor);
|
||||||
}
|
}
|
||||||
|
|
||||||
WL_EXPORT void
|
WL_EXPORT void
|
||||||
@@ -260,10 +430,10 @@ weston_surface_damage_below(struct weston_surface *surface)
|
|||||||
|
|
||||||
below = container_of(surface->link.next, struct weston_surface, link);
|
below = container_of(surface->link.next, struct weston_surface, link);
|
||||||
|
|
||||||
pixman_region32_union_rect(&below->damage,
|
weston_surface_update_transform(surface);
|
||||||
&below->damage,
|
pixman_region32_union(&below->damage, &below->damage,
|
||||||
surface->x, surface->y,
|
&surface->transform.boundingbox);
|
||||||
surface->width, surface->height);
|
|
||||||
weston_compositor_schedule_repaint(surface->compositor);
|
weston_compositor_schedule_repaint(surface->compositor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,10 +458,11 @@ weston_surface_configure(struct weston_surface *surface,
|
|||||||
{
|
{
|
||||||
weston_surface_damage_below(surface);
|
weston_surface_damage_below(surface);
|
||||||
|
|
||||||
surface->x = x;
|
surface->geometry.x = x;
|
||||||
surface->y = y;
|
surface->geometry.y = y;
|
||||||
surface->width = width;
|
surface->geometry.width = width;
|
||||||
surface->height = height;
|
surface->geometry.height = height;
|
||||||
|
surface->geometry.dirty = 1;
|
||||||
|
|
||||||
weston_surface_assign_output(surface);
|
weston_surface_assign_output(surface);
|
||||||
weston_surface_damage(surface);
|
weston_surface_damage(surface);
|
||||||
@@ -299,20 +470,14 @@ weston_surface_configure(struct weston_surface *surface,
|
|||||||
pixman_region32_fini(&surface->opaque);
|
pixman_region32_fini(&surface->opaque);
|
||||||
if (surface->visual == WESTON_RGB_VISUAL)
|
if (surface->visual == WESTON_RGB_VISUAL)
|
||||||
pixman_region32_init_rect(&surface->opaque,
|
pixman_region32_init_rect(&surface->opaque,
|
||||||
surface->x, surface->y,
|
surface->geometry.x,
|
||||||
surface->width, surface->height);
|
surface->geometry.y,
|
||||||
|
surface->geometry.width,
|
||||||
|
surface->geometry.height);
|
||||||
else
|
else
|
||||||
pixman_region32_init(&surface->opaque);
|
pixman_region32_init(&surface->opaque);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
weston_surface_transform(struct weston_surface *surface,
|
|
||||||
int32_t x, int32_t y, int32_t *sx, int32_t *sy)
|
|
||||||
{
|
|
||||||
*sx = x - surface->x;
|
|
||||||
*sy = y - surface->y;
|
|
||||||
}
|
|
||||||
|
|
||||||
WL_EXPORT uint32_t
|
WL_EXPORT uint32_t
|
||||||
weston_compositor_get_time(void)
|
weston_compositor_get_time(void)
|
||||||
{
|
{
|
||||||
@@ -344,7 +509,7 @@ weston_device_repick(struct wl_input_device *device, uint32_t time)
|
|||||||
|
|
||||||
focus = (struct weston_surface *) device->grab->focus;
|
focus = (struct weston_surface *) device->grab->focus;
|
||||||
if (focus)
|
if (focus)
|
||||||
weston_surface_transform(focus, device->x, device->y,
|
weston_surface_from_global(focus, device->x, device->y,
|
||||||
&device->grab->x, &device->grab->y);
|
&device->grab->x, &device->grab->y);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,6 +552,7 @@ destroy_surface(struct wl_resource *resource)
|
|||||||
|
|
||||||
wl_list_remove(&surface->buffer_link);
|
wl_list_remove(&surface->buffer_link);
|
||||||
|
|
||||||
|
pixman_region32_fini(&surface->transform.boundingbox);
|
||||||
pixman_region32_fini(&surface->damage);
|
pixman_region32_fini(&surface->damage);
|
||||||
pixman_region32_fini(&surface->opaque);
|
pixman_region32_fini(&surface->opaque);
|
||||||
|
|
||||||
@@ -442,7 +608,7 @@ weston_buffer_attach(struct wl_buffer *buffer, struct wl_surface *surface)
|
|||||||
ec->image_target_texture_2d(GL_TEXTURE_2D, es->image);
|
ec->image_target_texture_2d(GL_TEXTURE_2D, es->image);
|
||||||
|
|
||||||
es->visual = WESTON_ARGB_VISUAL;
|
es->visual = WESTON_ARGB_VISUAL;
|
||||||
es->pitch = es->width;
|
es->pitch = es->geometry.width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -451,6 +617,7 @@ texture_region(struct weston_surface *es, pixman_region32_t *region)
|
|||||||
{
|
{
|
||||||
struct weston_compositor *ec = es->compositor;
|
struct weston_compositor *ec = es->compositor;
|
||||||
GLfloat *v, inv_width, inv_height;
|
GLfloat *v, inv_width, inv_height;
|
||||||
|
GLfloat sx, sy;
|
||||||
pixman_box32_t *rectangles;
|
pixman_box32_t *rectangles;
|
||||||
unsigned int *p;
|
unsigned int *p;
|
||||||
int i, n;
|
int i, n;
|
||||||
@@ -459,28 +626,36 @@ texture_region(struct weston_surface *es, pixman_region32_t *region)
|
|||||||
v = wl_array_add(&ec->vertices, n * 16 * sizeof *v);
|
v = wl_array_add(&ec->vertices, n * 16 * sizeof *v);
|
||||||
p = wl_array_add(&ec->indices, n * 6 * sizeof *p);
|
p = wl_array_add(&ec->indices, n * 6 * sizeof *p);
|
||||||
inv_width = 1.0 / es->pitch;
|
inv_width = 1.0 / es->pitch;
|
||||||
inv_height = 1.0 / es->height;
|
inv_height = 1.0 / es->geometry.height;
|
||||||
|
|
||||||
for (i = 0; i < n; i++, v += 16, p += 6) {
|
for (i = 0; i < n; i++, v += 16, p += 6) {
|
||||||
|
surface_from_global_float(es, rectangles[i].x1,
|
||||||
|
rectangles[i].y1, &sx, &sy);
|
||||||
v[ 0] = rectangles[i].x1;
|
v[ 0] = rectangles[i].x1;
|
||||||
v[ 1] = rectangles[i].y1;
|
v[ 1] = rectangles[i].y1;
|
||||||
v[ 2] = (GLfloat) (rectangles[i].x1 - es->x) * inv_width;
|
v[ 2] = sx * inv_width;
|
||||||
v[ 3] = (GLfloat) (rectangles[i].y1 - es->y) * inv_height;
|
v[ 3] = sy * inv_height;
|
||||||
|
|
||||||
|
surface_from_global_float(es, rectangles[i].x1,
|
||||||
|
rectangles[i].y2, &sx, &sy);
|
||||||
v[ 4] = rectangles[i].x1;
|
v[ 4] = rectangles[i].x1;
|
||||||
v[ 5] = rectangles[i].y2;
|
v[ 5] = rectangles[i].y2;
|
||||||
v[ 6] = v[ 2];
|
v[ 6] = sx * inv_width;
|
||||||
v[ 7] = (GLfloat) (rectangles[i].y2 - es->y) * inv_height;
|
v[ 7] = sy * inv_height;
|
||||||
|
|
||||||
|
surface_from_global_float(es, rectangles[i].x2,
|
||||||
|
rectangles[i].y1, &sx, &sy);
|
||||||
v[ 8] = rectangles[i].x2;
|
v[ 8] = rectangles[i].x2;
|
||||||
v[ 9] = rectangles[i].y1;
|
v[ 9] = rectangles[i].y1;
|
||||||
v[10] = (GLfloat) (rectangles[i].x2 - es->x) * inv_width;
|
v[10] = sx * inv_width;
|
||||||
v[11] = v[ 3];
|
v[11] = sy * inv_height;
|
||||||
|
|
||||||
|
surface_from_global_float(es, rectangles[i].x2,
|
||||||
|
rectangles[i].y2, &sx, &sy);
|
||||||
v[12] = rectangles[i].x2;
|
v[12] = rectangles[i].x2;
|
||||||
v[13] = rectangles[i].y2;
|
v[13] = rectangles[i].y2;
|
||||||
v[14] = v[10];
|
v[14] = sx * inv_width;
|
||||||
v[15] = v[ 7];
|
v[15] = sy * inv_height;
|
||||||
|
|
||||||
p[0] = i * 4 + 0;
|
p[0] = i * 4 + 0;
|
||||||
p[1] = i * 4 + 1;
|
p[1] = i * 4 + 1;
|
||||||
@@ -493,51 +668,6 @@ texture_region(struct weston_surface *es, pixman_region32_t *region)
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
transform_vertex(struct weston_surface *surface,
|
|
||||||
GLfloat x, GLfloat y, GLfloat u, GLfloat v, GLfloat *r)
|
|
||||||
{
|
|
||||||
struct weston_vector t;
|
|
||||||
|
|
||||||
t.f[0] = x;
|
|
||||||
t.f[1] = y;
|
|
||||||
t.f[2] = 0.0;
|
|
||||||
t.f[3] = 1.0;
|
|
||||||
|
|
||||||
weston_matrix_transform(&surface->transform->matrix, &t);
|
|
||||||
|
|
||||||
r[ 0] = t.f[0];
|
|
||||||
r[ 1] = t.f[1];
|
|
||||||
r[ 2] = u;
|
|
||||||
r[ 3] = v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
texture_transformed_surface(struct weston_surface *es)
|
|
||||||
{
|
|
||||||
struct weston_compositor *ec = es->compositor;
|
|
||||||
GLfloat *v;
|
|
||||||
unsigned int *p;
|
|
||||||
|
|
||||||
v = wl_array_add(&ec->vertices, 16 * sizeof *v);
|
|
||||||
p = wl_array_add(&ec->indices, 6 * sizeof *p);
|
|
||||||
|
|
||||||
transform_vertex(es, es->x, es->y, 0.0, 0.0, &v[0]);
|
|
||||||
transform_vertex(es, es->x, es->y + es->height, 0.0, 1.0, &v[4]);
|
|
||||||
transform_vertex(es, es->x + es->width, es->y, 1.0, 0.0, &v[8]);
|
|
||||||
transform_vertex(es, es->x + es->width, es->y + es->height,
|
|
||||||
1.0, 1.0, &v[12]);
|
|
||||||
|
|
||||||
p[0] = 0;
|
|
||||||
p[1] = 1;
|
|
||||||
p[2] = 2;
|
|
||||||
p[3] = 2;
|
|
||||||
p[4] = 1;
|
|
||||||
p[5] = 3;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
WL_EXPORT void
|
WL_EXPORT void
|
||||||
weston_surface_draw(struct weston_surface *es, struct weston_output *output)
|
weston_surface_draw(struct weston_surface *es, struct weston_output *output)
|
||||||
{
|
{
|
||||||
@@ -547,13 +677,15 @@ weston_surface_draw(struct weston_surface *es, struct weston_output *output)
|
|||||||
GLint filter;
|
GLint filter;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
pixman_region32_init_rect(&repaint,
|
weston_surface_update_transform(es);
|
||||||
es->x, es->y, es->width, es->height);
|
|
||||||
pixman_region32_intersect(&repaint, &repaint, &output->region);
|
pixman_region32_init(&repaint);
|
||||||
|
pixman_region32_intersect(&repaint, &es->transform.boundingbox,
|
||||||
|
&output->region);
|
||||||
pixman_region32_intersect(&repaint, &repaint, &es->damage);
|
pixman_region32_intersect(&repaint, &repaint, &es->damage);
|
||||||
|
|
||||||
if (!pixman_region32_not_empty(&repaint))
|
if (!pixman_region32_not_empty(&repaint))
|
||||||
return;
|
goto out;
|
||||||
|
|
||||||
switch (es->visual) {
|
switch (es->visual) {
|
||||||
case WESTON_ARGB_VISUAL:
|
case WESTON_ARGB_VISUAL:
|
||||||
@@ -584,13 +716,16 @@ weston_surface_draw(struct weston_surface *es, struct weston_output *output)
|
|||||||
ec->current_alpha = es->alpha;
|
ec->current_alpha = es->alpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (es->transform == NULL) {
|
if (es->shader->texwidth_uniform != GL_NONE)
|
||||||
filter = GL_NEAREST;
|
glUniform1f(es->shader->texwidth_uniform,
|
||||||
n = texture_region(es, &repaint);
|
(GLfloat)es->geometry.width / es->pitch);
|
||||||
} else {
|
|
||||||
|
if (es->transform.enabled)
|
||||||
filter = GL_LINEAR;
|
filter = GL_LINEAR;
|
||||||
n = texture_transformed_surface(es);
|
else
|
||||||
}
|
filter = GL_NEAREST;
|
||||||
|
|
||||||
|
n = texture_region(es, &repaint);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, es->texture);
|
glBindTexture(GL_TEXTURE_2D, es->texture);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
|
||||||
@@ -601,10 +736,16 @@ weston_surface_draw(struct weston_surface *es, struct weston_output *output)
|
|||||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[2]);
|
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[2]);
|
||||||
glEnableVertexAttribArray(0);
|
glEnableVertexAttribArray(0);
|
||||||
glEnableVertexAttribArray(1);
|
glEnableVertexAttribArray(1);
|
||||||
|
|
||||||
glDrawElements(GL_TRIANGLES, n * 6, GL_UNSIGNED_INT, ec->indices.data);
|
glDrawElements(GL_TRIANGLES, n * 6, GL_UNSIGNED_INT, ec->indices.data);
|
||||||
|
|
||||||
|
glDisableVertexAttribArray(1);
|
||||||
|
glDisableVertexAttribArray(0);
|
||||||
|
|
||||||
ec->vertices.size = 0;
|
ec->vertices.size = 0;
|
||||||
ec->indices.size = 0;
|
ec->indices.size = 0;
|
||||||
|
|
||||||
|
out:
|
||||||
pixman_region32_fini(&repaint);
|
pixman_region32_fini(&repaint);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -716,12 +857,12 @@ weston_output_set_cursor(struct weston_output *output,
|
|||||||
if (device->sprite == NULL)
|
if (device->sprite == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pixman_region32_init_rect(&cursor_region,
|
weston_surface_update_transform(device->sprite);
|
||||||
device->sprite->x, device->sprite->y,
|
|
||||||
device->sprite->width,
|
|
||||||
device->sprite->height);
|
|
||||||
|
|
||||||
pixman_region32_intersect(&cursor_region, &cursor_region, &output->region);
|
pixman_region32_init(&cursor_region);
|
||||||
|
pixman_region32_intersect(&cursor_region,
|
||||||
|
&device->sprite->transform.boundingbox,
|
||||||
|
&output->region);
|
||||||
|
|
||||||
if (!pixman_region32_not_empty(&cursor_region)) {
|
if (!pixman_region32_not_empty(&cursor_region)) {
|
||||||
output->set_hardware_cursor(output, NULL);
|
output->set_hardware_cursor(output, NULL);
|
||||||
@@ -770,14 +911,15 @@ weston_output_repaint(struct weston_output *output, int msecs)
|
|||||||
pixman_region32_init(&overlap);
|
pixman_region32_init(&overlap);
|
||||||
|
|
||||||
wl_list_for_each(es, &ec->surface_list, link) {
|
wl_list_for_each(es, &ec->surface_list, link) {
|
||||||
|
weston_surface_update_transform(es);
|
||||||
|
|
||||||
pixman_region32_init(&surface_overlap);
|
pixman_region32_init(&surface_overlap);
|
||||||
pixman_region32_intersect_rect(&surface_overlap,
|
pixman_region32_intersect(&surface_overlap, &overlap,
|
||||||
&overlap, es->x, es->y,
|
&es->transform.boundingbox);
|
||||||
es->width, es->height);
|
|
||||||
es->overlapped = pixman_region32_not_empty(&surface_overlap);
|
es->overlapped = pixman_region32_not_empty(&surface_overlap);
|
||||||
pixman_region32_fini(&surface_overlap);
|
pixman_region32_fini(&surface_overlap);
|
||||||
pixman_region32_union_rect(&overlap, &overlap, es->x, es->y,
|
pixman_region32_union(&overlap, &overlap,
|
||||||
es->width, es->height);
|
&es->transform.boundingbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
weston_output_set_cursor(output, ec->input_device);
|
weston_output_set_cursor(output, ec->input_device);
|
||||||
@@ -903,12 +1045,14 @@ weston_surface_assign_output(struct weston_surface *es)
|
|||||||
uint32_t max, area;
|
uint32_t max, area;
|
||||||
pixman_box32_t *e;
|
pixman_box32_t *e;
|
||||||
|
|
||||||
|
weston_surface_update_transform(es);
|
||||||
|
|
||||||
new_output = NULL;
|
new_output = NULL;
|
||||||
max = 0;
|
max = 0;
|
||||||
|
pixman_region32_init(®ion);
|
||||||
wl_list_for_each(output, &ec->output_list, link) {
|
wl_list_for_each(output, &ec->output_list, link) {
|
||||||
pixman_region32_init_rect(®ion,
|
pixman_region32_intersect(®ion, &es->transform.boundingbox,
|
||||||
es->x, es->y, es->width, es->height);
|
&output->region);
|
||||||
pixman_region32_intersect(®ion, ®ion, &output->region);
|
|
||||||
|
|
||||||
e = pixman_region32_extents(®ion);
|
e = pixman_region32_extents(®ion);
|
||||||
area = (e->x2 - e->x1) * (e->y2 - e->y1);
|
area = (e->x2 - e->x1) * (e->y2 - e->y1);
|
||||||
@@ -918,6 +1062,7 @@ weston_surface_assign_output(struct weston_surface *es)
|
|||||||
max = area;
|
max = area;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pixman_region32_fini(®ion);
|
||||||
|
|
||||||
es->output = new_output;
|
es->output = new_output;
|
||||||
if (!wl_list_empty(&es->frame_callback_list)) {
|
if (!wl_list_empty(&es->frame_callback_list)) {
|
||||||
@@ -951,9 +1096,11 @@ surface_attach(struct wl_client *client,
|
|||||||
if (es->visual == WESTON_NONE_VISUAL) {
|
if (es->visual == WESTON_NONE_VISUAL) {
|
||||||
shell->map(shell, es, buffer->width, buffer->height);
|
shell->map(shell, es, buffer->width, buffer->height);
|
||||||
} else if (x != 0 || y != 0 ||
|
} else if (x != 0 || y != 0 ||
|
||||||
es->width != buffer->width ||
|
es->geometry.width != buffer->width ||
|
||||||
es->height != buffer->height) {
|
es->geometry.height != buffer->height) {
|
||||||
shell->configure(shell, es, es->x + x, es->y + y,
|
/* FIXME: the x,y delta should be in surface-local coords */
|
||||||
|
shell->configure(shell, es, es->geometry.x + x,
|
||||||
|
es->geometry.y + y,
|
||||||
buffer->width, buffer->height);
|
buffer->width, buffer->height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1052,9 +1199,9 @@ weston_compositor_pick_surface(struct weston_compositor *compositor,
|
|||||||
wl_list_for_each(surface, &compositor->surface_list, link) {
|
wl_list_for_each(surface, &compositor->surface_list, link) {
|
||||||
if (surface->surface.resource.client == NULL)
|
if (surface->surface.resource.client == NULL)
|
||||||
continue;
|
continue;
|
||||||
weston_surface_transform(surface, x, y, sx, sy);
|
weston_surface_from_global(surface, x, y, sx, sy);
|
||||||
if (0 <= *sx && *sx < surface->width &&
|
if (0 <= *sx && *sx < surface->geometry.width &&
|
||||||
0 <= *sy && *sy < surface->height)
|
0 <= *sy && *sy < surface->geometry.height)
|
||||||
return surface;
|
return surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1163,8 +1310,9 @@ notify_motion(struct wl_input_device *device, uint32_t time, int x, int y)
|
|||||||
if (wd->sprite) {
|
if (wd->sprite) {
|
||||||
weston_surface_damage_below(wd->sprite);
|
weston_surface_damage_below(wd->sprite);
|
||||||
|
|
||||||
wd->sprite->x = device->x - wd->hotspot_x;
|
wd->sprite->geometry.x = device->x - wd->hotspot_x;
|
||||||
wd->sprite->y = device->y - wd->hotspot_y;
|
wd->sprite->geometry.y = device->y - wd->hotspot_y;
|
||||||
|
wd->sprite->geometry.dirty = 1;
|
||||||
|
|
||||||
weston_surface_damage(wd->sprite);
|
weston_surface_damage(wd->sprite);
|
||||||
}
|
}
|
||||||
@@ -1440,7 +1588,7 @@ notify_touch(struct wl_input_device *device, uint32_t time, int touch_id,
|
|||||||
touch_set_focus(wd, &es->surface, time);
|
touch_set_focus(wd, &es->surface, time);
|
||||||
} else if (wd->touch_focus) {
|
} else if (wd->touch_focus) {
|
||||||
es = (struct weston_surface *) wd->touch_focus;
|
es = (struct weston_surface *) wd->touch_focus;
|
||||||
weston_surface_transform(es, x, y, &sx, &sy);
|
weston_surface_from_global(es, x, y, &sx, &sy);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wd->touch_focus_resource && wd->touch_focus)
|
if (wd->touch_focus_resource && wd->touch_focus)
|
||||||
@@ -1454,7 +1602,7 @@ notify_touch(struct wl_input_device *device, uint32_t time, int touch_id,
|
|||||||
if (!es)
|
if (!es)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
weston_surface_transform(es, x, y, &sx, &sy);
|
weston_surface_from_global(es, x, y, &sx, &sy);
|
||||||
if (wd->touch_focus_resource)
|
if (wd->touch_focus_resource)
|
||||||
wl_resource_post_event(wd->touch_focus_resource,
|
wl_resource_post_event(wd->touch_focus_resource,
|
||||||
touch_type, time,
|
touch_type, time,
|
||||||
@@ -1515,10 +1663,11 @@ input_device_attach(struct wl_client *client,
|
|||||||
|
|
||||||
device->hotspot_x = x;
|
device->hotspot_x = x;
|
||||||
device->hotspot_y = y;
|
device->hotspot_y = y;
|
||||||
device->sprite->width = buffer->width;
|
device->sprite->geometry.width = buffer->width;
|
||||||
device->sprite->height = buffer->height;
|
device->sprite->geometry.height = buffer->height;
|
||||||
device->sprite->x = device->input_device.x - device->hotspot_x;
|
device->sprite->geometry.x = device->input_device.x - device->hotspot_x;
|
||||||
device->sprite->y = device->input_device.y - device->hotspot_y;
|
device->sprite->geometry.y = device->input_device.y - device->hotspot_y;
|
||||||
|
device->sprite->geometry.dirty = 1;
|
||||||
|
|
||||||
weston_surface_damage(device->sprite);
|
weston_surface_damage(device->sprite);
|
||||||
}
|
}
|
||||||
@@ -1624,8 +1773,12 @@ static const char texture_fragment_shader[] =
|
|||||||
"varying vec2 v_texcoord;\n"
|
"varying vec2 v_texcoord;\n"
|
||||||
"uniform sampler2D tex;\n"
|
"uniform sampler2D tex;\n"
|
||||||
"uniform float alpha;\n"
|
"uniform float alpha;\n"
|
||||||
|
"uniform float texwidth;\n"
|
||||||
"void main()\n"
|
"void main()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
|
" if (v_texcoord.x < 0.0 || v_texcoord.x > texwidth ||\n"
|
||||||
|
" v_texcoord.y < 0.0 || v_texcoord.y > 1.0)\n"
|
||||||
|
" discard;\n"
|
||||||
" gl_FragColor = texture2D(tex, v_texcoord)\n;"
|
" gl_FragColor = texture2D(tex, v_texcoord)\n;"
|
||||||
" gl_FragColor = alpha * gl_FragColor;\n"
|
" gl_FragColor = alpha * gl_FragColor;\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
@@ -1687,6 +1840,8 @@ weston_shader_init(struct weston_shader *shader,
|
|||||||
shader->proj_uniform = glGetUniformLocation(shader->program, "proj");
|
shader->proj_uniform = glGetUniformLocation(shader->program, "proj");
|
||||||
shader->tex_uniform = glGetUniformLocation(shader->program, "tex");
|
shader->tex_uniform = glGetUniformLocation(shader->program, "tex");
|
||||||
shader->alpha_uniform = glGetUniformLocation(shader->program, "alpha");
|
shader->alpha_uniform = glGetUniformLocation(shader->program, "alpha");
|
||||||
|
shader->texwidth_uniform = glGetUniformLocation(shader->program,
|
||||||
|
"texwidth");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+45
-21
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2008-2011 Kristian Høgsberg
|
* Copyright © 2008-2011 Kristian Høgsberg
|
||||||
|
* Copyright © 2012 Collabora, Ltd.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, distribute, and sell this software and
|
* Permission to use, copy, modify, distribute, and sell this software and
|
||||||
* its documentation for any purpose is hereby granted without fee, provided
|
* its documentation for any purpose is hereby granted without fee, provided
|
||||||
@@ -32,27 +33,11 @@
|
|||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
#include <EGL/eglext.h>
|
#include <EGL/eglext.h>
|
||||||
|
|
||||||
struct weston_matrix {
|
#include "matrix.h"
|
||||||
GLfloat d[16];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct weston_vector {
|
|
||||||
GLfloat f[4];
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
weston_matrix_init(struct weston_matrix *matrix);
|
|
||||||
void
|
|
||||||
weston_matrix_scale(struct weston_matrix *matrix, GLfloat x, GLfloat y, GLfloat z);
|
|
||||||
void
|
|
||||||
weston_matrix_translate(struct weston_matrix *matrix,
|
|
||||||
GLfloat x, GLfloat y, GLfloat z);
|
|
||||||
void
|
|
||||||
weston_matrix_transform(struct weston_matrix *matrix, struct weston_vector *v);
|
|
||||||
|
|
||||||
struct weston_transform {
|
struct weston_transform {
|
||||||
struct weston_matrix matrix;
|
struct weston_matrix matrix;
|
||||||
struct weston_matrix inverse;
|
struct wl_list link;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct weston_surface;
|
struct weston_surface;
|
||||||
@@ -118,6 +103,7 @@ struct weston_shader {
|
|||||||
GLuint tex_uniform;
|
GLuint tex_uniform;
|
||||||
GLuint alpha_uniform;
|
GLuint alpha_uniform;
|
||||||
GLuint color_uniform;
|
GLuint color_uniform;
|
||||||
|
GLuint texwidth_uniform;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct weston_animation {
|
struct weston_animation {
|
||||||
@@ -162,7 +148,6 @@ struct weston_compositor {
|
|||||||
EGLContext context;
|
EGLContext context;
|
||||||
EGLConfig config;
|
EGLConfig config;
|
||||||
GLuint fbo;
|
GLuint fbo;
|
||||||
GLuint proj_uniform, tex_uniform, alpha_uniform;
|
|
||||||
uint32_t current_alpha;
|
uint32_t current_alpha;
|
||||||
struct weston_shader texture_shader;
|
struct weston_shader texture_shader;
|
||||||
struct weston_shader solid_shader;
|
struct weston_shader solid_shader;
|
||||||
@@ -230,17 +215,45 @@ struct weston_surface {
|
|||||||
GLuint texture;
|
GLuint texture;
|
||||||
pixman_region32_t damage;
|
pixman_region32_t damage;
|
||||||
pixman_region32_t opaque;
|
pixman_region32_t opaque;
|
||||||
int32_t x, y, width, height;
|
|
||||||
int32_t pitch;
|
int32_t pitch;
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
struct wl_list buffer_link;
|
struct wl_list buffer_link;
|
||||||
struct weston_transform *transform;
|
|
||||||
struct weston_shader *shader;
|
struct weston_shader *shader;
|
||||||
GLfloat color[4];
|
GLfloat color[4];
|
||||||
uint32_t alpha;
|
uint32_t alpha;
|
||||||
uint32_t visual;
|
uint32_t visual;
|
||||||
int overlapped;
|
int overlapped;
|
||||||
|
|
||||||
|
/* Surface geometry state, mutable.
|
||||||
|
* If you change anything, set dirty = 1.
|
||||||
|
* That includes the transformations referenced from the list.
|
||||||
|
*/
|
||||||
|
struct {
|
||||||
|
int32_t x, y; /* surface translation on display */
|
||||||
|
int32_t width, height;
|
||||||
|
|
||||||
|
/* struct weston_transform */
|
||||||
|
struct wl_list transformation_list;
|
||||||
|
|
||||||
|
int dirty;
|
||||||
|
} geometry;
|
||||||
|
|
||||||
|
/* State derived from geometry state, read-only.
|
||||||
|
* This is updated by weston_surface_update_transform().
|
||||||
|
*/
|
||||||
|
struct {
|
||||||
|
pixman_region32_t boundingbox;
|
||||||
|
|
||||||
|
/* matrix and inverse are used only if enabled = 1.
|
||||||
|
* If enabled = 0, use x, y, width, height directly.
|
||||||
|
*/
|
||||||
|
int enabled;
|
||||||
|
struct weston_matrix matrix;
|
||||||
|
struct weston_matrix inverse;
|
||||||
|
|
||||||
|
struct weston_transform position; /* matrix from x, y */
|
||||||
|
} transform;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Which output to vsync this surface to.
|
* Which output to vsync this surface to.
|
||||||
* Used to determine, whether to send or queue frame events.
|
* Used to determine, whether to send or queue frame events.
|
||||||
@@ -257,6 +270,17 @@ struct weston_surface {
|
|||||||
struct wl_listener buffer_destroy_listener;
|
struct wl_listener buffer_destroy_listener;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
weston_surface_update_transform(struct weston_surface *surface);
|
||||||
|
|
||||||
|
void
|
||||||
|
weston_surface_to_global(struct weston_surface *surface,
|
||||||
|
int32_t sx, int32_t sy, int32_t *x, int32_t *y);
|
||||||
|
|
||||||
|
void
|
||||||
|
weston_surface_from_global(struct weston_surface *surface,
|
||||||
|
int32_t x, int32_t y, int32_t *sx, int32_t *sy);
|
||||||
|
|
||||||
void
|
void
|
||||||
weston_device_repick(struct wl_input_device *device, uint32_t time);
|
weston_device_repick(struct wl_input_device *device, uint32_t time);
|
||||||
|
|
||||||
|
|||||||
+250
@@ -0,0 +1,250 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2011 Intel Corporation
|
||||||
|
* Copyright © 2012 Collabora, Ltd.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, distribute, and sell this software and
|
||||||
|
* its documentation for any purpose is hereby granted without fee, provided
|
||||||
|
* that the above copyright notice appear in all copies and that both that
|
||||||
|
* copyright notice and this permission notice appear in supporting
|
||||||
|
* documentation, and that the name of the copyright holders not be used in
|
||||||
|
* advertising or publicity pertaining to distribution of the software
|
||||||
|
* without specific, written prior permission. The copyright holders make
|
||||||
|
* no representations about the suitability of this software for any
|
||||||
|
* purpose. It is provided "as is" without express or implied warranty.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||||
|
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||||
|
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||||
|
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <GLES2/gl2.h>
|
||||||
|
#include <wayland-server.h>
|
||||||
|
|
||||||
|
#include "matrix.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Matrices are stored in column-major order, that is the array indices are:
|
||||||
|
* 0 4 8 12
|
||||||
|
* 1 5 9 13
|
||||||
|
* 2 6 10 14
|
||||||
|
* 3 7 11 15
|
||||||
|
*/
|
||||||
|
|
||||||
|
WL_EXPORT void
|
||||||
|
weston_matrix_init(struct weston_matrix *matrix)
|
||||||
|
{
|
||||||
|
static const struct weston_matrix identity = {
|
||||||
|
{ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 }
|
||||||
|
};
|
||||||
|
|
||||||
|
memcpy(matrix, &identity, sizeof identity);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* m <- n * m, that is, m is multiplied on the LEFT. */
|
||||||
|
WL_EXPORT void
|
||||||
|
weston_matrix_multiply(struct weston_matrix *m, const struct weston_matrix *n)
|
||||||
|
{
|
||||||
|
struct weston_matrix tmp;
|
||||||
|
const GLfloat *row, *column;
|
||||||
|
div_t d;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
for (i = 0; i < 16; i++) {
|
||||||
|
tmp.d[i] = 0;
|
||||||
|
d = div(i, 4);
|
||||||
|
row = m->d + d.quot * 4;
|
||||||
|
column = n->d + d.rem;
|
||||||
|
for (j = 0; j < 4; j++)
|
||||||
|
tmp.d[i] += row[j] * column[j * 4];
|
||||||
|
}
|
||||||
|
memcpy(m, &tmp, sizeof tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
WL_EXPORT void
|
||||||
|
weston_matrix_translate(struct weston_matrix *matrix, GLfloat x, GLfloat y, GLfloat z)
|
||||||
|
{
|
||||||
|
struct weston_matrix translate = {
|
||||||
|
{ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1 }
|
||||||
|
};
|
||||||
|
|
||||||
|
weston_matrix_multiply(matrix, &translate);
|
||||||
|
}
|
||||||
|
|
||||||
|
WL_EXPORT void
|
||||||
|
weston_matrix_scale(struct weston_matrix *matrix, GLfloat x, GLfloat y, GLfloat z)
|
||||||
|
{
|
||||||
|
struct weston_matrix scale = {
|
||||||
|
{ x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, 0, 0, 0, 1 }
|
||||||
|
};
|
||||||
|
|
||||||
|
weston_matrix_multiply(matrix, &scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* v <- m * v */
|
||||||
|
WL_EXPORT void
|
||||||
|
weston_matrix_transform(struct weston_matrix *matrix, struct weston_vector *v)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
struct weston_vector t;
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
t.f[i] = 0;
|
||||||
|
for (j = 0; j < 4; j++)
|
||||||
|
t.f[i] += v->f[j] * matrix->d[i + j * 4];
|
||||||
|
}
|
||||||
|
|
||||||
|
*v = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
swap_rows(double *a, double *b)
|
||||||
|
{
|
||||||
|
unsigned k;
|
||||||
|
double tmp;
|
||||||
|
|
||||||
|
for (k = 0; k < 13; k += 4) {
|
||||||
|
tmp = a[k];
|
||||||
|
a[k] = b[k];
|
||||||
|
b[k] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
swap_unsigned(unsigned *a, unsigned *b)
|
||||||
|
{
|
||||||
|
unsigned tmp;
|
||||||
|
|
||||||
|
tmp = *a;
|
||||||
|
*a = *b;
|
||||||
|
*b = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned
|
||||||
|
find_pivot(double *column, unsigned k)
|
||||||
|
{
|
||||||
|
unsigned p = k;
|
||||||
|
for (++k; k < 4; ++k)
|
||||||
|
if (fabs(column[p]) < fabs(column[k]))
|
||||||
|
p = k;
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* reference: Gene H. Golub and Charles F. van Loan. Matrix computations.
|
||||||
|
* 3rd ed. The Johns Hopkins University Press. 1996.
|
||||||
|
* LU decomposition, forward and back substitution: Chapter 3.
|
||||||
|
*/
|
||||||
|
|
||||||
|
MATRIX_TEST_EXPORT inline int
|
||||||
|
matrix_invert(double *A, unsigned *p, const struct weston_matrix *matrix)
|
||||||
|
{
|
||||||
|
unsigned i, j, k;
|
||||||
|
unsigned pivot;
|
||||||
|
double pv;
|
||||||
|
|
||||||
|
for (i = 0; i < 4; ++i)
|
||||||
|
p[i] = i;
|
||||||
|
for (i = 16; i--; )
|
||||||
|
A[i] = matrix->d[i];
|
||||||
|
|
||||||
|
/* LU decomposition with partial pivoting */
|
||||||
|
for (k = 0; k < 4; ++k) {
|
||||||
|
pivot = find_pivot(&A[k * 4], k);
|
||||||
|
if (pivot != k) {
|
||||||
|
swap_unsigned(&p[k], &p[pivot]);
|
||||||
|
swap_rows(&A[k], &A[pivot]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pv = A[k * 4 + k];
|
||||||
|
if (fabs(pv) < 1e-9)
|
||||||
|
return -1; /* zero pivot, not invertible */
|
||||||
|
|
||||||
|
for (i = k + 1; i < 4; ++i) {
|
||||||
|
A[i + k * 4] /= pv;
|
||||||
|
|
||||||
|
for (j = k + 1; j < 4; ++j)
|
||||||
|
A[i + j * 4] -= A[i + k * 4] * A[k + j * 4];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MATRIX_TEST_EXPORT inline void
|
||||||
|
inverse_transform(const double *LU, const unsigned *p, GLfloat *v)
|
||||||
|
{
|
||||||
|
/* Solve A * x = v, when we have P * A = L * U.
|
||||||
|
* P * A * x = P * v => L * U * x = P * v
|
||||||
|
* Let U * x = b, then L * b = P * v.
|
||||||
|
*/
|
||||||
|
double b[4];
|
||||||
|
unsigned j;
|
||||||
|
|
||||||
|
/* Forward substitution, column version, solves L * b = P * v */
|
||||||
|
/* The diagonal of L is all ones, and not explicitly stored. */
|
||||||
|
b[0] = v[p[0]];
|
||||||
|
b[1] = (double)v[p[1]] - b[0] * LU[1 + 0 * 4];
|
||||||
|
b[2] = (double)v[p[2]] - b[0] * LU[2 + 0 * 4];
|
||||||
|
b[3] = (double)v[p[3]] - b[0] * LU[3 + 0 * 4];
|
||||||
|
b[2] -= b[1] * LU[2 + 1 * 4];
|
||||||
|
b[3] -= b[1] * LU[3 + 1 * 4];
|
||||||
|
b[3] -= b[2] * LU[3 + 2 * 4];
|
||||||
|
|
||||||
|
/* backward substitution, column version, solves U * y = b */
|
||||||
|
#if 1
|
||||||
|
/* hand-unrolled, 25% faster for whole function */
|
||||||
|
b[3] /= LU[3 + 3 * 4];
|
||||||
|
b[0] -= b[3] * LU[0 + 3 * 4];
|
||||||
|
b[1] -= b[3] * LU[1 + 3 * 4];
|
||||||
|
b[2] -= b[3] * LU[2 + 3 * 4];
|
||||||
|
|
||||||
|
b[2] /= LU[2 + 2 * 4];
|
||||||
|
b[0] -= b[2] * LU[0 + 2 * 4];
|
||||||
|
b[1] -= b[2] * LU[1 + 2 * 4];
|
||||||
|
|
||||||
|
b[1] /= LU[1 + 1 * 4];
|
||||||
|
b[0] -= b[1] * LU[0 + 1 * 4];
|
||||||
|
|
||||||
|
b[0] /= LU[0 + 0 * 4];
|
||||||
|
#else
|
||||||
|
for (j = 3; j > 0; --j) {
|
||||||
|
unsigned k;
|
||||||
|
b[j] /= LU[j + j * 4];
|
||||||
|
for (k = 0; k < j; ++k)
|
||||||
|
b[k] -= b[j] * LU[k + j * 4];
|
||||||
|
}
|
||||||
|
|
||||||
|
b[0] /= LU[0 + 0 * 4];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* the result */
|
||||||
|
for (j = 0; j < 4; ++j)
|
||||||
|
v[j] = b[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
WL_EXPORT int
|
||||||
|
weston_matrix_invert(struct weston_matrix *inverse,
|
||||||
|
const struct weston_matrix *matrix)
|
||||||
|
{
|
||||||
|
double LU[16]; /* column-major */
|
||||||
|
unsigned perm[4]; /* permutation */
|
||||||
|
unsigned c;
|
||||||
|
|
||||||
|
if (matrix_invert(LU, perm, matrix) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
weston_matrix_init(inverse);
|
||||||
|
for (c = 0; c < 4; ++c)
|
||||||
|
inverse_transform(LU, perm, &inverse->d[c * 4]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2008-2011 Kristian Høgsberg
|
||||||
|
* Copyright © 2012 Collabora, Ltd.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, distribute, and sell this software and
|
||||||
|
* its documentation for any purpose is hereby granted without fee, provided
|
||||||
|
* that the above copyright notice appear in all copies and that both that
|
||||||
|
* copyright notice and this permission notice appear in supporting
|
||||||
|
* documentation, and that the name of the copyright holders not be used in
|
||||||
|
* advertising or publicity pertaining to distribution of the software
|
||||||
|
* without specific, written prior permission. The copyright holders make
|
||||||
|
* no representations about the suitability of this software for any
|
||||||
|
* purpose. It is provided "as is" without express or implied warranty.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||||
|
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||||
|
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||||
|
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WESTON_MATRIX_H
|
||||||
|
#define WESTON_MATRIX_H
|
||||||
|
|
||||||
|
struct weston_matrix {
|
||||||
|
GLfloat d[16];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct weston_vector {
|
||||||
|
GLfloat f[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
weston_matrix_init(struct weston_matrix *matrix);
|
||||||
|
void
|
||||||
|
weston_matrix_multiply(struct weston_matrix *m, const struct weston_matrix *n);
|
||||||
|
void
|
||||||
|
weston_matrix_scale(struct weston_matrix *matrix, GLfloat x, GLfloat y, GLfloat z);
|
||||||
|
void
|
||||||
|
weston_matrix_translate(struct weston_matrix *matrix,
|
||||||
|
GLfloat x, GLfloat y, GLfloat z);
|
||||||
|
void
|
||||||
|
weston_matrix_transform(struct weston_matrix *matrix, struct weston_vector *v);
|
||||||
|
|
||||||
|
int
|
||||||
|
weston_matrix_invert(struct weston_matrix *inverse,
|
||||||
|
const struct weston_matrix *matrix);
|
||||||
|
|
||||||
|
#ifdef UNIT_TEST
|
||||||
|
# define MATRIX_TEST_EXPORT WL_EXPORT
|
||||||
|
|
||||||
|
int
|
||||||
|
matrix_invert(double *A, unsigned *p, const struct weston_matrix *matrix);
|
||||||
|
|
||||||
|
void
|
||||||
|
inverse_transform(const double *LU, const unsigned *p, GLfloat *v);
|
||||||
|
|
||||||
|
#else
|
||||||
|
# define MATRIX_TEST_EXPORT static
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* WESTON_MATRIX_H */
|
||||||
+193
-47
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2010 Intel Corporation
|
* Copyright © 2010 Intel Corporation
|
||||||
* Copyright © 2011 Collabora, Ltd.
|
* Copyright © 2011-2012 Collabora, Ltd.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, distribute, and sell this software and
|
* Permission to use, copy, modify, distribute, and sell this software and
|
||||||
* its documentation for any purpose is hereby granted without fee, provided
|
* its documentation for any purpose is hereby granted without fee, provided
|
||||||
@@ -29,6 +29,7 @@
|
|||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#include <wayland-server.h>
|
#include <wayland-server.h>
|
||||||
#include "compositor.h"
|
#include "compositor.h"
|
||||||
@@ -93,6 +94,10 @@ struct shell_surface {
|
|||||||
enum shell_surface_type type;
|
enum shell_surface_type type;
|
||||||
int32_t saved_x, saved_y;
|
int32_t saved_x, saved_y;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct weston_transform transform;
|
||||||
|
} rotation;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct wl_grab grab;
|
struct wl_grab grab;
|
||||||
uint32_t time;
|
uint32_t time;
|
||||||
@@ -110,6 +115,15 @@ struct weston_move_grab {
|
|||||||
int32_t dx, dy;
|
int32_t dx, dy;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct rotate_grab {
|
||||||
|
struct wl_grab grab;
|
||||||
|
struct shell_surface *surface;
|
||||||
|
struct {
|
||||||
|
int32_t x;
|
||||||
|
int32_t y;
|
||||||
|
} center;
|
||||||
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
shell_configuration(struct wl_shell *shell)
|
shell_configuration(struct wl_shell *shell)
|
||||||
{
|
{
|
||||||
@@ -152,7 +166,7 @@ move_grab_motion(struct wl_grab *grab,
|
|||||||
weston_surface_configure(es,
|
weston_surface_configure(es,
|
||||||
device->x + move->dx,
|
device->x + move->dx,
|
||||||
device->y + move->dy,
|
device->y + move->dy,
|
||||||
es->width, es->height);
|
es->geometry.width, es->geometry.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -184,8 +198,8 @@ weston_surface_move(struct weston_surface *es,
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
move->grab.interface = &move_grab_interface;
|
move->grab.interface = &move_grab_interface;
|
||||||
move->dx = es->x - wd->input_device.grab_x;
|
move->dx = es->geometry.x - wd->input_device.grab_x;
|
||||||
move->dy = es->y - wd->input_device.grab_y;
|
move->dy = es->geometry.y - wd->input_device.grab_y;
|
||||||
move->surface = es;
|
move->surface = es;
|
||||||
|
|
||||||
wl_input_device_start_grab(&wd->input_device, &move->grab, time);
|
wl_input_device_start_grab(&wd->input_device, &move->grab, time);
|
||||||
@@ -282,10 +296,10 @@ weston_surface_resize(struct shell_surface *shsurf,
|
|||||||
|
|
||||||
resize->grab.interface = &resize_grab_interface;
|
resize->grab.interface = &resize_grab_interface;
|
||||||
resize->edges = edges;
|
resize->edges = edges;
|
||||||
resize->dx = es->x - wd->input_device.grab_x;
|
resize->dx = es->geometry.x - wd->input_device.grab_x;
|
||||||
resize->dy = es->y - wd->input_device.grab_y;
|
resize->dy = es->geometry.y - wd->input_device.grab_y;
|
||||||
resize->width = es->width;
|
resize->width = es->geometry.width;
|
||||||
resize->height = es->height;
|
resize->height = es->geometry.height;
|
||||||
resize->shsurf = shsurf;
|
resize->shsurf = shsurf;
|
||||||
|
|
||||||
if (edges == 0 || edges > 15 ||
|
if (edges == 0 || edges > 15 ||
|
||||||
@@ -328,8 +342,9 @@ reset_shell_surface_type(struct shell_surface *surface)
|
|||||||
{
|
{
|
||||||
switch (surface->type) {
|
switch (surface->type) {
|
||||||
case SHELL_SURFACE_FULLSCREEN:
|
case SHELL_SURFACE_FULLSCREEN:
|
||||||
surface->surface->x = surface->saved_x;
|
surface->surface->geometry.x = surface->saved_x;
|
||||||
surface->surface->y = surface->saved_y;
|
surface->surface->geometry.y = surface->saved_y;
|
||||||
|
surface->surface->geometry.dirty = 1;
|
||||||
surface->surface->fullscreen_output = NULL;
|
surface->surface->fullscreen_output = NULL;
|
||||||
break;
|
break;
|
||||||
case SHELL_SURFACE_PANEL:
|
case SHELL_SURFACE_PANEL:
|
||||||
@@ -385,8 +400,9 @@ shell_surface_set_transient(struct wl_client *client,
|
|||||||
/* assign to parents output */
|
/* assign to parents output */
|
||||||
es->output = pes->output;
|
es->output = pes->output;
|
||||||
|
|
||||||
es->x = pes->x + x;
|
es->geometry.x = pes->geometry.x + x;
|
||||||
es->y = pes->y + y;
|
es->geometry.y = pes->geometry.y + y;
|
||||||
|
es->geometry.dirty = 1;
|
||||||
|
|
||||||
weston_surface_damage(es);
|
weston_surface_damage(es);
|
||||||
shsurf->type = SHELL_SURFACE_TRANSIENT;
|
shsurf->type = SHELL_SURFACE_TRANSIENT;
|
||||||
@@ -416,10 +432,11 @@ shell_surface_set_fullscreen(struct wl_client *client,
|
|||||||
output = get_default_output(es->compositor);
|
output = get_default_output(es->compositor);
|
||||||
es->output = output;
|
es->output = output;
|
||||||
|
|
||||||
shsurf->saved_x = es->x;
|
shsurf->saved_x = es->geometry.x;
|
||||||
shsurf->saved_y = es->y;
|
shsurf->saved_y = es->geometry.y;
|
||||||
es->x = (output->current->width - es->width) / 2;
|
es->geometry.x = (output->current->width - es->geometry.width) / 2;
|
||||||
es->y = (output->current->height - es->height) / 2;
|
es->geometry.y = (output->current->height - es->geometry.height) / 2;
|
||||||
|
es->geometry.dirty = 1;
|
||||||
es->fullscreen_output = output;
|
es->fullscreen_output = output;
|
||||||
weston_surface_damage(es);
|
weston_surface_damage(es);
|
||||||
shsurf->type = SHELL_SURFACE_FULLSCREEN;
|
shsurf->type = SHELL_SURFACE_FULLSCREEN;
|
||||||
@@ -501,8 +518,9 @@ shell_map_popup(struct shell_surface *shsurf, uint32_t time)
|
|||||||
shsurf->popup.grab.interface = &popup_grab_interface;
|
shsurf->popup.grab.interface = &popup_grab_interface;
|
||||||
device = es->compositor->input_device;
|
device = es->compositor->input_device;
|
||||||
|
|
||||||
es->x = shsurf->parent->surface->x + shsurf->popup.x;
|
es->geometry.x = shsurf->parent->surface->geometry.x + shsurf->popup.x;
|
||||||
es->y = shsurf->parent->surface->y + shsurf->popup.y;
|
es->geometry.y = shsurf->parent->surface->geometry.y + shsurf->popup.y;
|
||||||
|
es->geometry.dirty = 1;
|
||||||
|
|
||||||
shsurf->popup.grab.input_device = device;
|
shsurf->popup.grab.input_device = device;
|
||||||
shsurf->popup.time = device->grab_time;
|
shsurf->popup.time = device->grab_time;
|
||||||
@@ -621,6 +639,9 @@ shell_get_shell_surface(struct wl_client *client,
|
|||||||
/* init link so its safe to always remove it in destroy_shell_surface */
|
/* init link so its safe to always remove it in destroy_shell_surface */
|
||||||
wl_list_init(&shsurf->link);
|
wl_list_init(&shsurf->link);
|
||||||
|
|
||||||
|
/* empty when not in use */
|
||||||
|
wl_list_init(&shsurf->rotation.transform.link);
|
||||||
|
|
||||||
shsurf->type = SHELL_SURFACE_NONE;
|
shsurf->type = SHELL_SURFACE_NONE;
|
||||||
|
|
||||||
wl_client_add_resource(client, &shsurf->resource);
|
wl_client_add_resource(client, &shsurf->resource);
|
||||||
@@ -673,10 +694,10 @@ show_screensaver(struct wl_shell *shell, struct shell_surface *surface)
|
|||||||
wl_list_remove(&surface->surface->link);
|
wl_list_remove(&surface->surface->link);
|
||||||
wl_list_insert(list, &surface->surface->link);
|
wl_list_insert(list, &surface->surface->link);
|
||||||
weston_surface_configure(surface->surface,
|
weston_surface_configure(surface->surface,
|
||||||
surface->surface->x,
|
surface->surface->geometry.x,
|
||||||
surface->surface->y,
|
surface->surface->geometry.y,
|
||||||
surface->surface->width,
|
surface->surface->geometry.width,
|
||||||
surface->surface->height);
|
surface->surface->geometry.height);
|
||||||
surface->surface->output = surface->output;
|
surface->surface->output = surface->output;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -716,8 +737,9 @@ desktop_shell_set_background(struct wl_client *client,
|
|||||||
|
|
||||||
wl_list_insert(&shell->backgrounds, &shsurf->link);
|
wl_list_insert(&shell->backgrounds, &shsurf->link);
|
||||||
|
|
||||||
surface->x = shsurf->output->x;
|
surface->geometry.x = shsurf->output->x;
|
||||||
surface->y = shsurf->output->y;
|
surface->geometry.y = shsurf->output->y;
|
||||||
|
surface->geometry.dirty = 1;
|
||||||
|
|
||||||
wl_resource_post_event(resource,
|
wl_resource_post_event(resource,
|
||||||
DESKTOP_SHELL_CONFIGURE,
|
DESKTOP_SHELL_CONFIGURE,
|
||||||
@@ -754,8 +776,9 @@ desktop_shell_set_panel(struct wl_client *client,
|
|||||||
|
|
||||||
wl_list_insert(&shell->panels, &shsurf->link);
|
wl_list_insert(&shell->panels, &shsurf->link);
|
||||||
|
|
||||||
surface->x = shsurf->output->x;
|
surface->geometry.x = shsurf->output->x;
|
||||||
surface->y = shsurf->output->y;
|
surface->geometry.y = shsurf->output->y;
|
||||||
|
surface->geometry.dirty = 1;
|
||||||
|
|
||||||
wl_resource_post_event(resource,
|
wl_resource_post_event(resource,
|
||||||
DESKTOP_SHELL_CONFIGURE,
|
DESKTOP_SHELL_CONFIGURE,
|
||||||
@@ -813,8 +836,10 @@ resume_desktop(struct wl_shell *shell)
|
|||||||
terminate_screensaver(shell);
|
terminate_screensaver(shell);
|
||||||
|
|
||||||
wl_list_for_each(surface, &shell->hidden_surface_list, link)
|
wl_list_for_each(surface, &shell->hidden_surface_list, link)
|
||||||
weston_surface_configure(surface, surface->x, surface->y,
|
weston_surface_configure(surface, surface->geometry.x,
|
||||||
surface->width, surface->height);
|
surface->geometry.y,
|
||||||
|
surface->geometry.width,
|
||||||
|
surface->geometry.height);
|
||||||
|
|
||||||
if (wl_list_empty(&shell->backgrounds)) {
|
if (wl_list_empty(&shell->backgrounds)) {
|
||||||
list = &shell->compositor->surface_list;
|
list = &shell->compositor->surface_list;
|
||||||
@@ -915,19 +940,20 @@ resize_binding(struct wl_input_device *device, uint32_t time,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
x = device->grab_x - surface->x;
|
/* FIXME: convert properly to surface coordinates */
|
||||||
y = device->grab_y - surface->y;
|
x = device->grab_x - surface->geometry.x;
|
||||||
|
y = device->grab_y - surface->geometry.y;
|
||||||
|
|
||||||
if (x < surface->width / 3)
|
if (x < surface->geometry.width / 3)
|
||||||
edges |= WL_SHELL_SURFACE_RESIZE_LEFT;
|
edges |= WL_SHELL_SURFACE_RESIZE_LEFT;
|
||||||
else if (x < 2 * surface->width / 3)
|
else if (x < 2 * surface->geometry.width / 3)
|
||||||
edges |= 0;
|
edges |= 0;
|
||||||
else
|
else
|
||||||
edges |= WL_SHELL_SURFACE_RESIZE_RIGHT;
|
edges |= WL_SHELL_SURFACE_RESIZE_RIGHT;
|
||||||
|
|
||||||
if (y < surface->height / 3)
|
if (y < surface->geometry.height / 3)
|
||||||
edges |= WL_SHELL_SURFACE_RESIZE_TOP;
|
edges |= WL_SHELL_SURFACE_RESIZE_TOP;
|
||||||
else if (y < 2 * surface->height / 3)
|
else if (y < 2 * surface->geometry.height / 3)
|
||||||
edges |= 0;
|
edges |= 0;
|
||||||
else
|
else
|
||||||
edges |= WL_SHELL_SURFACE_RESIZE_BOTTOM;
|
edges |= WL_SHELL_SURFACE_RESIZE_BOTTOM;
|
||||||
@@ -946,6 +972,114 @@ terminate_binding(struct wl_input_device *device, uint32_t time,
|
|||||||
wl_display_terminate(compositor->wl_display);
|
wl_display_terminate(compositor->wl_display);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rotate_grab_motion(struct wl_grab *grab,
|
||||||
|
uint32_t time, int32_t x, int32_t y)
|
||||||
|
{
|
||||||
|
struct rotate_grab *rotate =
|
||||||
|
container_of(grab, struct rotate_grab, grab);
|
||||||
|
struct wl_input_device *device = grab->input_device;
|
||||||
|
struct shell_surface *surface = rotate->surface;
|
||||||
|
GLfloat dx, dy;
|
||||||
|
GLfloat r;
|
||||||
|
|
||||||
|
dx = device->x - rotate->center.x;
|
||||||
|
dy = device->y - rotate->center.y;
|
||||||
|
r = sqrtf(dx * dx + dy * dy);
|
||||||
|
|
||||||
|
wl_list_remove(&surface->rotation.transform.link);
|
||||||
|
surface->surface->geometry.dirty = 1;
|
||||||
|
|
||||||
|
if (r > 20.0f) {
|
||||||
|
struct weston_matrix roto;
|
||||||
|
struct weston_matrix *matrix =
|
||||||
|
&surface->rotation.transform.matrix;
|
||||||
|
|
||||||
|
weston_matrix_init(&roto);
|
||||||
|
roto.d[0] = dx / r;
|
||||||
|
roto.d[4] = -dy / r;
|
||||||
|
roto.d[1] = -roto.d[4];
|
||||||
|
roto.d[5] = roto.d[0];
|
||||||
|
|
||||||
|
weston_matrix_init(matrix);
|
||||||
|
weston_matrix_translate(matrix, -rotate->center.x,
|
||||||
|
-rotate->center.y, 0.0f);
|
||||||
|
weston_matrix_multiply(matrix, &roto);
|
||||||
|
weston_matrix_translate(matrix, rotate->center.x,
|
||||||
|
rotate->center.y, 0.0f);
|
||||||
|
|
||||||
|
wl_list_insert(
|
||||||
|
surface->surface->geometry.transformation_list.prev,
|
||||||
|
&surface->rotation.transform.link);
|
||||||
|
} else {
|
||||||
|
wl_list_init(&surface->rotation.transform.link);
|
||||||
|
}
|
||||||
|
|
||||||
|
weston_compositor_damage_all(surface->surface->compositor);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rotate_grab_button(struct wl_grab *grab,
|
||||||
|
uint32_t time, int32_t button, int32_t state)
|
||||||
|
{
|
||||||
|
struct rotate_grab *rotate =
|
||||||
|
container_of(grab, struct rotate_grab, grab);
|
||||||
|
struct wl_input_device *device = grab->input_device;
|
||||||
|
|
||||||
|
if (device->button_count == 0 && state == 0) {
|
||||||
|
wl_input_device_end_grab(device, time);
|
||||||
|
free(rotate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_grab_interface rotate_grab_interface = {
|
||||||
|
noop_grab_focus,
|
||||||
|
rotate_grab_motion,
|
||||||
|
rotate_grab_button,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
rotate_binding(struct wl_input_device *device, uint32_t time,
|
||||||
|
uint32_t key, uint32_t button, uint32_t state, void *data)
|
||||||
|
{
|
||||||
|
struct weston_surface *base_surface =
|
||||||
|
(struct weston_surface *) device->pointer_focus;
|
||||||
|
struct shell_surface *surface;
|
||||||
|
struct rotate_grab *rotate;
|
||||||
|
|
||||||
|
if (base_surface == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
surface = get_shell_surface(base_surface);
|
||||||
|
if (!surface)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (surface->type) {
|
||||||
|
case SHELL_SURFACE_PANEL:
|
||||||
|
case SHELL_SURFACE_BACKGROUND:
|
||||||
|
case SHELL_SURFACE_FULLSCREEN:
|
||||||
|
case SHELL_SURFACE_SCREENSAVER:
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rotate = malloc(sizeof *rotate);
|
||||||
|
if (!rotate)
|
||||||
|
return;
|
||||||
|
|
||||||
|
rotate->grab.interface = &rotate_grab_interface;
|
||||||
|
rotate->surface = surface;
|
||||||
|
|
||||||
|
weston_surface_to_global(surface->surface,
|
||||||
|
surface->surface->geometry.width / 2,
|
||||||
|
surface->surface->geometry.height / 2,
|
||||||
|
&rotate->center.x, &rotate->center.y);
|
||||||
|
|
||||||
|
wl_input_device_start_grab(device, &rotate->grab, time);
|
||||||
|
wl_input_device_set_pointer_focus(device, NULL, time, 0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
activate(struct weston_shell *base, struct weston_surface *es,
|
activate(struct weston_shell *base, struct weston_surface *es,
|
||||||
struct weston_input_device *device, uint32_t time)
|
struct weston_input_device *device, uint32_t time)
|
||||||
@@ -1098,8 +1232,11 @@ center_on_output(struct weston_surface *surface, struct weston_output *output)
|
|||||||
{
|
{
|
||||||
struct weston_mode *mode = output->current;
|
struct weston_mode *mode = output->current;
|
||||||
|
|
||||||
surface->x = output->x + (mode->width - surface->width) / 2;
|
surface->geometry.x =
|
||||||
surface->y = output->y + (mode->height - surface->height) / 2;
|
output->x + (mode->width - surface->geometry.width) / 2;
|
||||||
|
surface->geometry.y =
|
||||||
|
output->y + (mode->height - surface->geometry.height) / 2;
|
||||||
|
surface->geometry.dirty = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -1125,14 +1262,16 @@ map(struct weston_shell *base,
|
|||||||
do_configure = 1;
|
do_configure = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
surface->width = width;
|
surface->geometry.width = width;
|
||||||
surface->height = height;
|
surface->geometry.height = height;
|
||||||
|
surface->geometry.dirty = 1;
|
||||||
|
|
||||||
/* initial positioning, see also configure() */
|
/* initial positioning, see also configure() */
|
||||||
switch (surface_type) {
|
switch (surface_type) {
|
||||||
case SHELL_SURFACE_TOPLEVEL:
|
case SHELL_SURFACE_TOPLEVEL:
|
||||||
surface->x = 10 + random() % 400;
|
surface->geometry.x = 10 + random() % 400;
|
||||||
surface->y = 10 + random() % 400;
|
surface->geometry.y = 10 + random() % 400;
|
||||||
|
surface->geometry.dirty = 1;
|
||||||
break;
|
break;
|
||||||
case SHELL_SURFACE_SCREENSAVER:
|
case SHELL_SURFACE_SCREENSAVER:
|
||||||
case SHELL_SURFACE_FULLSCREEN:
|
case SHELL_SURFACE_FULLSCREEN:
|
||||||
@@ -1189,8 +1328,9 @@ map(struct weston_shell *base,
|
|||||||
|
|
||||||
switch (surface_type) {
|
switch (surface_type) {
|
||||||
case SHELL_SURFACE_TOPLEVEL:
|
case SHELL_SURFACE_TOPLEVEL:
|
||||||
surface->x = 10 + random() % 400;
|
surface->geometry.x = 10 + random() % 400;
|
||||||
surface->y = 10 + random() % 400;
|
surface->geometry.y = 10 + random() % 400;
|
||||||
|
surface->geometry.dirty = 1;
|
||||||
break;
|
break;
|
||||||
case SHELL_SURFACE_POPUP:
|
case SHELL_SURFACE_POPUP:
|
||||||
shell_map_popup(shsurf, shsurf->popup.time);
|
shell_map_popup(shsurf, shsurf->popup.time);
|
||||||
@@ -1199,10 +1339,12 @@ map(struct weston_shell *base,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
surface->width = width;
|
surface->geometry.width = width;
|
||||||
surface->height = height;
|
surface->geometry.height = height;
|
||||||
|
surface->geometry.dirty = 1;
|
||||||
if (do_configure) {
|
if (do_configure) {
|
||||||
weston_surface_configure(surface, surface->x, surface->y,
|
weston_surface_configure(surface, surface->geometry.x,
|
||||||
|
surface->geometry.y,
|
||||||
width, height);
|
width, height);
|
||||||
weston_compositor_repick(compositor);
|
weston_compositor_repick(compositor);
|
||||||
}
|
}
|
||||||
@@ -1238,8 +1380,9 @@ configure(struct weston_shell *base, struct weston_surface *surface,
|
|||||||
if (shsurf)
|
if (shsurf)
|
||||||
surface_type = shsurf->type;
|
surface_type = shsurf->type;
|
||||||
|
|
||||||
surface->width = width;
|
surface->geometry.width = width;
|
||||||
surface->height = height;
|
surface->geometry.height = height;
|
||||||
|
surface->geometry.dirty = 1;
|
||||||
|
|
||||||
switch (surface_type) {
|
switch (surface_type) {
|
||||||
case SHELL_SURFACE_SCREENSAVER:
|
case SHELL_SURFACE_SCREENSAVER:
|
||||||
@@ -1474,6 +1617,9 @@ shell_init(struct weston_compositor *ec)
|
|||||||
terminate_binding, ec);
|
terminate_binding, ec);
|
||||||
weston_compositor_add_binding(ec, 0, BTN_LEFT, 0,
|
weston_compositor_add_binding(ec, 0, BTN_LEFT, 0,
|
||||||
click_to_activate_binding, ec);
|
click_to_activate_binding, ec);
|
||||||
|
weston_compositor_add_binding(ec, 0, BTN_LEFT,
|
||||||
|
MODIFIER_SUPER | MODIFIER_ALT,
|
||||||
|
rotate_binding, NULL);
|
||||||
|
|
||||||
ec->shell = &shell->shell;
|
ec->shell = &shell->shell;
|
||||||
|
|
||||||
|
|||||||
+14
-9
@@ -110,8 +110,9 @@ tablet_shell_map(struct weston_shell *base, struct weston_surface *surface,
|
|||||||
struct tablet_shell *shell =
|
struct tablet_shell *shell =
|
||||||
container_of(base, struct tablet_shell, shell);
|
container_of(base, struct tablet_shell, shell);
|
||||||
|
|
||||||
surface->x = 0;
|
surface->geometry.x = 0;
|
||||||
surface->y = 0;
|
surface->geometry.y = 0;
|
||||||
|
surface->geometry.dirty = 1;
|
||||||
|
|
||||||
if (surface == shell->lockscreen_surface) {
|
if (surface == shell->lockscreen_surface) {
|
||||||
/* */
|
/* */
|
||||||
@@ -133,7 +134,8 @@ tablet_shell_map(struct weston_shell *base, struct weston_surface *surface,
|
|||||||
}
|
}
|
||||||
|
|
||||||
wl_list_insert(&shell->compositor->surface_list, &surface->link);
|
wl_list_insert(&shell->compositor->surface_list, &surface->link);
|
||||||
weston_surface_configure(surface, surface->x, surface->y, width, height);
|
weston_surface_configure(surface, surface->geometry.x,
|
||||||
|
surface->geometry.y, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -165,8 +167,9 @@ tablet_shell_set_lockscreen(struct wl_client *client,
|
|||||||
struct tablet_shell *shell = resource->data;
|
struct tablet_shell *shell = resource->data;
|
||||||
struct weston_surface *es = surface_resource->data;
|
struct weston_surface *es = surface_resource->data;
|
||||||
|
|
||||||
es->x = 0;
|
es->geometry.x = 0;
|
||||||
es->y = 0;
|
es->geometry.y = 0;
|
||||||
|
es->geometry.dirty = 1;
|
||||||
shell->lockscreen_surface = es;
|
shell->lockscreen_surface = es;
|
||||||
shell->lockscreen_listener.func = handle_lockscreen_surface_destroy;
|
shell->lockscreen_listener.func = handle_lockscreen_surface_destroy;
|
||||||
wl_list_insert(es->surface.resource.destroy_listener_list.prev,
|
wl_list_insert(es->surface.resource.destroy_listener_list.prev,
|
||||||
@@ -199,8 +202,9 @@ tablet_shell_set_switcher(struct wl_client *client,
|
|||||||
* layer idea, we should be able to hit the framerate on the
|
* layer idea, we should be able to hit the framerate on the
|
||||||
* fade/zoom in. */
|
* fade/zoom in. */
|
||||||
shell->switcher_surface = es;
|
shell->switcher_surface = es;
|
||||||
shell->switcher_surface->x = 0;
|
shell->switcher_surface->geometry.x = 0;
|
||||||
shell->switcher_surface->y = 0;
|
shell->switcher_surface->geometry.y = 0;
|
||||||
|
shell->switcher_surface->geometry.dirty = 1;
|
||||||
|
|
||||||
shell->switcher_listener.func = handle_switcher_surface_destroy;
|
shell->switcher_listener.func = handle_switcher_surface_destroy;
|
||||||
wl_list_insert(es->surface.resource.destroy_listener_list.prev,
|
wl_list_insert(es->surface.resource.destroy_listener_list.prev,
|
||||||
@@ -215,8 +219,9 @@ tablet_shell_set_homescreen(struct wl_client *client,
|
|||||||
struct tablet_shell *shell = resource->data;
|
struct tablet_shell *shell = resource->data;
|
||||||
|
|
||||||
shell->home_surface = surface_resource->data;
|
shell->home_surface = surface_resource->data;
|
||||||
shell->home_surface->x = 0;
|
shell->home_surface->geometry.x = 0;
|
||||||
shell->home_surface->y = 0;
|
shell->home_surface->geometry.y = 0;
|
||||||
|
shell->home_surface->geometry.dirty = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
+11
-74
@@ -27,70 +27,6 @@
|
|||||||
|
|
||||||
#include "compositor.h"
|
#include "compositor.h"
|
||||||
|
|
||||||
WL_EXPORT void
|
|
||||||
weston_matrix_init(struct weston_matrix *matrix)
|
|
||||||
{
|
|
||||||
static const struct weston_matrix identity = {
|
|
||||||
{ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 }
|
|
||||||
};
|
|
||||||
|
|
||||||
memcpy(matrix, &identity, sizeof identity);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
weston_matrix_multiply(struct weston_matrix *m, const struct weston_matrix *n)
|
|
||||||
{
|
|
||||||
struct weston_matrix tmp;
|
|
||||||
const GLfloat *row, *column;
|
|
||||||
div_t d;
|
|
||||||
int i, j;
|
|
||||||
|
|
||||||
for (i = 0; i < 16; i++) {
|
|
||||||
tmp.d[i] = 0;
|
|
||||||
d = div(i, 4);
|
|
||||||
row = m->d + d.quot * 4;
|
|
||||||
column = n->d + d.rem;
|
|
||||||
for (j = 0; j < 4; j++)
|
|
||||||
tmp.d[i] += row[j] * column[j * 4];
|
|
||||||
}
|
|
||||||
memcpy(m, &tmp, sizeof tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
WL_EXPORT void
|
|
||||||
weston_matrix_translate(struct weston_matrix *matrix, GLfloat x, GLfloat y, GLfloat z)
|
|
||||||
{
|
|
||||||
struct weston_matrix translate = {
|
|
||||||
{ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1 }
|
|
||||||
};
|
|
||||||
|
|
||||||
weston_matrix_multiply(matrix, &translate);
|
|
||||||
}
|
|
||||||
|
|
||||||
WL_EXPORT void
|
|
||||||
weston_matrix_scale(struct weston_matrix *matrix, GLfloat x, GLfloat y, GLfloat z)
|
|
||||||
{
|
|
||||||
struct weston_matrix scale = {
|
|
||||||
{ x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, 0, 0, 0, 1 }
|
|
||||||
};
|
|
||||||
|
|
||||||
weston_matrix_multiply(matrix, &scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
WL_EXPORT void
|
|
||||||
weston_matrix_transform(struct weston_matrix *matrix, struct weston_vector *v)
|
|
||||||
{
|
|
||||||
int i, j;
|
|
||||||
struct weston_vector t;
|
|
||||||
|
|
||||||
for (i = 0; i < 4; i++) {
|
|
||||||
t.f[i] = 0;
|
|
||||||
for (j = 0; j < 4; j++)
|
|
||||||
t.f[i] += v->f[j] * matrix->d[i + j * 4];
|
|
||||||
}
|
|
||||||
|
|
||||||
*v = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
WL_EXPORT void
|
WL_EXPORT void
|
||||||
weston_spring_init(struct weston_spring *spring,
|
weston_spring_init(struct weston_spring *spring,
|
||||||
double k, double current, double target)
|
double k, double current, double target)
|
||||||
@@ -162,7 +98,8 @@ weston_zoom_destroy(struct weston_zoom *zoom)
|
|||||||
{
|
{
|
||||||
wl_list_remove(&zoom->animation.link);
|
wl_list_remove(&zoom->animation.link);
|
||||||
wl_list_remove(&zoom->listener.link);
|
wl_list_remove(&zoom->listener.link);
|
||||||
zoom->surface->transform = NULL;
|
wl_list_remove(&zoom->transform.link);
|
||||||
|
zoom->surface->geometry.dirty = 1;
|
||||||
if (zoom->done)
|
if (zoom->done)
|
||||||
zoom->done(zoom, zoom->data);
|
zoom->done(zoom, zoom->data);
|
||||||
free(zoom);
|
free(zoom);
|
||||||
@@ -198,19 +135,18 @@ weston_zoom_frame(struct weston_animation *animation,
|
|||||||
(zoom->stop - zoom->start) * zoom->spring.current;
|
(zoom->stop - zoom->start) * zoom->spring.current;
|
||||||
weston_matrix_init(&zoom->transform.matrix);
|
weston_matrix_init(&zoom->transform.matrix);
|
||||||
weston_matrix_translate(&zoom->transform.matrix,
|
weston_matrix_translate(&zoom->transform.matrix,
|
||||||
-(es->x + es->width / 2.0),
|
-0.5f * es->geometry.width,
|
||||||
-(es->y + es->height / 2.0), 0);
|
-0.5f * es->geometry.height, 0);
|
||||||
weston_matrix_scale(&zoom->transform.matrix, scale, scale, scale);
|
weston_matrix_scale(&zoom->transform.matrix, scale, scale, scale);
|
||||||
weston_matrix_translate(&zoom->transform.matrix,
|
weston_matrix_translate(&zoom->transform.matrix,
|
||||||
es->x + es->width / 2.0,
|
0.5f * es->geometry.width,
|
||||||
es->y + es->height / 2.0, 0);
|
0.5f * es->geometry.height, 0);
|
||||||
|
|
||||||
es->alpha = zoom->spring.current * 255;
|
es->alpha = zoom->spring.current * 255;
|
||||||
if (es->alpha > 255)
|
if (es->alpha > 255)
|
||||||
es->alpha = 255;
|
es->alpha = 255;
|
||||||
scale = 1.0 / zoom->spring.current;
|
|
||||||
weston_matrix_init(&zoom->transform.inverse);
|
zoom->surface->geometry.dirty = 1;
|
||||||
weston_matrix_scale(&zoom->transform.inverse, scale, scale, scale);
|
|
||||||
|
|
||||||
weston_compositor_damage_all(es->compositor);
|
weston_compositor_damage_all(es->compositor);
|
||||||
}
|
}
|
||||||
@@ -230,7 +166,8 @@ weston_zoom_run(struct weston_surface *surface, GLfloat start, GLfloat stop,
|
|||||||
zoom->data = data;
|
zoom->data = data;
|
||||||
zoom->start = start;
|
zoom->start = start;
|
||||||
zoom->stop = stop;
|
zoom->stop = stop;
|
||||||
surface->transform = &zoom->transform;
|
wl_list_insert(&surface->geometry.transformation_list,
|
||||||
|
&zoom->transform.link);
|
||||||
weston_spring_init(&zoom->spring, 200.0, 0.0, 1.0);
|
weston_spring_init(&zoom->spring, 200.0, 0.0, 1.0);
|
||||||
zoom->spring.friction = 700;
|
zoom->spring.friction = 700;
|
||||||
zoom->spring.timestamp = weston_compositor_get_time();
|
zoom->spring.timestamp = weston_compositor_get_time();
|
||||||
@@ -241,7 +178,7 @@ weston_zoom_run(struct weston_surface *surface, GLfloat start, GLfloat stop,
|
|||||||
wl_list_insert(surface->surface.resource.destroy_listener_list.prev,
|
wl_list_insert(surface->surface.resource.destroy_listener_list.prev,
|
||||||
&zoom->listener.link);
|
&zoom->listener.link);
|
||||||
|
|
||||||
wl_list_insert(surface->compositor->animation_list.prev,
|
wl_list_insert(&surface->compositor->animation_list,
|
||||||
&zoom->animation.link);
|
&zoom->animation.link);
|
||||||
|
|
||||||
return zoom;
|
return zoom;
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
matrix-test
|
||||||
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
if BUILD_TESTS
|
||||||
|
|
||||||
|
noinst_PROGRAMS = matrix-test
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
AM_CFLAGS = $(GCC_CFLAGS)
|
||||||
|
AM_CPPFLAGS = -I../src -DUNIT_TEST
|
||||||
|
|
||||||
|
matrix_test_SOURCES = \
|
||||||
|
matrix-test.c \
|
||||||
|
../src/matrix.c \
|
||||||
|
../src/matrix.h
|
||||||
|
matrix_test_LDADD = -lm -lrt
|
||||||
@@ -0,0 +1,422 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2012 Collabora, Ltd.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, distribute, and sell this software and
|
||||||
|
* its documentation for any purpose is hereby granted without fee, provided
|
||||||
|
* that the above copyright notice appear in all copies and that both that
|
||||||
|
* copyright notice and this permission notice appear in supporting
|
||||||
|
* documentation, and that the name of the copyright holders not be used in
|
||||||
|
* advertising or publicity pertaining to distribution of the software
|
||||||
|
* without specific, written prior permission. The copyright holders make
|
||||||
|
* no representations about the suitability of this software for any
|
||||||
|
* purpose. It is provided "as is" without express or implied warranty.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||||
|
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||||
|
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||||
|
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <GLES2/gl2.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "matrix.h"
|
||||||
|
|
||||||
|
struct inverse_matrix {
|
||||||
|
double LU[16]; /* column-major */
|
||||||
|
unsigned perm[4]; /* permutation */
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct timespec begin_time;
|
||||||
|
|
||||||
|
static void
|
||||||
|
reset_timer(void)
|
||||||
|
{
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &begin_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
static double
|
||||||
|
read_timer(void)
|
||||||
|
{
|
||||||
|
struct timespec t;
|
||||||
|
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &t);
|
||||||
|
return (double)(t.tv_sec - begin_time.tv_sec) +
|
||||||
|
1e-9 * (t.tv_nsec - begin_time.tv_nsec);
|
||||||
|
}
|
||||||
|
|
||||||
|
static double
|
||||||
|
det3x3(const GLfloat *c0, const GLfloat *c1, const GLfloat *c2)
|
||||||
|
{
|
||||||
|
return (double)
|
||||||
|
c0[0] * c1[1] * c2[2] +
|
||||||
|
c1[0] * c2[1] * c0[2] +
|
||||||
|
c2[0] * c0[1] * c1[2] -
|
||||||
|
c0[2] * c1[1] * c2[0] -
|
||||||
|
c1[2] * c2[1] * c0[0] -
|
||||||
|
c2[2] * c0[1] * c1[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
static double
|
||||||
|
determinant(const struct weston_matrix *m)
|
||||||
|
{
|
||||||
|
double det = 0;
|
||||||
|
#if 1
|
||||||
|
/* develop on last row */
|
||||||
|
det -= m->d[3 + 0 * 4] * det3x3(&m->d[4], &m->d[8], &m->d[12]);
|
||||||
|
det += m->d[3 + 1 * 4] * det3x3(&m->d[0], &m->d[8], &m->d[12]);
|
||||||
|
det -= m->d[3 + 2 * 4] * det3x3(&m->d[0], &m->d[4], &m->d[12]);
|
||||||
|
det += m->d[3 + 3 * 4] * det3x3(&m->d[0], &m->d[4], &m->d[8]);
|
||||||
|
#else
|
||||||
|
/* develop on first row */
|
||||||
|
det += m->d[0 + 0 * 4] * det3x3(&m->d[5], &m->d[9], &m->d[13]);
|
||||||
|
det -= m->d[0 + 1 * 4] * det3x3(&m->d[1], &m->d[9], &m->d[13]);
|
||||||
|
det += m->d[0 + 2 * 4] * det3x3(&m->d[1], &m->d[5], &m->d[13]);
|
||||||
|
det -= m->d[0 + 3 * 4] * det3x3(&m->d[1], &m->d[5], &m->d[9]);
|
||||||
|
#endif
|
||||||
|
return det;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_permutation_matrix(const struct inverse_matrix *m)
|
||||||
|
{
|
||||||
|
const unsigned *p = m->perm;
|
||||||
|
const char *row[4] = {
|
||||||
|
"1 0 0 0\n",
|
||||||
|
"0 1 0 0\n",
|
||||||
|
"0 0 1 0\n",
|
||||||
|
"0 0 0 1\n"
|
||||||
|
};
|
||||||
|
|
||||||
|
printf(" P =\n%s%s%s%s", row[p[0]], row[p[1]], row[p[2]], row[p[3]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_LU_decomposition(const struct inverse_matrix *m)
|
||||||
|
{
|
||||||
|
unsigned r, c;
|
||||||
|
|
||||||
|
printf(" L "
|
||||||
|
" U\n");
|
||||||
|
for (r = 0; r < 4; ++r) {
|
||||||
|
double v;
|
||||||
|
|
||||||
|
for (c = 0; c < 4; ++c) {
|
||||||
|
if (c < r)
|
||||||
|
v = m->LU[r + c * 4];
|
||||||
|
else if (c == r)
|
||||||
|
v = 1.0;
|
||||||
|
else
|
||||||
|
v = 0.0;
|
||||||
|
printf(" %12.6f", v);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(" | ");
|
||||||
|
|
||||||
|
for (c = 0; c < 4; ++c) {
|
||||||
|
if (c >= r)
|
||||||
|
v = m->LU[r + c * 4];
|
||||||
|
else
|
||||||
|
v = 0.0;
|
||||||
|
printf(" %12.6f", v);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_inverse_data_matrix(const struct inverse_matrix *m)
|
||||||
|
{
|
||||||
|
unsigned r, c;
|
||||||
|
|
||||||
|
for (r = 0; r < 4; ++r) {
|
||||||
|
for (c = 0; c < 4; ++c)
|
||||||
|
printf(" %12.6f", m->LU[r + c * 4]);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("permutation: ");
|
||||||
|
for (r = 0; r < 4; ++r)
|
||||||
|
printf(" %u", m->perm[r]);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_matrix(const struct weston_matrix *m)
|
||||||
|
{
|
||||||
|
unsigned r, c;
|
||||||
|
|
||||||
|
for (r = 0; r < 4; ++r) {
|
||||||
|
for (c = 0; c < 4; ++c)
|
||||||
|
printf(" %14.6e", m->d[r + c * 4]);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static double
|
||||||
|
frand(void)
|
||||||
|
{
|
||||||
|
double r = random();
|
||||||
|
return r / (double)(RAND_MAX / 2) - 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
randomize_matrix(struct weston_matrix *m)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < 16; ++i)
|
||||||
|
#if 1
|
||||||
|
m->d[i] = frand() * exp(10.0 * frand());
|
||||||
|
#else
|
||||||
|
m->d[i] = frand();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Take a matrix, compute inverse, multiply together
|
||||||
|
* and subtract the identity matrix to get the error matrix.
|
||||||
|
* Return the largest absolute value from the error matrix.
|
||||||
|
*/
|
||||||
|
static double
|
||||||
|
test_inverse(struct weston_matrix *m)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
struct inverse_matrix q;
|
||||||
|
double errsup = 0.0;
|
||||||
|
|
||||||
|
if (matrix_invert(q.LU, q.perm, m) != 0)
|
||||||
|
return INFINITY;
|
||||||
|
|
||||||
|
for (i = 0; i < 4; ++i)
|
||||||
|
inverse_transform(q.LU, q.perm, &m->d[i * 4]);
|
||||||
|
|
||||||
|
m->d[0] -= 1.0f;
|
||||||
|
m->d[5] -= 1.0f;
|
||||||
|
m->d[10] -= 1.0f;
|
||||||
|
m->d[15] -= 1.0f;
|
||||||
|
|
||||||
|
for (i = 0; i < 16; ++i) {
|
||||||
|
double err = fabs(m->d[i]);
|
||||||
|
if (err > errsup)
|
||||||
|
errsup = err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return errsup;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TEST_OK,
|
||||||
|
TEST_NOT_INVERTIBLE_OK,
|
||||||
|
TEST_FAIL,
|
||||||
|
TEST_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
test(void)
|
||||||
|
{
|
||||||
|
struct weston_matrix m;
|
||||||
|
struct weston_matrix n;
|
||||||
|
double det, errsup;
|
||||||
|
|
||||||
|
randomize_matrix(&m);
|
||||||
|
n = m;
|
||||||
|
det = determinant(&m);
|
||||||
|
|
||||||
|
errsup = test_inverse(&m);
|
||||||
|
if (errsup < 1e-6)
|
||||||
|
return TEST_OK;
|
||||||
|
|
||||||
|
if (fabs(det) < 1e-5 && isinf(errsup))
|
||||||
|
return TEST_NOT_INVERTIBLE_OK;
|
||||||
|
|
||||||
|
printf("test fail, det: %g, error sup: %g\n", det, errsup);
|
||||||
|
/* print_matrix(&n);*/
|
||||||
|
return TEST_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int running;
|
||||||
|
static void
|
||||||
|
stopme(int n)
|
||||||
|
{
|
||||||
|
running = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_loop_precision(void)
|
||||||
|
{
|
||||||
|
int counts[TEST_COUNT] = { 0 };
|
||||||
|
|
||||||
|
printf("\nRunning a test loop for 10 seconds...\n");
|
||||||
|
running = 1;
|
||||||
|
alarm(10);
|
||||||
|
while (running) {
|
||||||
|
counts[test()]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("tests: %d ok, %d not invertible but ok, %d failed.\n"
|
||||||
|
"Total: %d iterations.\n",
|
||||||
|
counts[TEST_OK], counts[TEST_NOT_INVERTIBLE_OK],
|
||||||
|
counts[TEST_FAIL],
|
||||||
|
counts[TEST_OK] + counts[TEST_NOT_INVERTIBLE_OK] +
|
||||||
|
counts[TEST_FAIL]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __attribute__((noinline))
|
||||||
|
test_loop_speed_matrixvector(void)
|
||||||
|
{
|
||||||
|
struct weston_matrix m;
|
||||||
|
struct weston_vector v = { { 0.5, 0.5, 0.5, 1.0 } };
|
||||||
|
unsigned long count = 0;
|
||||||
|
double t;
|
||||||
|
|
||||||
|
printf("\nRunning 3 s test on weston_matrix_transform()...\n");
|
||||||
|
|
||||||
|
weston_matrix_init(&m);
|
||||||
|
|
||||||
|
running = 1;
|
||||||
|
alarm(3);
|
||||||
|
reset_timer();
|
||||||
|
while (running) {
|
||||||
|
weston_matrix_transform(&m, &v);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
t = read_timer();
|
||||||
|
|
||||||
|
printf("%lu iterations in %f seconds, avg. %.1f us/iter.\n",
|
||||||
|
count, t, 1e9 * t / count);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __attribute__((noinline))
|
||||||
|
test_loop_speed_inversetransform(void)
|
||||||
|
{
|
||||||
|
struct weston_matrix m;
|
||||||
|
struct inverse_matrix inv;
|
||||||
|
struct weston_vector v = { { 0.5, 0.5, 0.5, 1.0 } };
|
||||||
|
unsigned long count = 0;
|
||||||
|
double t;
|
||||||
|
|
||||||
|
printf("\nRunning 3 s test on inverse_transform()...\n");
|
||||||
|
|
||||||
|
weston_matrix_init(&m);
|
||||||
|
matrix_invert(inv.LU, inv.perm, &m);
|
||||||
|
|
||||||
|
running = 1;
|
||||||
|
alarm(3);
|
||||||
|
reset_timer();
|
||||||
|
while (running) {
|
||||||
|
inverse_transform(inv.LU, inv.perm, v.f);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
t = read_timer();
|
||||||
|
|
||||||
|
printf("%lu iterations in %f seconds, avg. %.1f us/iter.\n",
|
||||||
|
count, t, 1e9 * t / count);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __attribute__((noinline))
|
||||||
|
test_loop_speed_invert(void)
|
||||||
|
{
|
||||||
|
struct weston_matrix m;
|
||||||
|
struct inverse_matrix inv;
|
||||||
|
unsigned long count = 0;
|
||||||
|
double t;
|
||||||
|
|
||||||
|
printf("\nRunning 3 s test on matrix_invert()...\n");
|
||||||
|
|
||||||
|
weston_matrix_init(&m);
|
||||||
|
|
||||||
|
running = 1;
|
||||||
|
alarm(3);
|
||||||
|
reset_timer();
|
||||||
|
while (running) {
|
||||||
|
matrix_invert(inv.LU, inv.perm, &m);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
t = read_timer();
|
||||||
|
|
||||||
|
printf("%lu iterations in %f seconds, avg. %.1f ns/iter.\n",
|
||||||
|
count, t, 1e9 * t / count);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __attribute__((noinline))
|
||||||
|
test_loop_speed_invert_explicit(void)
|
||||||
|
{
|
||||||
|
struct weston_matrix m;
|
||||||
|
unsigned long count = 0;
|
||||||
|
double t;
|
||||||
|
|
||||||
|
printf("\nRunning 3 s test on weston_matrix_invert()...\n");
|
||||||
|
|
||||||
|
weston_matrix_init(&m);
|
||||||
|
|
||||||
|
running = 1;
|
||||||
|
alarm(3);
|
||||||
|
reset_timer();
|
||||||
|
while (running) {
|
||||||
|
weston_matrix_invert(&m, &m);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
t = read_timer();
|
||||||
|
|
||||||
|
printf("%lu iterations in %f seconds, avg. %.1f ns/iter.\n",
|
||||||
|
count, t, 1e9 * t / count);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
struct sigaction ding;
|
||||||
|
struct weston_matrix M;
|
||||||
|
struct inverse_matrix Q;
|
||||||
|
int ret;
|
||||||
|
double errsup;
|
||||||
|
double det;
|
||||||
|
|
||||||
|
ding.sa_handler = stopme;
|
||||||
|
sigemptyset(&ding.sa_mask);
|
||||||
|
ding.sa_flags = 0;
|
||||||
|
sigaction(SIGALRM, &ding, NULL);
|
||||||
|
|
||||||
|
srandom(13);
|
||||||
|
|
||||||
|
M.d[0] = 3.0; M.d[4] = 17.0; M.d[8] = 10.0; M.d[12] = 0.0;
|
||||||
|
M.d[1] = 2.0; M.d[5] = 4.0; M.d[9] = -2.0; M.d[13] = 0.0;
|
||||||
|
M.d[2] = 6.0; M.d[6] = 18.0; M.d[10] = -12; M.d[14] = 0.0;
|
||||||
|
M.d[3] = 0.0; M.d[7] = 0.0; M.d[11] = 0.0; M.d[15] = 1.0;
|
||||||
|
|
||||||
|
ret = matrix_invert(Q.LU, Q.perm, &M);
|
||||||
|
printf("ret = %d\n", ret);
|
||||||
|
printf("det = %g\n\n", determinant(&M));
|
||||||
|
|
||||||
|
if (ret != 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
print_inverse_data_matrix(&Q);
|
||||||
|
printf("P * A = L * U\n");
|
||||||
|
print_permutation_matrix(&Q);
|
||||||
|
print_LU_decomposition(&Q);
|
||||||
|
|
||||||
|
|
||||||
|
printf("a random matrix:\n");
|
||||||
|
randomize_matrix(&M);
|
||||||
|
det = determinant(&M);
|
||||||
|
print_matrix(&M);
|
||||||
|
errsup = test_inverse(&M);
|
||||||
|
printf("\nThe matrix multiplied by its inverse, error:\n");
|
||||||
|
print_matrix(&M);
|
||||||
|
printf("max abs error: %g, original determinant %g\n", errsup, det);
|
||||||
|
|
||||||
|
test_loop_precision();
|
||||||
|
test_loop_speed_matrixvector();
|
||||||
|
test_loop_speed_inversetransform();
|
||||||
|
test_loop_speed_invert();
|
||||||
|
test_loop_speed_invert_explicit();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user