3 * Copyright (C) 2016-2020 William Morrow
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published
7 * by the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public
16 * License along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 #include "bccmodels.h"
23 #include "bcresources.h"
24 #include "condition.h"
30 static inline float clp(const int n, float v) {
31 v *= ((float)(n*(1-1./0x1000000)));
32 return v < 0 ? 0 : v >= n ? n-1 : v;
35 static inline float fclp(float v, const int n) {
36 v /= ((float)(n*(1-1./0x1000000)));
37 return v < 0 ? 0 : v > 1 ? 1 : v;
42 #define ZTYP(ty) typedef ty z_##ty __attribute__ ((__unused__))
47 #define xfer_flat_row_out(oty_t) \
48 for( unsigned i=y0; i<y1; ++i ) { \
49 oty_t *out = (oty_t *)(output_rows[i + out_y] + out_x * out_pixelsize); \
51 #define xfer_flat_row_in(ity_t) \
52 uint8_t *inp_row = input_rows[row_table[i]]; \
53 for( unsigned j=0; j<out_w; ++j ) { \
54 ity_t *inp = (ity_t *)(inp_row + column_table[j]); \
56 #define xfer_clear(s) \
57 for( unsigned j=0; j<out_w; ++j ) { \
62 #define xfer_yuv420p_row_out(oty_t) \
63 for( unsigned i=y0; i<y1; ++i ) { \
64 int out_rofs = i * total_out_w + out_x; \
65 oty_t *yop = (oty_t *)(out_yp + out_rofs); \
66 out_rofs = i / 2 * total_out_w / 2 + out_x / 2; \
67 oty_t *uop = (oty_t *)(out_up + out_rofs); \
68 oty_t *vop = (oty_t *)(out_vp + out_rofs); \
70 #define xfer_yuv420p_row_in(ity_t) \
71 int in_r = row_table[i]; \
72 int in_rofs = in_r * total_in_w; \
73 uint8_t *yip_row = in_yp + in_rofs; \
74 in_rofs = in_r / 2 * total_in_w / 2; \
75 uint8_t *uip_row = in_up + in_rofs; \
76 uint8_t *vip_row = in_vp + in_rofs; \
77 for( unsigned j=0; j<out_w; ++j ) { \
78 int in_ofs = column_table[j]; \
79 ity_t *yip = (ity_t *)(yip_row + in_ofs); \
81 ity_t *uip = (ity_t *)(uip_row + in_ofs); \
82 ity_t *vip = (ity_t *)(vip_row + in_ofs); \
85 #define xfer_yuv420pi_row_out(oty_t) \
86 for( unsigned i=y0; i<y1; ++i ) { \
87 int out_rofs = i * total_out_w + out_x; \
88 oty_t *yop = (oty_t *)(out_yp + out_rofs); \
89 int ot_k = ((i/4)<<1) + (i&1); \
90 out_rofs = ot_k * total_out_w / 2 + out_x / 2; \
91 oty_t *uop = (oty_t *)(out_up + out_rofs); \
92 oty_t *vop = (oty_t *)(out_vp + out_rofs); \
94 #define xfer_yuv420pi_row_in(ity_t) \
95 int in_r = row_table[i]; \
96 int in_rofs = in_r * total_in_w; \
97 uint8_t *yip_row = in_yp + in_rofs; \
98 int in_k = ((in_r/4)<<1) + (in_r&1); \
99 in_rofs = in_k * total_in_w / 2; \
100 uint8_t *uip_row = in_up + in_rofs; \
101 uint8_t *vip_row = in_vp + in_rofs; \
102 for( unsigned j=0; j<out_w; ++j ) { \
103 int in_ofs = column_table[j]; \
104 ity_t *yip = (ity_t *)(yip_row + in_ofs); \
106 ity_t *uip = (ity_t *)(uip_row + in_ofs); \
107 ity_t *vip = (ity_t *)(vip_row + in_ofs); \
110 #define xfer_yuv422p_row_out(oty_t) \
111 for( unsigned i=y0; i<y1; ++i ) { \
112 int out_rofs = i * total_out_w + out_x; \
113 oty_t *yop = (oty_t *)(out_yp + out_rofs); \
114 out_rofs = i * total_out_w / 2 + out_x / 2; \
115 oty_t *uop = (oty_t *)(out_up + out_rofs); \
116 oty_t *vop = (oty_t *)(out_vp + out_rofs); \
118 #define xfer_yuv422p_row_in(ity_t) \
119 int in_rofs = row_table[i] * total_in_w; \
120 uint8_t *yip_row = in_yp + in_rofs; \
122 uint8_t *uip_row = in_up + in_rofs; \
123 uint8_t *vip_row = in_vp + in_rofs; \
124 for( unsigned j=0; j<out_w; ++j ) { \
125 int in_ofs = column_table[j]; \
126 ity_t *yip = (ity_t *)(yip_row + in_ofs); \
128 ity_t *uip = (ity_t *)(uip_row + in_ofs); \
129 ity_t *vip = (ity_t *)(vip_row + in_ofs); \
132 #define xfer_yuv444p_row_out(oty_t) \
133 for( unsigned i=y0; i<y1; ++i ) { \
134 int out_rofs = i * total_out_w + out_x; \
135 oty_t *yop = (oty_t *)((oty_t *)(out_yp + out_rofs)); \
136 oty_t *uop = (oty_t *)(out_up + out_rofs); \
137 oty_t *vop = (oty_t *)(out_vp + out_rofs); \
139 #define xfer_yuv444p_row_in(ity_t) \
140 int in_rofs = row_table[i] * total_in_w; \
141 uint8_t *yip_row = in_yp + in_rofs; \
142 uint8_t *uip_row = in_up + in_rofs; \
143 uint8_t *vip_row = in_vp + in_rofs; \
144 for( unsigned j=0; j<out_w; ++j ) { \
145 int in_ofs = column_table[j]; \
146 ity_t *yip = (ity_t *)(yip_row + in_ofs); \
147 ity_t *uip = (ity_t *)(uip_row + in_ofs); \
148 ity_t *vip = (ity_t *)(vip_row + in_ofs); \
151 #define xfer_yuv411p_row_out(oty_t) \
152 for( unsigned i=y0; i<y1; ++i ) { \
153 int out_rofs = i * total_out_w + out_x; \
154 oty_t *yop = (oty_t *)(out_yp + out_rofs); \
155 out_rofs = i * total_out_w / 4 + out_x / 4; \
156 oty_t *uop = (oty_t *)(out_up + out_rofs); \
157 oty_t *vop = (oty_t *)(out_vp + out_rofs); \
159 #define xfer_yuv411p_row_in(ity_t) \
160 int in_rofs = row_table[i] * total_in_w; \
161 uint8_t *yip_row = in_yp + in_rofs; \
163 uint8_t *uip_row = in_up + in_rofs; \
164 uint8_t *vip_row = in_vp + in_rofs; \
165 for( unsigned j=0; j<out_w; ++j ) { \
166 int in_ofs = column_table[j]; \
167 ity_t *yip = (ity_t *)(yip_row + in_ofs); \
169 ity_t *uip = (ity_t *)(uip_row + in_ofs); \
170 ity_t *vip = (ity_t *)(vip_row + in_ofs); \
173 #define xfer_yuv410p_row_out(oty_t) \
174 for( unsigned i=y0; i<y1; ++i ) { \
175 int out_rofs = i * total_out_w + out_x; \
176 oty_t *yop = (oty_t *)(out_yp + out_rofs); \
177 out_rofs = i / 4 * total_out_w / 4 + out_x / 4; \
178 oty_t *uop = (oty_t *)(out_up + out_rofs); \
179 oty_t *vop = (oty_t *)(out_vp + out_rofs); \
181 #define xfer_yuv410p_row_in(ity_t) \
182 int in_rofs = row_table[i] * total_in_w; \
183 uint8_t *yip_row = in_yp + in_rofs; \
184 in_rofs = row_table[i] / 4 * total_in_w / 4; \
185 uint8_t *uip_row = in_up + in_rofs; \
186 uint8_t *vip_row = in_vp + in_rofs; \
187 for( unsigned j=0; j<out_w; ++j ) { \
188 int in_ofs = column_table[j]; \
189 ity_t *yip = (ity_t *)(yip_row + in_ofs); \
191 ity_t *uip = (ity_t *)(uip_row + in_ofs); \
192 ity_t *vip = (ity_t *)(vip_row + in_ofs); \
195 #define xfer_rgbp_row_out(oty_t) \
196 for( unsigned i=y0; i<y1; ++i ) { \
197 int out_rofs = i * total_out_w + out_x; \
198 oty_t *rop = (oty_t *)(out_yp + out_rofs); \
199 oty_t *gop = (oty_t *)(out_up + out_rofs); \
200 oty_t *bop = (oty_t *)(out_vp + out_rofs); \
202 #define xfer_rgbap_row_out(oty_t) \
203 xfer_rgbp_row_out(oty_t) \
204 oty_t *aop = (oty_t *)(out_ap + out_rofs); \
207 #define xfer_row_in_rgbp(ity_t) \
208 int in_rofs = row_table[i] * total_in_w; \
209 uint8_t *rip_row = in_yp + in_rofs; \
210 uint8_t *gip_row = in_up + in_rofs; \
211 uint8_t *bip_row = in_vp + in_rofs; \
213 #define xfer_row_in_rgbap(oty_t) \
214 xfer_row_in_rgbp(ity_t) \
215 uint8_t *aip_row = in_ap + in_rofs; \
218 #define xfer_col_in_rgbp(ity_t) \
219 for( unsigned j=0; j<out_w; ++j ) { \
220 int in_ofs = column_table[j]; \
221 ity_t *rip = (ity_t *)(rip_row + in_ofs); \
222 ity_t *gip = (ity_t *)(gip_row + in_ofs); \
223 ity_t *bip = (ity_t *)(bip_row + in_ofs); \
225 #define xfer_col_in_rgbap(ity_t) \
226 xfer_col_in_rgbp(ity_t) \
227 ity_t *aip = (ity_t *)(aip_row + in_ofs); \
230 #define xfer_rgbp_row_in(ity_t) \
231 xfer_row_in_rgbp(ity_t) \
232 xfer_col_in_rgbp(ity_t) \
234 #define xfer_rgbap_row_in(ity_t) \
235 xfer_row_in_rgbap(ity_t) \
236 xfer_col_in_rgbap(ity_t) \
240 BC_Xfer(const BC_Xfer&) {}
242 BC_Xfer(uint8_t **output_rows, uint8_t **input_rows,
243 uint8_t *out_yp, uint8_t *out_up, uint8_t *out_vp,
244 uint8_t *in_yp, uint8_t *in_up, uint8_t *in_vp,
245 int in_x, int in_y, int in_w, int in_h, int out_x, int out_y, int out_w, int out_h,
246 int in_colormodel, int out_colormodel, int bg_color, int bg_alpha,
247 int in_rowspan, int out_rowspan);
248 BC_Xfer(uint8_t **output_ptrs, int out_colormodel,
249 int out_x, int out_y, int out_w, int out_h, int out_rowspan,
250 uint8_t **input_ptrs, int in_colormodel,
251 int in_x, int in_y, int in_w, int in_h, int in_rowspan,
252 int bg_color, int bg_alpha);
255 uint8_t **output_rows, **input_rows;
256 uint8_t *out_yp, *out_up, *out_vp, *out_ap;
257 uint8_t *in_yp, *in_up, *in_vp, *in_ap;
258 int in_x, in_y; unsigned in_w, in_h;
259 int out_x, out_y; unsigned out_w, out_h;
260 int in_colormodel, out_colormodel;
261 uint32_t total_in_w, total_out_w;
263 int out_pixelsize, in_pixelsize;
264 int *row_table, *column_table;
265 uint32_t bg_r, bg_g, bg_b, bg_a;
266 float bg_fr, bg_fg, bg_fb, bg_fa;
269 int xfer_slices(int slices);
270 typedef void (BC_Xfer::*xfer_fn)(unsigned y0, unsigned y1);
273 class Slicer : public ListItem<Slicer>, public Thread {
275 Condition *init, *complete;
278 void slice(BC_Xfer *xp, unsigned y0, unsigned y1);
284 class SlicerList : public List<Slicer>, public Mutex {
287 Slicer *get_slicer(BC_Xfer *xp);
292 static SlicerList slicers;
295 uint8_t **output_rows, int out_colormodel, int out_x, int out_y, int out_w, int out_h,
296 uint8_t *out_yp, uint8_t *out_up, uint8_t *out_vp, uint8_t *out_ap, int out_rowspan,
297 uint8_t **input_rows, int in_colormodel, int in_x, int in_y, int in_w, int in_h,
298 uint8_t *in_yp, uint8_t *in_up, uint8_t *in_vp, uint8_t *in_ap, int in_rowspan,
299 int bg_color, int bg_alpha);
301 // generated code concatentated here