void BC_Xfer::init( uint8_t **output_rows, int out_colormodel, int out_x, int out_y, int out_w, int out_h, uint8_t *out_yp, uint8_t *out_up, uint8_t *out_vp, uint8_t *out_ap, int out_rowspan, uint8_t **input_rows, int in_colormodel, int in_x, int in_y, int in_w, int in_h, uint8_t *in_yp, uint8_t *in_up, uint8_t *in_vp, uint8_t *in_ap, int in_rowspan, int bg_color, int bg_alpha) { if( bg_color >= 0 ) { this->bg_a = bg_alpha; // only used with init_color this->bg_r = (bg_color>>16) & 0xff; this->bg_g = (bg_color>>8) & 0xff; this->bg_b = (bg_color>>0) & 0xff; } else { // bg_color < 0, no src blending switch( in_colormodel ) { case BC_RGBA8888: in_colormodel = BC_RGBX8888; break; case BC_RGBA16161616: in_colormodel = BC_RGBX16161616; break; case BC_YUVA8888: in_colormodel = BC_YUVX8888; break; case BC_YUVA16161616: in_colormodel = BC_YUVX16161616; break; case BC_RGBA_FLOAT: in_colormodel = BC_RGBX_FLOAT; break; } this->bg_r = this->bg_g = this->bg_b = this->bg_a = 0; } int pmx = BC_CModels::calculate_max(out_colormodel); switch( in_colormodel ) { case BC_TRANSPARENCY: if( BC_CModels::is_yuv(out_colormodel) ) { int ry = this->bg_r, gu = this->bg_g, bv = this->bg_b; YUV::yuv.rgb_to_yuv_8(ry, gu, bv); this->bg_r = ry, this->bg_g = gu, this->bg_b = bv; } if( pmx > 0xff ) { this->bg_r <<= 8; this->bg_g <<= 8; this->bg_b <<= 8; this->bg_a <<= 8; } else pmx = 0xff; break; // prevent bounds errors on poorly dimensioned macro pixel formats case BC_UVY422: case BC_YUV422: in_w &= ~1; break; // 2x1 case BC_YUV420P: case BC_YUV420PI: in_w &= ~1; in_h &= ~1; break; // 2x2 case BC_YUV422P: in_w &= ~1; break; // 2x1 case BC_YUV410P: in_w &= ~3; in_h &= ~3; break; // 4x4 case BC_YUV411P: in_w &= ~3; break; // 4x1 } switch( out_colormodel ) { case BC_UVY422: case BC_YUV422: out_w &= ~1; break; case BC_YUV420P: case BC_YUV420PI: out_w &= ~1; out_h &= ~1; break; case BC_YUV422P: out_w &= ~1; break; case BC_YUV410P: out_w &= ~3; out_h &= ~3; break; case BC_YUV411P: out_w &= ~3; break; } this->output_rows = output_rows; this->input_rows = input_rows; this->out_yp = out_yp; this->out_up = out_up; this->out_vp = out_vp; this->out_ap = out_ap; this->in_yp = in_yp; this->in_up = in_up; this->in_vp = in_vp; this->in_ap = in_ap; this->in_x = in_x; this->in_y = in_y; this->in_w = in_w; this->in_h = in_h; this->out_x = out_x; this->out_y = out_y; this->out_w = out_w; this->out_h = out_h; this->in_colormodel = in_colormodel; switch( in_colormodel ) { case BC_GBRP: in_rowspan = in_w * sizeof(uint8_t); break; case BC_RGB_FLOATP: case BC_RGBA_FLOATP: if( !BC_CModels::has_alpha(out_colormodel) ) this->in_colormodel = BC_RGB_FLOATP; in_rowspan = in_w * sizeof(float); break; } this->total_in_w = in_rowspan; this->out_colormodel = out_colormodel; switch( out_colormodel ) { case BC_GBRP: out_rowspan = out_w * sizeof(uint8_t); break; case BC_RGB_FLOATP: case BC_RGBA_FLOATP: out_rowspan = out_w * sizeof(float); break; } this->total_out_w = out_rowspan; this->in_pixelsize = BC_CModels::calculate_pixelsize(in_colormodel); this->out_pixelsize = BC_CModels::calculate_pixelsize(out_colormodel); if( in_w ) { this->scale = (out_w != in_w) || (in_x != 0); /* + 1 so we don't overflow when calculating in advance */ column_table = new int[out_w+1]; double hscale = (double)in_w/out_w; for( int i=0; iscale = 0; column_table = 0; row_table = 0; } this->bg_fa = (float)this->bg_a / pmx; this->bg_fr = (float)this->bg_r / pmx; this->bg_fg = (float)this->bg_g / pmx; this->bg_fb = (float)this->bg_b / pmx; } BC_Xfer::BC_Xfer(uint8_t **output_rows, uint8_t **input_rows, uint8_t *out_yp, uint8_t *out_up, uint8_t *out_vp, uint8_t *in_yp, uint8_t *in_up, uint8_t *in_vp, int in_x, int in_y, int in_w, int in_h, int out_x, int out_y, int out_w, int out_h, int in_colormodel, int out_colormodel, int bg_color, int bg_alpha, int in_rowspan, int out_rowspan) { init(output_rows, out_colormodel, out_x, out_y, out_w, out_h, out_yp, out_up, out_vp, 0, out_rowspan, input_rows, in_colormodel, in_x, in_y, in_w, in_h, in_yp, in_up, in_vp, 0, in_rowspan, bg_color, bg_alpha); } BC_Xfer::BC_Xfer( uint8_t **output_ptrs, int out_colormodel, int out_x, int out_y, int out_w, int out_h, int out_rowspan, uint8_t **input_ptrs, int in_colormodel, int in_x, int in_y, int in_w, int in_h, int in_rowspan, int bg_color, int bg_alpha) { uint8_t *out_yp = 0, *out_up = 0, *out_vp = 0, *out_ap = 0; uint8_t *in_yp = 0, *in_up = 0, *in_vp = 0, *in_ap = 0; if( BC_CModels::is_planar(in_colormodel) ) { in_yp = input_ptrs[0]; in_up = input_ptrs[1]; in_vp = input_ptrs[2]; if( BC_CModels::has_alpha(in_colormodel) ) in_ap = input_ptrs[3]; } if( BC_CModels::is_planar(out_colormodel) ) { out_yp = output_ptrs[0]; out_up = output_ptrs[1]; out_vp = output_ptrs[2]; if( BC_CModels::has_alpha(out_colormodel) ) out_ap = output_ptrs[3]; } init(output_ptrs, out_colormodel, out_x, out_y, out_w, out_h, out_yp, out_up, out_vp, out_ap, out_rowspan, input_ptrs, in_colormodel, in_x, in_y, in_w, in_h, in_yp, in_up, in_vp, in_ap, in_rowspan, bg_color, bg_alpha); } BC_Xfer::~BC_Xfer() { delete [] column_table; delete [] row_table; } void BC_CModels::transfer(unsigned char **output_rows, unsigned char **input_rows, unsigned char *out_yp, unsigned char *out_up, unsigned char *out_vp, unsigned char *in_yp, unsigned char *in_up, unsigned char *in_vp, int in_x, int in_y, int in_w, int in_h, int out_x, int out_y, int out_w, int out_h, int in_colormodel, int out_colormodel, int bg_color, int in_rowspan, int out_rowspan) { int ret = 1; if( in_w > 0 && in_h > 0 && out_w > 0 && out_h > 0 ) { BC_Xfer xfer(output_rows, input_rows, out_yp, out_up, out_vp, in_yp, in_up, in_vp, in_x, in_y, in_w, in_h, out_x, out_y, out_w, out_h, in_colormodel, out_colormodel, bg_color,0xff, in_rowspan, out_rowspan); ret = xfer.xfer(); } if( ret ) printf("BC_CModels::transfer failed:%d %d(%dx%d) to %d(%dx%d)\n", __LINE__, in_colormodel, in_w, in_h, out_colormodel, out_w, out_h); } void BC_CModels::transfer( uint8_t **output_ptrs, int out_colormodel, int out_x, int out_y, int out_w, int out_h, int out_rowspan, uint8_t **input_ptrs, int in_colormodel, int in_x, int in_y, int in_w, int in_h, int in_rowspan, int bg_color) { int ret = 1; if( in_w > 0 && in_h > 0 && out_w > 0 && out_h > 0 ) { BC_Xfer xfer( output_ptrs, out_colormodel, out_x, out_y, out_w, out_h, out_rowspan, input_ptrs, in_colormodel, in_x, in_y, in_w, in_h, in_rowspan, bg_color,0xff); ret = xfer.xfer(); } if( ret ) printf("BC_CModels::transfer failed:%d %d(%dx%d) to %d(%dx%d)\n", __LINE__, in_colormodel, in_w, in_h, out_colormodel, out_w, out_h); } // color is rgb int BC_CModels::init_color(int color, int alpha, unsigned char **output_rows, int out_colormodel, unsigned char *out_yp, unsigned char *out_up, unsigned char *out_vp, int out_x, int out_y, int out_w, int out_h, int out_rowspan) { int ret = 1; if( out_w > 0 && out_h > 0 ) { BC_Xfer xfer(output_rows, 0, out_yp,out_up,out_vp, 0,0,0, 0,0,0,0, out_x,out_y,out_w,out_h, BC_TRANSPARENCY, out_colormodel, color,alpha, 0, out_rowspan); ret = xfer.xfer(); } if( ret ) printf("BC_CModels::init_color failed:%d(%dx%d)\n", out_colormodel, out_w, out_h); return ret; } // specialized functions // in bccmdl.py: specialize("bc_rgba8888", "bc_transparency", "XFER_rgba8888_to_transparency") void BC_Xfer::XFER_rgba8888_to_transparency(unsigned y0, unsigned y1) { for( unsigned i=y0; i max_slices ) slices = max_slices; if( slices < 1 ) slices = 1; Slicer *active[slices]; unsigned y0 = 0, y1 = out_h; int slices1 = slices-1; if( slices1 > 0 ) { slicers.lock("BC_Xfer::xfer_slices"); for( int i=0; islice(this, y0, y1); } slicers.unlock(); } (this->*xfn)(y0, out_h); if( slices1 > 0 ) { for( int i=0; icomplete->lock("BC_Xfer::xfer_slices"); slicers.lock("BC_Xfer::xfer_slices"); for( int i=0; ixp = xp; init = new Condition(0, "BC_Xfer::Slicer::init", 0); complete = new Condition(0, "BC_Xfer::Slicer::complete", 0); done = 0; start(); } BC_Xfer::Slicer::~Slicer() { done = 1; init->unlock(); join(); delete complete; delete init; } void BC_Xfer::Slicer::slice(BC_Xfer *xp, unsigned y0, unsigned y1) { this->xp = xp; this->y0 = y0; this->y1 = y1; init->unlock(); } void BC_Xfer::Slicer::run() { while( !done ) { init->lock("Slicer::run"); if( done ) break; xfer_fn xfn = xp->xfn; (xp->*xfn)(y0, y1); complete->unlock(); } } void BC_CModels::bcxfer_stop_slicers() { BC_Xfer::slicers.reset(); }