git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

scenefx/util/matrix.c (3.9K)

  1 #include <assert.h>
  2 #include <string.h>
  3 #include <wayland-server-protocol.h>
  4 #include <wlr/util/box.h>
  5 #include "util/matrix.h"
  6 
  7 void wlr_matrix_identity(float mat[static 9]) {
  8 	static const float identity[9] = {
  9 		1.0f, 0.0f, 0.0f,
 10 		0.0f, 1.0f, 0.0f,
 11 		0.0f, 0.0f, 1.0f,
 12 	};
 13 	memcpy(mat, identity, sizeof(identity));
 14 }
 15 
 16 void wlr_matrix_multiply(float mat[static 9], const float a[static 9],
 17 		const float b[static 9]) {
 18 	float product[9];
 19 
 20 	product[0] = a[0]*b[0] + a[1]*b[3] + a[2]*b[6];
 21 	product[1] = a[0]*b[1] + a[1]*b[4] + a[2]*b[7];
 22 	product[2] = a[0]*b[2] + a[1]*b[5] + a[2]*b[8];
 23 
 24 	product[3] = a[3]*b[0] + a[4]*b[3] + a[5]*b[6];
 25 	product[4] = a[3]*b[1] + a[4]*b[4] + a[5]*b[7];
 26 	product[5] = a[3]*b[2] + a[4]*b[5] + a[5]*b[8];
 27 
 28 	product[6] = a[6]*b[0] + a[7]*b[3] + a[8]*b[6];
 29 	product[7] = a[6]*b[1] + a[7]*b[4] + a[8]*b[7];
 30 	product[8] = a[6]*b[2] + a[7]*b[5] + a[8]*b[8];
 31 
 32 	memcpy(mat, product, sizeof(product));
 33 }
 34 
 35 void wlr_matrix_translate(float mat[static 9], float x, float y) {
 36 	float translate[9] = {
 37 		1.0f, 0.0f, x,
 38 		0.0f, 1.0f, y,
 39 		0.0f, 0.0f, 1.0f,
 40 	};
 41 	wlr_matrix_multiply(mat, mat, translate);
 42 }
 43 
 44 void wlr_matrix_scale(float mat[static 9], float x, float y) {
 45 	float scale[9] = {
 46 		x,    0.0f, 0.0f,
 47 		0.0f, y,    0.0f,
 48 		0.0f, 0.0f, 1.0f,
 49 	};
 50 	wlr_matrix_multiply(mat, mat, scale);
 51 }
 52 
 53 static const float transforms[][9] = {
 54 	[WL_OUTPUT_TRANSFORM_NORMAL] = {
 55 		1.0f, 0.0f, 0.0f,
 56 		0.0f, 1.0f, 0.0f,
 57 		0.0f, 0.0f, 1.0f,
 58 	},
 59 	[WL_OUTPUT_TRANSFORM_90] = {
 60 		0.0f, 1.0f, 0.0f,
 61 		-1.0f, 0.0f, 0.0f,
 62 		0.0f, 0.0f, 1.0f,
 63 	},
 64 	[WL_OUTPUT_TRANSFORM_180] = {
 65 		-1.0f, 0.0f, 0.0f,
 66 		0.0f, -1.0f, 0.0f,
 67 		0.0f, 0.0f, 1.0f,
 68 	},
 69 	[WL_OUTPUT_TRANSFORM_270] = {
 70 		0.0f, -1.0f, 0.0f,
 71 		1.0f, 0.0f, 0.0f,
 72 		0.0f, 0.0f, 1.0f,
 73 	},
 74 	[WL_OUTPUT_TRANSFORM_FLIPPED] = {
 75 		-1.0f, 0.0f, 0.0f,
 76 		0.0f, 1.0f, 0.0f,
 77 		0.0f, 0.0f, 1.0f,
 78 	},
 79 	[WL_OUTPUT_TRANSFORM_FLIPPED_90] = {
 80 		0.0f, 1.0f, 0.0f,
 81 		1.0f, 0.0f, 0.0f,
 82 		0.0f, 0.0f, 1.0f,
 83 	},
 84 	[WL_OUTPUT_TRANSFORM_FLIPPED_180] = {
 85 		1.0f, 0.0f, 0.0f,
 86 		0.0f, -1.0f, 0.0f,
 87 		0.0f, 0.0f, 1.0f,
 88 	},
 89 	[WL_OUTPUT_TRANSFORM_FLIPPED_270] = {
 90 		0.0f, -1.0f, 0.0f,
 91 		-1.0f, 0.0f, 0.0f,
 92 		0.0f, 0.0f, 1.0f,
 93 	},
 94 };
 95 
 96 void wlr_matrix_transform(float mat[static 9],
 97 		enum wl_output_transform transform) {
 98 	wlr_matrix_multiply(mat, mat, transforms[transform]);
 99 }
100 
101 void matrix_projection(float mat[static 9], int width, int height,
102 		enum wl_output_transform transform) {
103 	memset(mat, 0, sizeof(*mat) * 9);
104 
105 	const float *t = transforms[transform];
106 	float x = 2.0f / width;
107 	float y = 2.0f / height;
108 
109 	// Rotation + reflection
110 	mat[0] = x * t[0];
111 	mat[1] = x * t[1];
112 	mat[3] = y * -t[3];
113 	mat[4] = y * -t[4];
114 
115 	// Translation
116 	mat[2] = -copysign(1.0f, mat[0] + mat[1]);
117 	mat[5] = -copysign(1.0f, mat[3] + mat[4]);
118 
119 	// Identity
120 	mat[8] = 1.0f;
121 }
122 
123 void wlr_matrix_project_box(float mat[static 9], const struct wlr_box *box,
124 		enum wl_output_transform transform, const float projection[static 9]) {
125 	int x = box->x;
126 	int y = box->y;
127 	int width = box->width;
128 	int height = box->height;
129 
130 	wlr_matrix_identity(mat);
131 	wlr_matrix_translate(mat, x, y);
132 
133 	wlr_matrix_scale(mat, width, height);
134 
135 	if (transform != WL_OUTPUT_TRANSFORM_NORMAL) {
136 		wlr_matrix_translate(mat, 0.5, 0.5);
137 		wlr_matrix_transform(mat, transform);
138 		wlr_matrix_translate(mat, -0.5, -0.5);
139 	}
140 
141 	wlr_matrix_multiply(mat, projection, mat);
142 }
143 
144 void matrix_invert(float out[static 9], float m[static 9]) {
145 	float a = m[0], b = m[1], c = m[2], d = m[3], e = m[4], f = m[5], g = m[6], h = m[7], i = m[8];
146 
147 	// See: https://en.wikipedia.org/wiki/Determinant
148 	float det = a*e*i + b*f*g + c*d*h - c*e*g - b*d*i - a*f*h;
149 	assert(det != 0);
150 	float inv_det = 1 / det;
151 
152 	// See: https://en.wikipedia.org/wiki/Invertible_matrix#Inversion_of_3_%C3%97_3_matrices
153 	float result[] = {
154 		inv_det * (e*i - f*h),
155 		inv_det * -(b*i - c*h),
156 		inv_det * (b*f - c*e),
157 		inv_det * -(d*i - f*g),
158 		inv_det * (a*i - c*g),
159 		inv_det * -(a*f - c*d),
160 		inv_det * (d*h - e*g),
161 		inv_det * -(a*h - b*g),
162 		inv_det * (a*e - b*d),
163 	};
164 	memcpy(out, result, sizeof(result));
165 }