}
cmodels = []
+bcmodels = {}
layout = {}
-dtype = {}
+dtype = { None: None }
special = {}
+mx_bcmdl = -1
-def add_cmodel(nm, typ=None, *args):
- global cmodels, layout, dtype
+def add_cmodel(n, nm, typ=None, *args):
+ global cmodels, bcmodels, layout, dtype, mx_bcmdl
cmodels += [nm,]
+ bcmodels[n] = nm
+ if( n > mx_bcmdl ): mx_bcmdl = n
dtype[nm] = typ
layout[nm] = args
global special
special[(fr_cmdl, to_cmdl)] = fn
-add_cmodel("bc_transparency")
-add_cmodel("bc_compressed")
-
-add_cmodel("bc_rgb8", "i8", "rgb8")
-add_cmodel("bc_rgb565", "i8", "rgb565")
-add_cmodel("bc_bgr565", "i8", "bgr565")
-add_cmodel("bc_bgr888", "i8", "bgr888")
-add_cmodel("bc_bgr8888", "i8", "bgr8888")
-
-add_cmodel("bc_rgb888", "i8", "rgb888")
-add_cmodel("bc_rgba8888", "i8", "rgb888", "a8")
-add_cmodel("bc_argb8888", "i8", "a8", "rgb888")
-add_cmodel("bc_abgr8888", "i8", "a8", "bgr888")
-add_cmodel("bc_rgb161616", "i16", "rgb161616")
-add_cmodel("bc_rgba16161616", "i16", "rgb161616", "a16")
-add_cmodel("bc_yuv888", "i8", "yuv888")
-add_cmodel("bc_yuva8888", "i8", "yuv888", "a8")
-add_cmodel("bc_yuv161616", "i16", "yuv161616")
-add_cmodel("bc_yuva16161616", "i16", "yuv161616", "a16")
-
-add_cmodel("bc_yuv422", "i8", "yuyv8888")
-add_cmodel("bc_uvy422", "i8", "uyvy8888")
-add_cmodel("bc_a8")
-add_cmodel("bc_a16")
-add_cmodel("bc_a_float")
-add_cmodel("bc_yuv101010", "i16", "yuv10101010")
-add_cmodel("bc_vyu888", "i8", "vyu888")
-add_cmodel("bc_uyva8888", "i8", "uyv888", "a8")
-add_cmodel("bc_rgb_float", "fp", "rgbfloat")
-add_cmodel("bc_rgba_float", "fp", "rgbfloat", "afp")
-
-add_cmodel("bc_yuv420p", "i8", "yuv420p")
-add_cmodel("bc_yuv422p", "i8", "yuv422p")
-add_cmodel("bc_yuv444p", "i8", "yuv444p")
-add_cmodel("bc_yuv411p", "i8", "yuv411p")
-add_cmodel("bc_yuv410p", "i8", "yuv410p")
-add_cmodel("bc_rgb_floatp", "fp", "rgbfltp")
-add_cmodel("bc_rgba_floatp", "fp", "rgbfltp", "afpp")
+add_cmodel( 0, "bc_transparency")
+add_cmodel( 1, "bc_compressed")
+
+add_cmodel( 2, "bc_rgb8", "i8", "rgb8")
+add_cmodel( 3, "bc_rgb565", "i8", "rgb565")
+add_cmodel( 4, "bc_bgr565", "i8", "bgr565")
+add_cmodel( 5, "bc_bgr888", "i8", "bgr888")
+add_cmodel( 6, "bc_bgr8888", "i8", "bgr8888")
+
+add_cmodel( 9, "bc_rgb888", "i8", "rgb888")
+add_cmodel(10, "bc_rgba8888", "i8", "rgb888", "a8")
+add_cmodel(20, "bc_argb8888", "i8", "a8", "rgb888")
+add_cmodel(21, "bc_abgr8888", "i8", "a8", "bgr888")
+add_cmodel(11, "bc_rgb161616", "i16", "rgb161616")
+add_cmodel(12, "bc_rgba16161616", "i16", "rgb161616", "a16")
+add_cmodel(13, "bc_yuv888", "i8", "yuv888")
+add_cmodel(14, "bc_yuva8888", "i8", "yuv888", "a8")
+add_cmodel(15, "bc_yuv161616", "i16", "yuv161616")
+add_cmodel(16, "bc_yuva16161616", "i16", "yuv161616", "a16")
+
+add_cmodel(18, "bc_yuv422", "i8", "yuyv8888")
+add_cmodel(19, "bc_uvy422", "i8", "uyvy8888")
+add_cmodel(22, "bc_a8")
+add_cmodel(23, "bc_a16")
+add_cmodel(31, "bc_a_float")
+add_cmodel(24, "bc_yuv101010", "i16", "yuv10101010")
+add_cmodel(25, "bc_vyu888", "i8", "vyu888")
+add_cmodel(26, "bc_uyva8888", "i8", "uyv888", "a8")
+add_cmodel(29, "bc_rgb_float", "fp", "rgbfloat")
+add_cmodel(30, "bc_rgba_float", "fp", "rgbfloat", "afp")
+
+add_cmodel( 7, "bc_yuv420p", "i8", "yuv420p")
+add_cmodel( 8, "bc_yuv422p", "i8", "yuv422p")
+add_cmodel(27, "bc_yuv444p", "i8", "yuv444p")
+add_cmodel(17, "bc_yuv411p", "i8", "yuv411p")
+add_cmodel(28, "bc_yuv410p", "i8", "yuv410p")
+add_cmodel(32, "bc_rgb_floatp", "fp", "rgbfltp")
+add_cmodel(33, "bc_rgba_floatp", "fp", "rgbfltp", "afpp")
specialize("bc_rgba8888", "bc_transparency", "XFER_rgba8888_to_transparency")
print "%svoid %sxfer_%s_to_%s" % (pfx, cls, fr_cmdl[3:], to_cmdl[3:]),
ityp = dtype[fr_cmdl]; fr_typ = ctype[ityp];
otyp = dtype[to_cmdl]; to_typ = ctype[otyp];
- print "()",
+ print "(unsigned y0, unsigned y1)",
def gen_xfer_fn(fr_cmdl, to_cmdl):
global layout, dtype, adata
for to_cmdl in cmodels:
otyp = dtype[to_cmdl]
if( is_specialized(fr_cmdl, to_cmdl) ):
- print " void %s();" % (special[(fr_cmdl, to_cmdl)])
+ print " void %s(unsigned y0, unsigned y1);" % (special[(fr_cmdl, to_cmdl)])
continue
if( ityp is None or otyp is None ): continue
gen_xfer_proto(" ", "", fr_cmdl, to_cmdl);
print ""
print "void %sxfer()" % class_qual
print "{"
-print " switch(in_colormodel) {"
-for fr_cmdl in cmodels:
+mx_no = mx_bcmdl + 1
+print " static xfer_fn xfns[%d][%d] = {" % (mx_no, mx_no)
+for fr_no in range(mx_no):
+ fr_cmdl = bcmodels.get(fr_no)
ityp = dtype[fr_cmdl]
- if( ityp is None ):
- if( not fr_cmdl in [it[0] for it in special] ): continue
- print " case %s:" % (fr_cmdl.upper())
- print " switch(out_colormodel) {"
- for to_cmdl in cmodels:
- if( is_specialized(fr_cmdl, to_cmdl) ):
- print " case %s: %s(); break;" % (to_cmdl.upper(), special[(fr_cmdl, to_cmdl)])
- continue
+ print " { // %s" % (fr_cmdl.upper() if ityp else "None")
+ n = 0
+ for to_no in range(mx_no):
+ to_cmdl = bcmodels.get(to_no)
otyp = dtype[to_cmdl]
- if( ityp is None or otyp is None ): continue
- print " case %s:" % (to_cmdl.upper()),
- print "xfer_%s_to_%s(); break;" % (fr_cmdl[3:], to_cmdl[3:])
- print " }"
- print " break;"
-print " }"
+ xfn = special[(fr_cmdl, to_cmdl)] if( is_specialized(fr_cmdl, to_cmdl) ) else \
+ "xfer_%s_to_%s" % (fr_cmdl[3:], to_cmdl[3:]) if ( ityp and otyp ) else None
+ if( n > 72 ): print ""; n = 0
+ if( n == 0 ): print " ",; n += 4
+ fn = "&%s%s" % (class_qual, xfn) if( xfn ) else "0"
+ print "%s, " % (fn),
+ n += len(fn) + 3
+ print "}, "
+print " }; "
+print " xfn = xfns[in_colormodel][out_colormodel];"
+print " xfer_slices(out_w*out_h/0x80000+1);"
print "}"
print ""
print "#include \"xfer.C\""
// specialized functions
// in bccmdl.py: specialize("bc_rgba8888", "bc_transparency", "XFER_rgba8888_to_transparency")
-void BC_Xfer::XFER_rgba8888_to_transparency()
+void BC_Xfer::XFER_rgba8888_to_transparency(unsigned y0, unsigned y1)
{
- for( unsigned i=0; i<out_h; ++i ) {
+ for( unsigned i=y0; i<y1; ++i ) {
uint8_t *outp = output_rows[i + out_y] + out_x * out_pixelsize;
uint8_t *inp_row = input_rows[row_table[i]];
int bit_no = 0, bit_vec = 0;
}
}
+BC_Xfer::SlicerList BC_Xfer::slicers;
+
+BC_Xfer::SlicerList::SlicerList()
+{
+ waiting = new Condition(0, "BC_Xfer::SlicerList", 1);
+ count = 0;
+}
+
+BC_Xfer::SlicerList::~SlicerList()
+{
+ reset();
+ delete waiting;
+}
+
+void BC_Xfer::SlicerList::reset()
+{
+ lock("BC_Xfer::SlicerList::reset");
+ while( last ) remove(last);
+ count = 0;
+ unlock();
+}
+
+BC_Xfer::Slicer *BC_Xfer::SlicerList::get_slicer(BC_Xfer *xp)
+{
+ while( !first ) {
+ if( count < BC_Resources::machine_cpus ) {
+ append(new Slicer(xp));
+ ++count;
+ }
+ else
+ waiting->lock("BC_Xfer::SlicerList::get_slicer");
+ }
+ Slicer *slicer = first;
+ remove_pointer(slicer);
+ return slicer;
+}
+
+void BC_Xfer::xfer_slices(int slices)
+{
+ if( !xfn ) return;
+ int max_slices = BC_Resources::machine_cpus/2+1;
+ if( slices > max_slices ) slices = max_slices;
+ 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; i<slices1; y0=y1 ) {
+ Slicer *slicer = slicers.get_slicer(this);
+ active[i] = slicer;
+ y1 = out_h * ++i / slices;
+ slicer->slice(this, y0, y1);
+ }
+ slicers.unlock();
+ }
+ (this->*xfn)(y0, out_h);
+ if( slices1 > 0 ) {
+ for( int i=0; i<slices1; ++i )
+ active[i]->complete->lock("BC_Xfer::xfer_slices");
+ slicers.lock("BC_Xfer::xfer_slices");
+ for( int i=0; i<slices1; ++i )
+ slicers.append(active[i]);
+ slicers.unlock();
+ slicers.waiting->unlock();
+ }
+}
+
+BC_Xfer::Slicer::Slicer(BC_Xfer *xp)
+{
+ this->xp = 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();
+}
+
+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();
+}
+
#include "bccmodels.h"
+#include "bcresources.h"
+#include "condition.h"
+#include "linklist.h"
+#include "mutex.h"
+#include "thread.h"
#include "clip.h"
static inline float clp(const int n, float v) {
#define xfer_flat_row_out(oty_t) \
- for( unsigned i=0; i<out_h; ++i ) { \
+ for( unsigned i=y0; i<y1; ++i ) { \
oty_t *out = (oty_t *)(output_rows[i + out_y] + out_x * out_pixelsize); \
#define xfer_flat_row_in(ity_t) \
// yuv420p 2x2
#define xfer_yuv420p_row_out(oty_t) \
- for( unsigned i=0; i<out_h; ++i ) { \
+ for( unsigned i=y0; i<y1; ++i ) { \
int out_rofs = i * total_out_w + out_x; \
oty_t *yop = (oty_t *)(out_yp + out_rofs); \
out_rofs = i / 2 * total_out_w / 2 + out_x / 2; \
// yuv422p 2x1
#define xfer_yuv422p_row_out(oty_t) \
- for( unsigned i=0; i<out_h; ++i ) { \
+ for( unsigned i=y0; i<y1; ++i ) { \
int out_rofs = i * total_out_w + out_x; \
oty_t *yop = (oty_t *)(out_yp + out_rofs); \
out_rofs = i * total_out_w / 2 + out_x / 2; \
// yuv444p 1x1
#define xfer_yuv444p_row_out(oty_t) \
- for( unsigned i=0; i<out_h; ++i ) { \
+ for( unsigned i=y0; i<y1; ++i ) { \
int out_rofs = i * total_out_w + out_x; \
oty_t *yop = (oty_t *)((oty_t *)(out_yp + out_rofs)); \
oty_t *uop = (oty_t *)(out_up + out_rofs); \
// yuv411p 4x1
#define xfer_yuv411p_row_out(oty_t) \
- for( unsigned i=0; i<out_h; ++i ) { \
+ for( unsigned i=y0; i<y1; ++i ) { \
int out_rofs = i * total_out_w + out_x; \
oty_t *yop = (oty_t *)(out_yp + out_rofs); \
out_rofs = i * total_out_w / 4 + out_x / 4; \
// yuv410p 4x4
#define xfer_yuv410p_row_out(oty_t) \
- for( unsigned i=0; i<out_h; ++i ) { \
+ for( unsigned i=y0; i<y1; ++i ) { \
int out_rofs = i * total_out_w + out_x; \
oty_t *yop = (oty_t *)(out_yp + out_rofs); \
out_rofs = i / 4 * total_out_w / 4 + out_x / 4; \
// rgb_floatp
#define xfer_rgb_fltp_row_out(oty_t) \
- for( unsigned i=0; i<out_h; ++i ) { \
+ for( unsigned i=y0; i<y1; ++i ) { \
int out_rofs = i * total_out_w + out_x; \
oty_t *rop = (oty_t *)(out_yp + out_rofs); \
oty_t *gop = (oty_t *)(out_up + out_rofs); \
uint32_t bg_r, bg_g, bg_b;
void xfer();
+ void xfer_slices(int slices);
+ typedef void (BC_Xfer::*xfer_fn)(unsigned y0, unsigned y1);
+ xfer_fn xfn;
+
+ class Slicer : public ListItem<Slicer>, public Thread {
+ public:
+ Condition *init, *complete;
+ Slicer(BC_Xfer *xp);
+ ~Slicer();
+ void slice(BC_Xfer *xp, unsigned y0, unsigned y1);
+ void run();
+ BC_Xfer *xp;
+ int done, y0, y1;
+ };
+
+ class SlicerList : public List<Slicer>, public Mutex {
+ public:
+ int count;
+ Condition *waiting;
+ Slicer *get_slicer(BC_Xfer *xp);
+ void reset();
+ SlicerList();
+ ~SlicerList();
+ };
+ static SlicerList slicers;
static void init();
static class Tables { public: Tables() { init(); } } tables;