3 uint8_t **output_rows, int out_colormodel, int out_x, int out_y, int out_w, int out_h,
4 uint8_t *out_yp, uint8_t *out_up, uint8_t *out_vp, uint8_t *out_ap, int out_rowspan,
5 uint8_t **input_rows, int in_colormodel, int in_x, int in_y, int in_w, int in_h,
6 uint8_t *in_yp, uint8_t *in_up, uint8_t *in_vp, uint8_t *in_ap, int in_rowspan,
7 int bg_color, int bg_alpha)
10 this->bg_a = bg_alpha; // only used with init_color
11 this->bg_r = (bg_color>>16) & 0xff;
12 this->bg_g = (bg_color>>8) & 0xff;
13 this->bg_b = (bg_color>>0) & 0xff;
15 else { // bg_color < 0, no src blending
16 switch( in_colormodel ) {
17 case BC_RGBA8888: in_colormodel = BC_RGBX8888; break;
18 case BC_RGBA16161616: in_colormodel = BC_RGBX16161616; break;
19 case BC_YUVA8888: in_colormodel = BC_YUVX8888; break;
20 case BC_YUVA16161616: in_colormodel = BC_YUVX16161616; break;
21 case BC_RGBA_FLOAT: in_colormodel = BC_RGBX_FLOAT; break;
23 this->bg_r = this->bg_g = this->bg_b = this->bg_a = 0;
25 int pmx = BC_CModels::calculate_max(out_colormodel);
26 switch( in_colormodel ) {
28 if( BC_CModels::is_yuv(out_colormodel) ) {
29 int ry = this->bg_r, gu = this->bg_g, bv = this->bg_b;
30 YUV::yuv.rgb_to_yuv_8(ry, gu, bv);
31 this->bg_r = ry, this->bg_g = gu, this->bg_b = bv;
42 // prevent bounds errors on poorly dimensioned macro pixel formats
44 case BC_YUV422: in_w &= ~1; break; // 2x1
46 case BC_YUV420PI: in_w &= ~1; in_h &= ~1; break; // 2x2
47 case BC_YUV422P: in_w &= ~1; break; // 2x1
48 case BC_YUV410P: in_w &= ~3; in_h &= ~3; break; // 4x4
49 case BC_YUV411P: in_w &= ~3; break; // 4x1
51 switch( out_colormodel ) {
53 case BC_YUV422: out_w &= ~1; break;
55 case BC_YUV420PI: out_w &= ~1; out_h &= ~1; break;
56 case BC_YUV422P: out_w &= ~1; break;
57 case BC_YUV410P: out_w &= ~3; out_h &= ~3; break;
58 case BC_YUV411P: out_w &= ~3; break;
60 this->output_rows = output_rows;
61 this->input_rows = input_rows;
62 this->out_yp = out_yp;
63 this->out_up = out_up;
64 this->out_vp = out_vp;
65 this->out_ap = out_ap;
78 this->in_colormodel = in_colormodel;
79 switch( in_colormodel ) {
81 in_rowspan = in_w * sizeof(uint8_t);
85 if( !BC_CModels::has_alpha(out_colormodel) )
86 this->in_colormodel = BC_RGB_FLOATP;
87 in_rowspan = in_w * sizeof(float);
90 this->total_in_w = in_rowspan;
91 this->out_colormodel = out_colormodel;
92 switch( out_colormodel ) {
94 out_rowspan = out_w * sizeof(uint8_t);
98 out_rowspan = out_w * sizeof(float);
101 this->total_out_w = out_rowspan;
102 this->in_pixelsize = BC_CModels::calculate_pixelsize(in_colormodel);
103 this->out_pixelsize = BC_CModels::calculate_pixelsize(out_colormodel);
105 this->scale = (out_w != in_w) || (in_x != 0);
106 /* + 1 so we don't overflow when calculating in advance */
107 column_table = new int[out_w+1];
108 double hscale = (double)in_w/out_w;
109 for( int i=0; i<out_w; ++i ) {
110 column_table[i] = ((int)(hscale * i) + in_x) * in_pixelsize;
111 if( in_colormodel == BC_YUV422 || in_colormodel == BC_UVY422 )
112 column_table[i] &= ~3;
114 double vscale = (double)in_h/out_h;
115 row_table = new int[out_h];
116 for( int i=0; i<out_h; ++i )
117 row_table[i] = (int)(vscale * i) + in_y;
124 this->bg_fa = (float)this->bg_a / pmx;
125 this->bg_fr = (float)this->bg_r / pmx;
126 this->bg_fg = (float)this->bg_g / pmx;
127 this->bg_fb = (float)this->bg_b / pmx;
130 BC_Xfer::BC_Xfer(uint8_t **output_rows, uint8_t **input_rows,
131 uint8_t *out_yp, uint8_t *out_up, uint8_t *out_vp,
132 uint8_t *in_yp, uint8_t *in_up, uint8_t *in_vp,
133 int in_x, int in_y, int in_w, int in_h, int out_x, int out_y, int out_w, int out_h,
134 int in_colormodel, int out_colormodel, int bg_color, int bg_alpha,
135 int in_rowspan, int out_rowspan)
137 init(output_rows, out_colormodel, out_x, out_y, out_w, out_h,
138 out_yp, out_up, out_vp, 0, out_rowspan,
139 input_rows, in_colormodel, in_x, in_y, in_w, in_h,
140 in_yp, in_up, in_vp, 0, in_rowspan, bg_color, bg_alpha);
144 uint8_t **output_ptrs, int out_colormodel,
145 int out_x, int out_y, int out_w, int out_h, int out_rowspan,
146 uint8_t **input_ptrs, int in_colormodel,
147 int in_x, int in_y, int in_w, int in_h, int in_rowspan,
148 int bg_color, int bg_alpha)
150 uint8_t *out_yp = 0, *out_up = 0, *out_vp = 0, *out_ap = 0;
151 uint8_t *in_yp = 0, *in_up = 0, *in_vp = 0, *in_ap = 0;
152 if( BC_CModels::is_planar(in_colormodel) ) {
153 in_yp = input_ptrs[0]; in_up = input_ptrs[1]; in_vp = input_ptrs[2];
154 if( BC_CModels::has_alpha(in_colormodel) ) in_ap = input_ptrs[3];
156 if( BC_CModels::is_planar(out_colormodel) ) {
157 out_yp = output_ptrs[0]; out_up = output_ptrs[1]; out_vp = output_ptrs[2];
158 if( BC_CModels::has_alpha(out_colormodel) ) out_ap = output_ptrs[3];
160 init(output_ptrs, out_colormodel, out_x, out_y, out_w, out_h,
161 out_yp, out_up, out_vp, out_ap, out_rowspan,
162 input_ptrs, in_colormodel, in_x, in_y, in_w, in_h,
163 in_yp, in_up, in_vp, in_ap, in_rowspan, bg_color, bg_alpha);
168 delete [] column_table;
172 void BC_CModels::transfer(unsigned char **output_rows, unsigned char **input_rows,
173 unsigned char *out_yp, unsigned char *out_up, unsigned char *out_vp,
174 unsigned char *in_yp, unsigned char *in_up, unsigned char *in_vp,
175 int in_x, int in_y, int in_w, int in_h, int out_x, int out_y, int out_w, int out_h,
176 int in_colormodel, int out_colormodel, int bg_color,
177 int in_rowspan, int out_rowspan)
180 if( in_w > 0 && in_h > 0 && out_w > 0 && out_h > 0 ) {
181 BC_Xfer xfer(output_rows, input_rows,
182 out_yp, out_up, out_vp, in_yp, in_up, in_vp,
183 in_x, in_y, in_w, in_h, out_x, out_y, out_w, out_h,
184 in_colormodel, out_colormodel, bg_color,0xff, in_rowspan, out_rowspan);
188 printf("BC_CModels::transfer failed:%d %d(%dx%d) to %d(%dx%d)\n", __LINE__,
189 in_colormodel, in_w, in_h, out_colormodel, out_w, out_h);
192 void BC_CModels::transfer(
193 uint8_t **output_ptrs, int out_colormodel,
194 int out_x, int out_y, int out_w, int out_h, int out_rowspan,
195 uint8_t **input_ptrs, int in_colormodel,
196 int in_x, int in_y, int in_w, int in_h, int in_rowspan,
200 if( in_w > 0 && in_h > 0 && out_w > 0 && out_h > 0 ) {
202 output_ptrs, out_colormodel, out_x, out_y, out_w, out_h, out_rowspan,
203 input_ptrs, in_colormodel, in_x, in_y, in_w, in_h, in_rowspan,
208 printf("BC_CModels::transfer failed:%d %d(%dx%d) to %d(%dx%d)\n", __LINE__,
209 in_colormodel, in_w, in_h, out_colormodel, out_w, out_h);
213 int BC_CModels::init_color(int color, int alpha,
214 unsigned char **output_rows, int out_colormodel,
215 unsigned char *out_yp, unsigned char *out_up, unsigned char *out_vp,
216 int out_x, int out_y, int out_w, int out_h, int out_rowspan)
219 if( out_w > 0 && out_h > 0 ) {
220 BC_Xfer xfer(output_rows, 0, out_yp,out_up,out_vp, 0,0,0,
221 0,0,0,0, out_x,out_y,out_w,out_h, BC_TRANSPARENCY,
222 out_colormodel, color,alpha, 0, out_rowspan);
226 printf("BC_CModels::init_color failed:%d(%dx%d)\n",
227 out_colormodel, out_w, out_h);
231 // specialized functions
233 // in bccmdl.py: specialize("bc_rgba8888", "bc_transparency", "XFER_rgba8888_to_transparency")
234 void BC_Xfer::XFER_rgba8888_to_transparency(unsigned y0, unsigned y1)
236 for( unsigned i=y0; i<y1; ++i ) {
237 uint8_t *outp = output_rows[i + out_y] + out_x * out_pixelsize;
238 uint8_t *inp_row = input_rows[row_table[i]];
239 int bit_no = 0, bit_vec = 0;
240 for( unsigned j=0; j<out_w; ) {
241 uint8_t *inp = inp_row + column_table[j];
242 if( inp[3] < 127 ) bit_vec |= 0x01 << bit_no;
244 if( !bit_no ) { *outp++ = bit_vec; bit_vec = 0; }
246 if( bit_no ) *outp = bit_vec;
250 BC_Xfer::SlicerList BC_Xfer::slicers;
252 BC_Xfer::SlicerList::SlicerList()
257 BC_Xfer::SlicerList::~SlicerList()
262 void BC_Xfer::SlicerList::reset()
264 lock("BC_Xfer::SlicerList::reset");
265 while( last ) remove(last);
270 BC_Xfer::Slicer *BC_Xfer::SlicerList::get_slicer(BC_Xfer *xp)
272 Slicer *slicer = first;
274 if( count < BC_Resources::machine_cpus ) {
275 slicer = new Slicer(xp);
280 remove_pointer(slicer);
284 int BC_Xfer::xfer_slices(int slices)
287 int max_slices = BC_Resources::machine_cpus/2;
288 if( slices > max_slices ) slices = max_slices;
289 if( slices < 1 ) slices = 1;
290 Slicer *active[slices];
291 unsigned y0 = 0, y1 = out_h;
292 int slices1 = slices-1;
294 slicers.lock("BC_Xfer::xfer_slices");
295 for( int i=0; i<slices1; y0=y1 ) {
296 Slicer *slicer = slicers.get_slicer(this);
297 if( !slicer ) { slices1 = i; break; }
299 y1 = out_h * ++i / slices;
300 slicer->slice(this, y0, y1);
304 (this->*xfn)(y0, out_h);
306 for( int i=0; i<slices1; ++i )
307 active[i]->complete->lock("BC_Xfer::xfer_slices");
308 slicers.lock("BC_Xfer::xfer_slices");
309 for( int i=0; i<slices1; ++i )
310 slicers.append(active[i]);
316 BC_Xfer::Slicer::Slicer(BC_Xfer *xp)
319 init = new Condition(0, "BC_Xfer::Slicer::init", 0);
320 complete = new Condition(0, "BC_Xfer::Slicer::complete", 0);
324 BC_Xfer::Slicer::~Slicer()
333 void BC_Xfer::Slicer::slice(BC_Xfer *xp, unsigned y0, unsigned y1)
341 void BC_Xfer::Slicer::run()
344 init->lock("Slicer::run");
346 xfer_fn xfn = xp->xfn;
352 void BC_CModels::bcxfer_stop_slicers()
354 BC_Xfer::slicers.reset();