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