Merge remote-tracking branch 'pq/transform-v1'

This commit is contained in:
Kristian Høgsberg 2012-01-27 11:42:18 -05:00
commit b7674a2a6c
18 changed files with 1511 additions and 293 deletions

View File

@ -1 +1 @@
SUBDIRS = shared src clients data protocol
SUBDIRS = shared src clients data protocol tests

6
clients/.gitignore vendored
View File

@ -1,3 +1,4 @@
clickdot
desktop-shell-client-protocol.h
desktop-shell-protocol.c
dnd
@ -12,11 +13,12 @@ screenshooter-protocol.c
screenshot
simple-egl
simple-shm
simple-touch
smoke
tablet-shell-client-protocol.h
tablet-shell-protocol.c
terminal
view
wayland-desktop-shell
wayland-tablet-shell
weston-desktop-shell
weston-tablet-shell
wscreensaver

View File

@ -37,6 +37,7 @@ clients_programs = \
smoke \
resizor \
eventdemo \
clickdot \
$(full_gl_client_programs)
desktop_shell = weston-desktop-shell
@ -83,6 +84,9 @@ resizor_LDADD = $(toolkit_libs)
eventdemo_SOURCES = eventdemo.c
eventdemo_LDADD = $(toolkit_libs)
clickdot_SOURCES = clickdot.c
clickdot_LDADD = $(toolkit_libs)
weston_desktop_shell_SOURCES = \
desktop-shell.c \
desktop-shell-client-protocol.h \

181
clients/clickdot.c Normal file
View File

@ -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;
}

View File

@ -148,6 +148,9 @@ AC_ARG_ENABLE(tablet-shell, [ --enable-tablet-shell],,
AM_CONDITIONAL(ENABLE_TABLET_SHELL,
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
GCC_CFLAGS="-Wall -g -Wstrict-prototypes -Wmissing-prototypes -fvisibility=hidden"
fi
@ -160,7 +163,8 @@ AC_CONFIG_FILES([Makefile
src/Makefile
clients/Makefile
data/Makefile
protocol/Makefile])
protocol/Makefile
tests/Makefile])
AC_OUTPUT
if test "x$enable_setuid_install" == xyes; then

2
src/.gitignore vendored
View File

@ -1,4 +1,4 @@
wayland-compositor
weston
screenshooter-protocol.c
screenshooter-server-protocol.h
tablet-shell-protocol.c

View File

@ -20,6 +20,8 @@ weston_SOURCES = \
screenshooter-protocol.c \
screenshooter-server-protocol.h \
util.c \
matrix.c \
matrix.h \
$(xserver_launcher_sources)
if ENABLE_SETUID_INSTALL

View File

@ -97,16 +97,18 @@ drm_output_prepare_scanout_surface(struct drm_output *output)
struct weston_surface, link);
if (es->visual != WESTON_RGB_VISUAL ||
es->x != output->base.x ||
es->y != output->base.y ||
es->width != output->base.current->width ||
es->height != output->base.current->height ||
es->geometry.x != output->base.x ||
es->geometry.y != output->base.y ||
es->geometry.width != output->base.current->width ||
es->geometry.height != output->base.current->height ||
es->transform.enabled ||
es->image == EGL_NO_IMAGE_KHR)
return -1;
bo = gbm_bo_create_from_egl_image(c->gbm,
c->base.display, es->image,
es->width, es->height,
es->geometry.width,
es->geometry.height,
GBM_BO_USE_SCANOUT);
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,
eid->sprite->x, eid->sprite->y,
eid->sprite->width, eid->sprite->height);
eid->sprite->geometry.x,
eid->sprite->geometry.y,
eid->sprite->geometry.width,
eid->sprite->geometry.height);
pixman_region32_intersect_rect(&cursor_region, &cursor_region,
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)
goto out;
if (eid->sprite->width > 64 || eid->sprite->height > 64)
if (eid->sprite->geometry.width > 64 ||
eid->sprite->geometry.height > 64)
goto out;
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,
eid->sprite->x - output->base.x,
eid->sprite->y - output->base.y);
eid->sprite->geometry.x - output->base.x,
eid->sprite->geometry.y - output->base.y);
if (ret) {
fprintf(stderr, "failed to move cursor: %s\n", strerror(-ret));
goto out;

View File

@ -1,6 +1,7 @@
/*
* Copyright © 2010-2011 Intel Corporation
* 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
@ -189,10 +190,10 @@ weston_surface_create(struct weston_compositor *compositor,
surface->compositor = compositor;
surface->visual = WESTON_NONE_VISUAL;
surface->image = EGL_NO_IMAGE_KHR;
surface->x = x;
surface->y = y;
surface->width = width;
surface->height = height;
surface->geometry.x = x;
surface->geometry.y = y;
surface->geometry.width = width;
surface->geometry.height = height;
surface->alpha = 255;
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->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;
}
@ -226,25 +232,189 @@ weston_surface_set_color(struct weston_surface *surface,
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
weston_surface_damage_rectangle(struct weston_surface *surface,
int32_t x, int32_t y,
int32_t width, int32_t height)
int32_t sx, int32_t sy,
int32_t width, int32_t height)
{
struct weston_compositor *compositor = surface->compositor;
weston_surface_update_transform(surface);
pixman_region32_union_rect(&surface->damage,
&surface->damage,
surface->x + x, surface->y + y,
width, height);
weston_compositor_schedule_repaint(compositor);
if (surface->transform.enabled) {
pixman_region32_t box;
surface_compute_bbox(surface, sx, sy, width, height, &box);
pixman_region32_union(&surface->damage, &surface->damage,
&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
weston_surface_damage(struct weston_surface *surface)
{
weston_surface_damage_rectangle(surface, 0, 0,
surface->width, surface->height);
weston_surface_update_transform(surface);
pixman_region32_union(&surface->damage, &surface->damage,
&surface->transform.boundingbox);
weston_compositor_schedule_repaint(surface->compositor);
}
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);
pixman_region32_union_rect(&below->damage,
&below->damage,
surface->x, surface->y,
surface->width, surface->height);
weston_surface_update_transform(surface);
pixman_region32_union(&below->damage, &below->damage,
&surface->transform.boundingbox);
weston_compositor_schedule_repaint(surface->compositor);
}
@ -288,10 +458,11 @@ weston_surface_configure(struct weston_surface *surface,
{
weston_surface_damage_below(surface);
surface->x = x;
surface->y = y;
surface->width = width;
surface->height = height;
surface->geometry.x = x;
surface->geometry.y = y;
surface->geometry.width = width;
surface->geometry.height = height;
surface->geometry.dirty = 1;
weston_surface_assign_output(surface);
weston_surface_damage(surface);
@ -299,20 +470,14 @@ weston_surface_configure(struct weston_surface *surface,
pixman_region32_fini(&surface->opaque);
if (surface->visual == WESTON_RGB_VISUAL)
pixman_region32_init_rect(&surface->opaque,
surface->x, surface->y,
surface->width, surface->height);
surface->geometry.x,
surface->geometry.y,
surface->geometry.width,
surface->geometry.height);
else
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
weston_compositor_get_time(void)
{
@ -344,8 +509,8 @@ weston_device_repick(struct wl_input_device *device, uint32_t time)
focus = (struct weston_surface *) device->grab->focus;
if (focus)
weston_surface_transform(focus, device->x, device->y,
&device->grab->x, &device->grab->y);
weston_surface_from_global(focus, device->x, device->y,
&device->grab->x, &device->grab->y);
}
WL_EXPORT void
@ -387,6 +552,7 @@ destroy_surface(struct wl_resource *resource)
wl_list_remove(&surface->buffer_link);
pixman_region32_fini(&surface->transform.boundingbox);
pixman_region32_fini(&surface->damage);
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);
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;
GLfloat *v, inv_width, inv_height;
GLfloat sx, sy;
pixman_box32_t *rectangles;
unsigned int *p;
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);
p = wl_array_add(&ec->indices, n * 6 * sizeof *p);
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) {
surface_from_global_float(es, rectangles[i].x1,
rectangles[i].y1, &sx, &sy);
v[ 0] = rectangles[i].x1;
v[ 1] = rectangles[i].y1;
v[ 2] = (GLfloat) (rectangles[i].x1 - es->x) * inv_width;
v[ 3] = (GLfloat) (rectangles[i].y1 - es->y) * inv_height;
v[ 2] = sx * inv_width;
v[ 3] = sy * inv_height;
surface_from_global_float(es, rectangles[i].x1,
rectangles[i].y2, &sx, &sy);
v[ 4] = rectangles[i].x1;
v[ 5] = rectangles[i].y2;
v[ 6] = v[ 2];
v[ 7] = (GLfloat) (rectangles[i].y2 - es->y) * inv_height;
v[ 6] = sx * inv_width;
v[ 7] = sy * inv_height;
surface_from_global_float(es, rectangles[i].x2,
rectangles[i].y1, &sx, &sy);
v[ 8] = rectangles[i].x2;
v[ 9] = rectangles[i].y1;
v[10] = (GLfloat) (rectangles[i].x2 - es->x) * inv_width;
v[11] = v[ 3];
v[10] = sx * inv_width;
v[11] = sy * inv_height;
surface_from_global_float(es, rectangles[i].x2,
rectangles[i].y2, &sx, &sy);
v[12] = rectangles[i].x2;
v[13] = rectangles[i].y2;
v[14] = v[10];
v[15] = v[ 7];
v[14] = sx * inv_width;
v[15] = sy * inv_height;
p[0] = i * 4 + 0;
p[1] = i * 4 + 1;
@ -493,51 +668,6 @@ texture_region(struct weston_surface *es, pixman_region32_t *region)
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
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;
int n;
pixman_region32_init_rect(&repaint,
es->x, es->y, es->width, es->height);
pixman_region32_intersect(&repaint, &repaint, &output->region);
weston_surface_update_transform(es);
pixman_region32_init(&repaint);
pixman_region32_intersect(&repaint, &es->transform.boundingbox,
&output->region);
pixman_region32_intersect(&repaint, &repaint, &es->damage);
if (!pixman_region32_not_empty(&repaint))
return;
goto out;
switch (es->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;
}
if (es->transform == NULL) {
filter = GL_NEAREST;
n = texture_region(es, &repaint);
} else {
if (es->shader->texwidth_uniform != GL_NONE)
glUniform1f(es->shader->texwidth_uniform,
(GLfloat)es->geometry.width / es->pitch);
if (es->transform.enabled)
filter = GL_LINEAR;
n = texture_transformed_surface(es);
}
else
filter = GL_NEAREST;
n = texture_region(es, &repaint);
glBindTexture(GL_TEXTURE_2D, es->texture);
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]);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glDrawElements(GL_TRIANGLES, n * 6, GL_UNSIGNED_INT, ec->indices.data);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(0);
ec->vertices.size = 0;
ec->indices.size = 0;
out:
pixman_region32_fini(&repaint);
}
@ -716,12 +857,12 @@ weston_output_set_cursor(struct weston_output *output,
if (device->sprite == NULL)
return;
pixman_region32_init_rect(&cursor_region,
device->sprite->x, device->sprite->y,
device->sprite->width,
device->sprite->height);
weston_surface_update_transform(device->sprite);
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)) {
output->set_hardware_cursor(output, NULL);
@ -770,14 +911,15 @@ weston_output_repaint(struct weston_output *output, int msecs)
pixman_region32_init(&overlap);
wl_list_for_each(es, &ec->surface_list, link) {
weston_surface_update_transform(es);
pixman_region32_init(&surface_overlap);
pixman_region32_intersect_rect(&surface_overlap,
&overlap, es->x, es->y,
es->width, es->height);
pixman_region32_intersect(&surface_overlap, &overlap,
&es->transform.boundingbox);
es->overlapped = pixman_region32_not_empty(&surface_overlap);
pixman_region32_fini(&surface_overlap);
pixman_region32_union_rect(&overlap, &overlap, es->x, es->y,
es->width, es->height);
pixman_region32_union(&overlap, &overlap,
&es->transform.boundingbox);
}
weston_output_set_cursor(output, ec->input_device);
@ -903,12 +1045,14 @@ weston_surface_assign_output(struct weston_surface *es)
uint32_t max, area;
pixman_box32_t *e;
weston_surface_update_transform(es);
new_output = NULL;
max = 0;
pixman_region32_init(&region);
wl_list_for_each(output, &ec->output_list, link) {
pixman_region32_init_rect(&region,
es->x, es->y, es->width, es->height);
pixman_region32_intersect(&region, &region, &output->region);
pixman_region32_intersect(&region, &es->transform.boundingbox,
&output->region);
e = pixman_region32_extents(&region);
area = (e->x2 - e->x1) * (e->y2 - e->y1);
@ -918,6 +1062,7 @@ weston_surface_assign_output(struct weston_surface *es)
max = area;
}
}
pixman_region32_fini(&region);
es->output = new_output;
if (!wl_list_empty(&es->frame_callback_list)) {
@ -951,9 +1096,11 @@ surface_attach(struct wl_client *client,
if (es->visual == WESTON_NONE_VISUAL) {
shell->map(shell, es, buffer->width, buffer->height);
} else if (x != 0 || y != 0 ||
es->width != buffer->width ||
es->height != buffer->height) {
shell->configure(shell, es, es->x + x, es->y + y,
es->geometry.width != buffer->width ||
es->geometry.height != buffer->height) {
/* 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);
}
@ -1052,9 +1199,9 @@ weston_compositor_pick_surface(struct weston_compositor *compositor,
wl_list_for_each(surface, &compositor->surface_list, link) {
if (surface->surface.resource.client == NULL)
continue;
weston_surface_transform(surface, x, y, sx, sy);
if (0 <= *sx && *sx < surface->width &&
0 <= *sy && *sy < surface->height)
weston_surface_from_global(surface, x, y, sx, sy);
if (0 <= *sx && *sx < surface->geometry.width &&
0 <= *sy && *sy < surface->geometry.height)
return surface;
}
@ -1163,8 +1310,9 @@ notify_motion(struct wl_input_device *device, uint32_t time, int x, int y)
if (wd->sprite) {
weston_surface_damage_below(wd->sprite);
wd->sprite->x = device->x - wd->hotspot_x;
wd->sprite->y = device->y - wd->hotspot_y;
wd->sprite->geometry.x = device->x - wd->hotspot_x;
wd->sprite->geometry.y = device->y - wd->hotspot_y;
wd->sprite->geometry.dirty = 1;
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);
} else if (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)
@ -1454,7 +1602,7 @@ notify_touch(struct wl_input_device *device, uint32_t time, int touch_id,
if (!es)
break;
weston_surface_transform(es, x, y, &sx, &sy);
weston_surface_from_global(es, x, y, &sx, &sy);
if (wd->touch_focus_resource)
wl_resource_post_event(wd->touch_focus_resource,
touch_type, time,
@ -1515,10 +1663,11 @@ input_device_attach(struct wl_client *client,
device->hotspot_x = x;
device->hotspot_y = y;
device->sprite->width = buffer->width;
device->sprite->height = buffer->height;
device->sprite->x = device->input_device.x - device->hotspot_x;
device->sprite->y = device->input_device.y - device->hotspot_y;
device->sprite->geometry.width = buffer->width;
device->sprite->geometry.height = buffer->height;
device->sprite->geometry.x = device->input_device.x - device->hotspot_x;
device->sprite->geometry.y = device->input_device.y - device->hotspot_y;
device->sprite->geometry.dirty = 1;
weston_surface_damage(device->sprite);
}
@ -1624,8 +1773,12 @@ static const char texture_fragment_shader[] =
"varying vec2 v_texcoord;\n"
"uniform sampler2D tex;\n"
"uniform float alpha;\n"
"uniform float texwidth;\n"
"void main()\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 = alpha * gl_FragColor;\n"
"}\n";
@ -1687,6 +1840,8 @@ weston_shader_init(struct weston_shader *shader,
shader->proj_uniform = glGetUniformLocation(shader->program, "proj");
shader->tex_uniform = glGetUniformLocation(shader->program, "tex");
shader->alpha_uniform = glGetUniformLocation(shader->program, "alpha");
shader->texwidth_uniform = glGetUniformLocation(shader->program,
"texwidth");
return 0;
}

View File

@ -1,5 +1,6 @@
/*
* 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
@ -32,27 +33,11 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
struct weston_matrix {
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);
#include "matrix.h"
struct weston_transform {
struct weston_matrix matrix;
struct weston_matrix inverse;
struct wl_list link;
};
struct weston_surface;
@ -118,6 +103,7 @@ struct weston_shader {
GLuint tex_uniform;
GLuint alpha_uniform;
GLuint color_uniform;
GLuint texwidth_uniform;
};
struct weston_animation {
@ -162,7 +148,6 @@ struct weston_compositor {
EGLContext context;
EGLConfig config;
GLuint fbo;
GLuint proj_uniform, tex_uniform, alpha_uniform;
uint32_t current_alpha;
struct weston_shader texture_shader;
struct weston_shader solid_shader;
@ -230,17 +215,45 @@ struct weston_surface {
GLuint texture;
pixman_region32_t damage;
pixman_region32_t opaque;
int32_t x, y, width, height;
int32_t pitch;
struct wl_list link;
struct wl_list buffer_link;
struct weston_transform *transform;
struct weston_shader *shader;
GLfloat color[4];
uint32_t alpha;
uint32_t visual;
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.
* Used to determine, whether to send or queue frame events.
@ -257,6 +270,17 @@ struct weston_surface {
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
weston_device_repick(struct wl_input_device *device, uint32_t time);

250
src/matrix.c Normal file
View File

@ -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;
}

64
src/matrix.h Normal file
View File

@ -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 */

View File

@ -1,6 +1,6 @@
/*
* Copyright © 2010 Intel Corporation
* Copyright © 2011 Collabora, Ltd.
* Copyright © 2011-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
@ -29,6 +29,7 @@
#include <linux/input.h>
#include <assert.h>
#include <signal.h>
#include <math.h>
#include <wayland-server.h>
#include "compositor.h"
@ -93,6 +94,10 @@ struct shell_surface {
enum shell_surface_type type;
int32_t saved_x, saved_y;
struct {
struct weston_transform transform;
} rotation;
struct {
struct wl_grab grab;
uint32_t time;
@ -110,6 +115,15 @@ struct weston_move_grab {
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
shell_configuration(struct wl_shell *shell)
{
@ -152,7 +166,7 @@ move_grab_motion(struct wl_grab *grab,
weston_surface_configure(es,
device->x + move->dx,
device->y + move->dy,
es->width, es->height);
es->geometry.width, es->geometry.height);
}
static void
@ -184,8 +198,8 @@ weston_surface_move(struct weston_surface *es,
return -1;
move->grab.interface = &move_grab_interface;
move->dx = es->x - wd->input_device.grab_x;
move->dy = es->y - wd->input_device.grab_y;
move->dx = es->geometry.x - wd->input_device.grab_x;
move->dy = es->geometry.y - wd->input_device.grab_y;
move->surface = es;
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->edges = edges;
resize->dx = es->x - wd->input_device.grab_x;
resize->dy = es->y - wd->input_device.grab_y;
resize->width = es->width;
resize->height = es->height;
resize->dx = es->geometry.x - wd->input_device.grab_x;
resize->dy = es->geometry.y - wd->input_device.grab_y;
resize->width = es->geometry.width;
resize->height = es->geometry.height;
resize->shsurf = shsurf;
if (edges == 0 || edges > 15 ||
@ -328,8 +342,9 @@ reset_shell_surface_type(struct shell_surface *surface)
{
switch (surface->type) {
case SHELL_SURFACE_FULLSCREEN:
surface->surface->x = surface->saved_x;
surface->surface->y = surface->saved_y;
surface->surface->geometry.x = surface->saved_x;
surface->surface->geometry.y = surface->saved_y;
surface->surface->geometry.dirty = 1;
surface->surface->fullscreen_output = NULL;
break;
case SHELL_SURFACE_PANEL:
@ -385,8 +400,9 @@ shell_surface_set_transient(struct wl_client *client,
/* assign to parents output */
es->output = pes->output;
es->x = pes->x + x;
es->y = pes->y + y;
es->geometry.x = pes->geometry.x + x;
es->geometry.y = pes->geometry.y + y;
es->geometry.dirty = 1;
weston_surface_damage(es);
shsurf->type = SHELL_SURFACE_TRANSIENT;
@ -416,10 +432,11 @@ shell_surface_set_fullscreen(struct wl_client *client,
output = get_default_output(es->compositor);
es->output = output;
shsurf->saved_x = es->x;
shsurf->saved_y = es->y;
es->x = (output->current->width - es->width) / 2;
es->y = (output->current->height - es->height) / 2;
shsurf->saved_x = es->geometry.x;
shsurf->saved_y = es->geometry.y;
es->geometry.x = (output->current->width - es->geometry.width) / 2;
es->geometry.y = (output->current->height - es->geometry.height) / 2;
es->geometry.dirty = 1;
es->fullscreen_output = output;
weston_surface_damage(es);
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;
device = es->compositor->input_device;
es->x = shsurf->parent->surface->x + shsurf->popup.x;
es->y = shsurf->parent->surface->y + shsurf->popup.y;
es->geometry.x = shsurf->parent->surface->geometry.x + shsurf->popup.x;
es->geometry.y = shsurf->parent->surface->geometry.y + shsurf->popup.y;
es->geometry.dirty = 1;
shsurf->popup.grab.input_device = device;
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 */
wl_list_init(&shsurf->link);
/* empty when not in use */
wl_list_init(&shsurf->rotation.transform.link);
shsurf->type = SHELL_SURFACE_NONE;
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_insert(list, &surface->surface->link);
weston_surface_configure(surface->surface,
surface->surface->x,
surface->surface->y,
surface->surface->width,
surface->surface->height);
surface->surface->geometry.x,
surface->surface->geometry.y,
surface->surface->geometry.width,
surface->surface->geometry.height);
surface->surface->output = surface->output;
}
@ -716,8 +737,9 @@ desktop_shell_set_background(struct wl_client *client,
wl_list_insert(&shell->backgrounds, &shsurf->link);
surface->x = shsurf->output->x;
surface->y = shsurf->output->y;
surface->geometry.x = shsurf->output->x;
surface->geometry.y = shsurf->output->y;
surface->geometry.dirty = 1;
wl_resource_post_event(resource,
DESKTOP_SHELL_CONFIGURE,
@ -754,8 +776,9 @@ desktop_shell_set_panel(struct wl_client *client,
wl_list_insert(&shell->panels, &shsurf->link);
surface->x = shsurf->output->x;
surface->y = shsurf->output->y;
surface->geometry.x = shsurf->output->x;
surface->geometry.y = shsurf->output->y;
surface->geometry.dirty = 1;
wl_resource_post_event(resource,
DESKTOP_SHELL_CONFIGURE,
@ -813,8 +836,10 @@ resume_desktop(struct wl_shell *shell)
terminate_screensaver(shell);
wl_list_for_each(surface, &shell->hidden_surface_list, link)
weston_surface_configure(surface, surface->x, surface->y,
surface->width, surface->height);
weston_surface_configure(surface, surface->geometry.x,
surface->geometry.y,
surface->geometry.width,
surface->geometry.height);
if (wl_list_empty(&shell->backgrounds)) {
list = &shell->compositor->surface_list;
@ -915,19 +940,20 @@ resize_binding(struct wl_input_device *device, uint32_t time,
break;
}
x = device->grab_x - surface->x;
y = device->grab_y - surface->y;
/* FIXME: convert properly to surface coordinates */
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;
else if (x < 2 * surface->width / 3)
else if (x < 2 * surface->geometry.width / 3)
edges |= 0;
else
edges |= WL_SHELL_SURFACE_RESIZE_RIGHT;
if (y < surface->height / 3)
if (y < surface->geometry.height / 3)
edges |= WL_SHELL_SURFACE_RESIZE_TOP;
else if (y < 2 * surface->height / 3)
else if (y < 2 * surface->geometry.height / 3)
edges |= 0;
else
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);
}
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
activate(struct weston_shell *base, struct weston_surface *es,
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;
surface->x = output->x + (mode->width - surface->width) / 2;
surface->y = output->y + (mode->height - surface->height) / 2;
surface->geometry.x =
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
@ -1125,14 +1262,16 @@ map(struct weston_shell *base,
do_configure = 1;
}
surface->width = width;
surface->height = height;
surface->geometry.width = width;
surface->geometry.height = height;
surface->geometry.dirty = 1;
/* initial positioning, see also configure() */
switch (surface_type) {
case SHELL_SURFACE_TOPLEVEL:
surface->x = 10 + random() % 400;
surface->y = 10 + random() % 400;
surface->geometry.x = 10 + random() % 400;
surface->geometry.y = 10 + random() % 400;
surface->geometry.dirty = 1;
break;
case SHELL_SURFACE_SCREENSAVER:
case SHELL_SURFACE_FULLSCREEN:
@ -1189,8 +1328,9 @@ map(struct weston_shell *base,
switch (surface_type) {
case SHELL_SURFACE_TOPLEVEL:
surface->x = 10 + random() % 400;
surface->y = 10 + random() % 400;
surface->geometry.x = 10 + random() % 400;
surface->geometry.y = 10 + random() % 400;
surface->geometry.dirty = 1;
break;
case SHELL_SURFACE_POPUP:
shell_map_popup(shsurf, shsurf->popup.time);
@ -1199,10 +1339,12 @@ map(struct weston_shell *base,
break;
}
surface->width = width;
surface->height = height;
surface->geometry.width = width;
surface->geometry.height = height;
surface->geometry.dirty = 1;
if (do_configure) {
weston_surface_configure(surface, surface->x, surface->y,
weston_surface_configure(surface, surface->geometry.x,
surface->geometry.y,
width, height);
weston_compositor_repick(compositor);
}
@ -1238,8 +1380,9 @@ configure(struct weston_shell *base, struct weston_surface *surface,
if (shsurf)
surface_type = shsurf->type;
surface->width = width;
surface->height = height;
surface->geometry.width = width;
surface->geometry.height = height;
surface->geometry.dirty = 1;
switch (surface_type) {
case SHELL_SURFACE_SCREENSAVER:
@ -1474,6 +1617,9 @@ shell_init(struct weston_compositor *ec)
terminate_binding, ec);
weston_compositor_add_binding(ec, 0, BTN_LEFT, 0,
click_to_activate_binding, ec);
weston_compositor_add_binding(ec, 0, BTN_LEFT,
MODIFIER_SUPER | MODIFIER_ALT,
rotate_binding, NULL);
ec->shell = &shell->shell;

View File

@ -110,8 +110,9 @@ tablet_shell_map(struct weston_shell *base, struct weston_surface *surface,
struct tablet_shell *shell =
container_of(base, struct tablet_shell, shell);
surface->x = 0;
surface->y = 0;
surface->geometry.x = 0;
surface->geometry.y = 0;
surface->geometry.dirty = 1;
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);
weston_surface_configure(surface, surface->x, surface->y, width, height);
weston_surface_configure(surface, surface->geometry.x,
surface->geometry.y, width, height);
}
static void
@ -165,8 +167,9 @@ tablet_shell_set_lockscreen(struct wl_client *client,
struct tablet_shell *shell = resource->data;
struct weston_surface *es = surface_resource->data;
es->x = 0;
es->y = 0;
es->geometry.x = 0;
es->geometry.y = 0;
es->geometry.dirty = 1;
shell->lockscreen_surface = es;
shell->lockscreen_listener.func = handle_lockscreen_surface_destroy;
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
* fade/zoom in. */
shell->switcher_surface = es;
shell->switcher_surface->x = 0;
shell->switcher_surface->y = 0;
shell->switcher_surface->geometry.x = 0;
shell->switcher_surface->geometry.y = 0;
shell->switcher_surface->geometry.dirty = 1;
shell->switcher_listener.func = handle_switcher_surface_destroy;
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;
shell->home_surface = surface_resource->data;
shell->home_surface->x = 0;
shell->home_surface->y = 0;
shell->home_surface->geometry.x = 0;
shell->home_surface->geometry.y = 0;
shell->home_surface->geometry.dirty = 1;
}
static void

View File

@ -27,70 +27,6 @@
#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
weston_spring_init(struct weston_spring *spring,
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->listener.link);
zoom->surface->transform = NULL;
wl_list_remove(&zoom->transform.link);
zoom->surface->geometry.dirty = 1;
if (zoom->done)
zoom->done(zoom, zoom->data);
free(zoom);
@ -198,19 +135,18 @@ weston_zoom_frame(struct weston_animation *animation,
(zoom->stop - zoom->start) * zoom->spring.current;
weston_matrix_init(&zoom->transform.matrix);
weston_matrix_translate(&zoom->transform.matrix,
-(es->x + es->width / 2.0),
-(es->y + es->height / 2.0), 0);
-0.5f * es->geometry.width,
-0.5f * es->geometry.height, 0);
weston_matrix_scale(&zoom->transform.matrix, scale, scale, scale);
weston_matrix_translate(&zoom->transform.matrix,
es->x + es->width / 2.0,
es->y + es->height / 2.0, 0);
0.5f * es->geometry.width,
0.5f * es->geometry.height, 0);
es->alpha = zoom->spring.current * 255;
if (es->alpha > 255)
es->alpha = 255;
scale = 1.0 / zoom->spring.current;
weston_matrix_init(&zoom->transform.inverse);
weston_matrix_scale(&zoom->transform.inverse, scale, scale, scale);
zoom->surface->geometry.dirty = 1;
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->start = start;
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);
zoom->spring.friction = 700;
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,
&zoom->listener.link);
wl_list_insert(surface->compositor->animation_list.prev,
wl_list_insert(&surface->compositor->animation_list,
&zoom->animation.link);
return zoom;

2
tests/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
matrix-test

15
tests/Makefile.am Normal file
View File

@ -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

422
tests/matrix-test.c Normal file
View File

@ -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;
}