1 /*
2  * This file is part of libplacebo.
3  *
4  * libplacebo is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * libplacebo is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with libplacebo.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef LIBPLACEBO_COMMON_H_
19 #define LIBPLACEBO_COMMON_H_
20 
21 // C++ compatibility
22 #ifdef __cplusplus
23 # define PL_STRUCT(name) struct name##_t
24 # define PL_API_BEGIN extern "C" {
25 # define PL_API_END }
26 #else
27 # define PL_STRUCT(name) struct name
28 # define PL_API_BEGIN
29 # define PL_API_END
30 #endif
31 
32 #include <libplacebo/log.h>
33 #include <stdbool.h>
34 
35 PL_API_BEGIN
36 
37 // Some common utility types. These are overloaded to support 2D, 3D and
38 // integer/float variants.
39 struct pl_rect2d {
40     int x0, y0;
41     int x1, y1;
42 };
43 
44 struct pl_rect3d {
45     int x0, y0, z0;
46     int x1, y1, z1;
47 };
48 
49 struct pl_rect2df {
50     float x0, y0;
51     float x1, y1;
52 };
53 
54 struct pl_rect3df {
55     float x0, y0, z0;
56     float x1, y1, z1;
57 };
58 
59 // These macros will work for any of the above pl_rect variants (with enough
60 // dimensions). Careful: double-evaluation hazard
61 #define pl_rect_w(r) ((r).x1 - (r).x0)
62 #define pl_rect_h(r) ((r).y1 - (r).y0)
63 #define pl_rect_d(r) ((r).z1 - (r).z0)
64 
65 #define pl_rect2d_eq(a, b) \
66     ((a).x0 == (b).x0 && (a).x1 == (b).x1 && \
67      (a).y0 == (b).y0 && (a).y1 == (b).y1)
68 
69 #define pl_rect3d_eq(a, b) \
70     ((a).x0 == (b).x0 && (a).x1 == (b).x1 && \
71      (a).y0 == (b).y0 && (a).y1 == (b).y1 && \
72      (a).z0 == (b).z0 && (a).z1 == (b).z1)
73 
74 // "Normalize" a rectangle: This ensures d1 >= d0 for all dimensions.
75 void pl_rect2d_normalize(struct pl_rect2d *rc);
76 void pl_rect3d_normalize(struct pl_rect3d *rc);
77 
78 void pl_rect2df_normalize(struct pl_rect2df *rc);
79 void pl_rect3df_normalize(struct pl_rect3df *rc);
80 
81 // Return the rounded form of a rect.
82 struct pl_rect2d pl_rect2df_round(const struct pl_rect2df *rc);
83 struct pl_rect3d pl_rect3df_round(const struct pl_rect3df *rc);
84 
85 // Represents a row-major matrix, i.e. the following matrix
86 //     [ a11 a12 a13 ]
87 //     [ a21 a22 a23 ]
88 //     [ a31 a32 a33 ]
89 // is represented in C like this:
90 //   { { a11, a12, a13 },
91 //     { a21, a22, a23 },
92 //     { a31, a32, a33 } };
93 struct pl_matrix3x3 {
94     float m[3][3];
95 };
96 
97 extern const struct pl_matrix3x3 pl_matrix3x3_identity;
98 
99 // Applies a matrix to a float vector in-place.
100 void pl_matrix3x3_apply(const struct pl_matrix3x3 *mat, float vec[3]);
101 
102 // Applies a matrix to a pl_rect3df
103 void pl_matrix3x3_apply_rc(const struct pl_matrix3x3 *mat, struct pl_rect3df *rc);
104 
105 // Scales a color matrix by a linear factor.
106 void pl_matrix3x3_scale(struct pl_matrix3x3 *mat, float scale);
107 
108 // Inverts a matrix. Only use where precision is not that important.
109 void pl_matrix3x3_invert(struct pl_matrix3x3 *mat);
110 
111 // Composes/multiplies two matrices. Multiples B into A, i.e.
112 // A := A * B
113 void pl_matrix3x3_mul(struct pl_matrix3x3 *a, const struct pl_matrix3x3 *b);
114 
115 // Flipped version of `pl_matrix3x3_mul`.
116 // B := A * B
117 void pl_matrix3x3_rmul(const struct pl_matrix3x3 *a, struct pl_matrix3x3 *b);
118 
119 // Represents an affine transformation, which is basically a 3x3 matrix
120 // together with a column vector to add onto the output.
121 struct pl_transform3x3 {
122     struct pl_matrix3x3 mat;
123     float c[3];
124 };
125 
126 extern const struct pl_transform3x3 pl_transform3x3_identity;
127 
128 // Applies a transform to a float vector in-place.
129 void pl_transform3x3_apply(const struct pl_transform3x3 *t, float vec[3]);
130 
131 // Applies a transform to a pl_rect3df
132 void pl_transform3x3_apply_rc(const struct pl_transform3x3 *t, struct pl_rect3df *rc);
133 
134 // Scales the output of a transform by a linear factor. Since an affine
135 // transformation is non-linear, this does not commute. If you want to scale
136 // the *input* of a transform, use pl_matrix3x3_scale on `t.mat`.
137 void pl_transform3x3_scale(struct pl_transform3x3 *t, float scale);
138 
139 // Inverts a transform. Only use where precision is not that important.
140 void pl_transform3x3_invert(struct pl_transform3x3 *t);
141 
142 // 2D analog of the above structs. Since these are featured less prominently,
143 // we omit some of the other helper functions.
144 struct pl_matrix2x2 {
145     float m[2][2];
146 };
147 
148 extern const struct pl_matrix2x2 pl_matrix2x2_identity;
149 
150 void pl_matrix2x2_apply(const struct pl_matrix2x2 *mat, float vec[2]);
151 void pl_matrix2x2_apply_rc(const struct pl_matrix2x2 *mat, struct pl_rect2df *rc);
152 
153 struct pl_transform2x2 {
154     struct pl_matrix2x2 mat;
155     float c[2];
156 };
157 
158 extern const struct pl_transform2x2 pl_transform2x2_identity;
159 
160 void pl_transform2x2_apply(const struct pl_transform2x2 *t, float vec[2]);
161 void pl_transform2x2_apply_rc(const struct pl_transform2x2 *t, struct pl_rect2df *rc);
162 
163 // Helper functions for dealing with aspect ratios and stretched/scaled rects.
164 
165 // Return the (absolute) aspect ratio (width/height) of a given pl_rect2df.
166 // This will always be a positive number, even if `rc` is flipped.
167 float pl_rect2df_aspect(const struct pl_rect2df *rc);
168 
169 // Set the aspect of a `rc` to a given aspect ratio with an extra 'panscan'
170 // factor choosing the balance between shrinking and growing the `rc` to meet
171 // this aspect ratio.
172 //
173 // Notes:
174 // - If `panscan` is 0.0, this function will only ever shrink the `rc`.
175 // - If `panscan` is 1.0, this function will only ever grow the `rc`.
176 // - If `panscan` is 0.5, this function is area-preserving.
177 void pl_rect2df_aspect_set(struct pl_rect2df *rc, float aspect, float panscan);
178 
179 // Set one rect's aspect to that of another
180 #define pl_rect2df_aspect_copy(rc, src, panscan) \
181     pl_rect2df_aspect_set((rc), pl_rect2df_aspect(src), (panscan))
182 
183 // 'Fit' one rect inside another. `rc` will be set to the same size and aspect
184 // ratio as `src`, but with the size limited to fit inside the original `rc`.
185 // Like `pl_rect2df_aspect_set`, `panscan` controls the pan&scan factor.
186 void pl_rect2df_aspect_fit(struct pl_rect2df *rc, const struct pl_rect2df *src,
187                            float panscan);
188 
189 // Scale rect in each direction while keeping it centered.
190 void pl_rect2df_stretch(struct pl_rect2df *rc, float stretch_x, float stretch_y);
191 
192 // Offset rect by an arbitrary offset factor. If the corresponding dimension
193 // of a rect is flipped, so too is the applied offset.
194 void pl_rect2df_offset(struct pl_rect2df *rc, float offset_x, float offset_y);
195 
196 // Scale a rect uniformly in both dimensions.
197 #define pl_rect2df_zoom(rc, zoom) pl_rect2df_stretch((rc), (zoom), (zoom))
198 
199 PL_API_END
200 
201 #endif // LIBPLACEBO_COMMON_H_
202