diff options
author | James Courtier-Dutton <jcdutton@users.sourceforge.net> | 2002-09-30 05:16:45 +0000 |
---|---|---|
committer | James Courtier-Dutton <jcdutton@users.sourceforge.net> | 2002-09-30 05:16:45 +0000 |
commit | 10439661bc81dee78a374e6aee938eabbea49685 (patch) | |
tree | ea0f6874dbd975f4deb809e2266734bdbc3f5acd /src | |
parent | 6ab806af7e98df9e520773e4d6612c329f8cc285 (diff) | |
download | xine-lib-10439661bc81dee78a374e6aee938eabbea49685.tar.gz xine-lib-10439661bc81dee78a374e6aee938eabbea49685.tar.bz2 |
Fixes and performance improvements to the alphablend.c code.
The fixes involved getting blend_rgb16 to correctly handle different colours in the
highlight area and general overlay area.
Another fix involved fixing the overlay scaling function so that it scales in the same
proportion as the yuv2rgb code.
Currently, blend_yuv has not been updated.
blend_rgb16 has been improved.
blend_rgb24 and blend_rgb32 have not been changed and will probably not work now.
The performance improvements are due to two things: -
1) Special detection of overlays without any buttons/clip areas.
This is detected by ensuring overl->clip_top = -1 when no button is present.
2) Reorganise the blending code so that for each time round the loop, the fewest
possible IF statements are executed.
So, for overlays without any buttons, not checks for the clip area is done.
For overlay with buttons, state is kept as to whether we are above, to the left, inside
or to the right or below the clip area, thus saving having to do IF statements each time
round the loop to find out where we are.
CVS patchset: 2762
CVS date: 2002/09/30 05:16:45
Diffstat (limited to 'src')
-rw-r--r-- | src/libspudec/spu.c | 14 | ||||
-rw-r--r-- | src/video_out/alphablend.c | 410 | ||||
-rw-r--r-- | src/video_out/video_out_xshm.c | 8 | ||||
-rw-r--r-- | src/video_out/yuv2rgb.c | 11 | ||||
-rw-r--r-- | src/xine-engine/osd.c | 2 |
5 files changed, 374 insertions, 71 deletions
diff --git a/src/libspudec/spu.c b/src/libspudec/spu.c index 005f74627..1e2ffda49 100644 --- a/src/libspudec/spu.c +++ b/src/libspudec/spu.c @@ -35,7 +35,7 @@ * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Id: spu.c,v 1.47 2002/09/18 15:42:56 mroi Exp $ + * $Id: spu.c,v 1.48 2002/09/30 05:16:45 jcdutton Exp $ * */ @@ -519,14 +519,16 @@ static void spudec_do_commands(spudec_state_t *state, spudec_seq_t* seq, vo_over ovl->trans[2] = trans->entry1; ovl->trans[1] = trans->entry2; ovl->trans[0] = trans->entry3; -/**************************88 +/* FIXME: Force invisible SPUs to be visible. */ +/* if ( (trans->entry0 | trans->entry1 | trans->entry2 | trans->entry3) == 0) { ovl->trans[3] = 15; ovl->trans[2] = 15; ovl->trans[1] = 15; - ovl->trans[0] = 0; + ovl->trans[0] = 8; } -*************************/ +*/ + #ifdef LOG_DEBUG printf ("spu: \ttrans [%d %d %d %d]\n", ovl->trans[0], ovl->trans[1], ovl->trans[2], ovl->trans[3]); @@ -547,7 +549,7 @@ static void spudec_do_commands(spudec_state_t *state, spudec_seq_t* seq, vo_over ovl->y = (buf[4] << 4) | (buf[5] >> 4); ovl->width = (((buf[2] & 0x0f) << 8) | buf[3]) - ovl->x + 1; ovl->height = (((buf[5] & 0x0f) << 8) | buf[6]) - ovl->y + 1; - ovl->clip_top = 0; + ovl->clip_top = -1; ovl->clip_bottom = ovl->height - 1; ovl->clip_left = 0; ovl->clip_right = ovl->width - 1; @@ -859,7 +861,7 @@ void spudec_copy_nav_to_overlay(pci_t* nav_pci, uint32_t* clut, int32_t button, * overlay clipping areas are in overlay coordinates; * therefore we must subtract the display coordinates of the underlying overlay */ overlay->clip_left = (button_ptr->x_start > base->x) ? (button_ptr->x_start - base->x) : 0; - overlay->clip_top = (button_ptr->y_start > base->y) ? (button_ptr->y_start - base->y) : 0; + overlay->clip_top = (button_ptr->y_start > base->y) ? (button_ptr->y_start - base->y) : -1; overlay->clip_right = (button_ptr->x_end > base->x) ? (button_ptr->x_end - base->x) : 0; overlay->clip_bottom = (button_ptr->y_end > base->y) ? (button_ptr->y_end - base->y) : 0; if(button_ptr->btn_coln != 0) { diff --git a/src/video_out/alphablend.c b/src/video_out/alphablend.c index 1e9d19a6a..3ade25735 100644 --- a/src/video_out/alphablend.c +++ b/src/video_out/alphablend.c @@ -30,6 +30,7 @@ /* #define LOG_BLEND_YUV +#define LOG_BLEND_RGB16 */ #include <string.h> @@ -126,31 +127,70 @@ rle_img_advance_line(rle_elem_t *rle, rle_elem_t *rle_limit, int w) return rle; } - void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl, - int img_width, int img_height, - int dst_width, int dst_height) + int img_width, int img_height, + int dst_width, int dst_height) { uint8_t *trans; - clut_t* clut = (clut_t*) img_overl->clip_color; + clut_t *clut; int src_width = img_overl->width; int src_height = img_overl->height; rle_elem_t *rle = img_overl->rle; + rle_elem_t *rle_start = img_overl->rle; rle_elem_t *rle_limit = rle + img_overl->num_rle; int x, y, x1_scaled, x2_scaled; - int dy, dy_step, x_scale; /* scaled 2**SCALE_SHIFT */ + int dy, dy_step, x_scale; /* scaled 2**SCALE_SHIFT */ + int dst_y; int clip_right; uint16_t *img_pix; + int rlelen; + int rle_this_bite; + int rle_remainder; + int zone_state=0; + uint8_t clr_next,clr; + uint16_t o; + double img_offset; + int stripe_height; +/* + * Let zone_state keep state. + * 0 = Starting. + * 1 = Above button. + * 2 = Left of button. + * 3 = Inside of button. + * 4 = Right of button. + * 5 = Below button. + * 6 = Finished. + * + * Each time round the loop, update the state. + * We can do this easily and cheaply(fewer IF statements per cycle) as we are testing rle end position anyway. + * Possible optimization is to ensure that rle never overlaps from outside to inside a button. + * Possible optimization is to pre-scale the RLE overlay, so that no scaling is needed here. + */ - dy_step = INT_TO_SCALED(dst_height) / img_height; +#ifdef LOG_BLEND_RGB16 + printf("blend_rgb16: img_height=%i, dst_height=%i\n", img_height, dst_height); + printf("blend_rgb16: img_width=%i, dst_width=%i\n", img_width, dst_width); +#endif +/* stripe_height is used in yuv2rgb scaling, so use the same scale factor here for overlays. */ + stripe_height = 16 * img_height / dst_height; +/* dy_step = INT_TO_SCALED(dst_height) / img_height; */ + dy_step = INT_TO_SCALED(16) / stripe_height; x_scale = INT_TO_SCALED(img_width) / dst_width; +#ifdef LOG_BLEND_RGB16 + printf("blend_rgb16: dy_step=%i, x_scale=%i\n", dy_step, x_scale); +#endif - img_pix = (uint16_t *) img + img_offset = ( ( (img_overl->y * img_height) / dst_height) * img_width) + + ( (img_overl->x * img_width) / dst_width); +#ifdef LOG_BLEND_RGB16 + printf("blend_rgb16: x=%i, y=%i, img_offset=%lf\n", img_overl->x, img_overl->y, img_offset); +#endif + img_pix = (uint16_t *) img + (int)img_offset; +/* + (img_overl->y * img_height / dst_height) * img_width + (img_overl->x * img_width / dst_width); - - trans = img_overl->clip_trans; +*/ /* avoid wraping overlay if drawing to small image */ if( (img_overl->x + img_overl->clip_right) < dst_width ) @@ -162,66 +202,320 @@ void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl, if( (src_height + img_overl->y) >= dst_height ) src_height = dst_height - 1 - img_overl->y; - for (y = dy = 0; y < src_height && rle < rle_limit;) { - int mask = !(img_overl->clip_top > y || img_overl->clip_bottom < y); - rle_elem_t *rle_start = rle; + rlelen = rle_remainder = rle_this_bite = 0; + rle_remainder = rlelen = rle->len; + clr_next = rle->color; + rle++; + y = dy = 0; + dst_y = 0; + x = x1_scaled = x2_scaled = 0; - for (x = x1_scaled = 0; x < src_width;) { - uint8_t clr; - uint16_t o; - int rlelen; +#ifdef LOG_BLEND_RGB16 + printf("blend_rgb16 started\n"); +#endif - clr = rle->color; - o = trans[clr]; - rlelen = rle->len; + while (zone_state != 6) { + clr = clr_next; + switch (zone_state) { + case 0: /* Starting */ + /* FIXME: Get libspudec to set clip_top to -1 if no button */ + if (img_overl->clip_top < 0) { +#ifdef LOG_BLEND_RGB16 + printf("blend_rgb16: No button clip area\n"); +#endif - if (o && mask) { - /* threat cases where clipping border is inside rle->len pixels */ - if ( img_overl->clip_left > x ) { - if( img_overl->clip_left < x + rlelen ) { - x1_scaled = SCALED_TO_INT( img_overl->clip_left * x_scale ); - rlelen -= img_overl->clip_left - x; - x += img_overl->clip_left - x; - } else { - o = 0; + zone_state = 7; + break; + } +#ifdef LOG_BLEND_RGB16 + printf("blend_rgb16: Button clip area found\n"); +#endif + if (y < img_overl->clip_top) { + zone_state = 1; + break; + } else if (y > img_overl->clip_bottom) { + zone_state = 5; + break; + } else if (x < img_overl->clip_left) { + zone_state = 2; + break; + } else if (x > img_overl->clip_right) { + zone_state = 4; + break; + } else { + zone_state = 3; + break; + } + break; + case 1: /* Above clip area */ + clut = (clut_t*) img_overl->color; + trans = img_overl->trans; + o = trans[clr]; + rle_this_bite = rle_remainder; + rle_remainder = 0; + rlelen -= rle_this_bite; + /*printf("(x,y) = (%03i,%03i), clr=%03x, len=%03i, zone=%i\n", x, y, clr, rle_this_bite, zone_state); */ + if (o) { + x1_scaled = SCALED_TO_INT( x * x_scale ); + x2_scaled = SCALED_TO_INT( (x + rle_this_bite) * x_scale); + mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled); + } + x += rle_this_bite; + if (x >= src_width ) { + x -= src_width; + img_pix += img_width; + + dy += dy_step; + if (dy >= INT_TO_SCALED(1)) { + dy -= INT_TO_SCALED(1); + ++y; + while (dy >= INT_TO_SCALED(1)) { + rle = rle_img_advance_line(rle, rle_limit, src_width); + dy -= INT_TO_SCALED(1); + ++y; } - } else if( clip_right < x + rlelen ) { - if( clip_right > x ) { - x2_scaled = SCALED_TO_INT( clip_right * x_scale); - mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, - x2_scaled-x1_scaled); - o = 0; - } else { - o = 0; + rle_start = rle; + } else { + rle = rle_start; /* y-scaling, reuse the last rle encoded line */ + } + } + rle_remainder = rlelen = rle->len; + clr_next = rle->color; + rle++; + if (rle >= rle_limit) { + zone_state = 6; + } + if (y >= img_overl->clip_top) { + zone_state = 2; + if (x >= img_overl->clip_left) { + zone_state = 3; + if (x >= img_overl->clip_right) { + zone_state = 4; } - } + } } - - x2_scaled = SCALED_TO_INT((x + rlelen) * x_scale); - if (o && mask) { - mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled); + break; + case 2: /* Left of button */ + clut = (clut_t*) img_overl->color; + trans = img_overl->trans; + o = trans[clr]; + if (x + rle_remainder < img_overl->clip_left) { + rle_this_bite = rle_remainder; + rle_remainder = rlelen = rle->len; + clr_next = rle->color; + rle++; + } else { + rle_this_bite = img_overl->clip_left - x; + rle_remainder -= rle_this_bite; + zone_state = 3; } - - x1_scaled = x2_scaled; - x += rlelen; + if (o) { + x1_scaled = SCALED_TO_INT( x * x_scale ); + x2_scaled = SCALED_TO_INT( (x + rle_this_bite) * x_scale); + mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled); + } + x += rle_this_bite; + if (x >= src_width ) { + x -= src_width; + img_pix += img_width; + dy += dy_step; + if (dy >= INT_TO_SCALED(1)) { + dy -= INT_TO_SCALED(1); + ++y; + while (dy >= INT_TO_SCALED(1)) { + rle = rle_img_advance_line(rle, rle_limit, src_width); + dy -= INT_TO_SCALED(1); + ++y; + } + rle_start = rle; + } else { + rle = rle_start; /* y-scaling, reuse the last rle encoded line */ + } + if (y > img_overl->clip_bottom) { + zone_state = 5; + break; + } + } + if (rle >= rle_limit) { + zone_state = 6; + } + break; + case 3: /* In button */ + clut = (clut_t*) img_overl->clip_color; + trans = img_overl->clip_trans; + o = trans[clr]; + if (x + rle_remainder < img_overl->clip_right) { + rle_this_bite = rle_remainder; + rle_remainder = rlelen = rle->len; + clr_next = rle->color; + rle++; + } else { + rle_this_bite = img_overl->clip_right - x; + rle_remainder -= rle_this_bite; + zone_state = 4; + } + if (o) { + x1_scaled = SCALED_TO_INT( x * x_scale ); + x2_scaled = SCALED_TO_INT( (x + rle_this_bite) * x_scale); + mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled); + } + x += rle_this_bite; + if (x >= src_width ) { + x -= src_width; + img_pix += img_width; + dy += dy_step; + if (dy >= INT_TO_SCALED(1)) { + dy -= INT_TO_SCALED(1); + ++y; + while (dy >= INT_TO_SCALED(1)) { + rle = rle_img_advance_line(rle, rle_limit, src_width); + dy -= INT_TO_SCALED(1); + ++y; + } + rle_start = rle; + } else { + rle = rle_start; /* y-scaling, reuse the last rle encoded line */ + } + if (y > img_overl->clip_bottom) { + zone_state = 5; + break; + } + } + if (rle >= rle_limit) { + zone_state = 6; + } + break; + case 4: /* Right of button */ + clut = (clut_t*) img_overl->color; + trans = img_overl->trans; + o = trans[clr]; + if (x + rle_remainder < src_width) { + rle_this_bite = rle_remainder; + rle_remainder = rlelen = rle->len; + clr_next = rle->color; + rle++; + } else { + rle_this_bite = src_width - x; + rle_remainder -= rle_this_bite; + zone_state = 2; + } + if (o) { + x1_scaled = SCALED_TO_INT( x * x_scale ); + x2_scaled = SCALED_TO_INT( (x + rle_this_bite) * x_scale); + mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled); + } + x += rle_this_bite; + if (x >= src_width ) { + x -= src_width; + img_pix += img_width; + dy += dy_step; + if (dy >= INT_TO_SCALED(1)) { + dy -= INT_TO_SCALED(1); + ++y; + while (dy >= INT_TO_SCALED(1)) { + rle = rle_img_advance_line(rle, rle_limit, src_width); + dy -= INT_TO_SCALED(1); + ++y; + } + rle_start = rle; + } else { + rle = rle_start; /* y-scaling, reuse the last rle encoded line */ + } + if (y > img_overl->clip_bottom) { + zone_state = 5; + break; + } + } + if (rle >= rle_limit) { + zone_state = 6; + } + break; + case 5: /* Below button */ + clut = (clut_t*) img_overl->color; + trans = img_overl->trans; + o = trans[clr]; + rle_this_bite = rle_remainder; + rle_remainder = 0; + rlelen -= rle_this_bite; + if (o) { + x1_scaled = SCALED_TO_INT( x * x_scale ); + x2_scaled = SCALED_TO_INT( (x + rle_this_bite) * x_scale); + mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled); + } + x += rle_this_bite; + if (x >= src_width ) { + x -= src_width; + img_pix += img_width; + dy += dy_step; + if (dy >= INT_TO_SCALED(1)) { + dy -= INT_TO_SCALED(1); + ++y; + while (dy >= INT_TO_SCALED(1)) { + rle = rle_img_advance_line(rle, rle_limit, src_width); + dy -= INT_TO_SCALED(1); + ++y; + } + rle_start = rle; + } else { + rle = rle_start; /* y-scaling, reuse the last rle encoded line */ + } + } + rle_remainder = rlelen = rle->len; + clr_next = rle->color; rle++; - if (rle >= rle_limit) break; - } - - img_pix += img_width; - dy += dy_step; - if (dy >= INT_TO_SCALED(1)) { - dy -= INT_TO_SCALED(1); - ++y; - while (dy >= INT_TO_SCALED(1)) { - rle = rle_img_advance_line(rle, rle_limit, src_width); - dy -= INT_TO_SCALED(1); - ++y; + if (rle >= rle_limit) { + zone_state = 6; } - } else { - rle = rle_start; /* y-scaling, reuse the last rle encoded line */ + break; + case 6: /* Finished */ + printf("Don't ever get here\n"); + assert(0); + case 7: /* No button */ + clut = (clut_t*) img_overl->color; + trans = img_overl->trans; + o = trans[clr]; + rle_this_bite = rle_remainder; + rle_remainder = 0; + rlelen -= rle_this_bite; + if (o) { + x1_scaled = SCALED_TO_INT( x * x_scale ); + x2_scaled = SCALED_TO_INT( (x + rle_this_bite) * x_scale); + mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled); + } + x += rle_this_bite; + if (x >= src_width ) { + x -= src_width; + img_pix += img_width; + dst_y++; + dy += dy_step; + if (dy >= INT_TO_SCALED(1)) { + dy -= INT_TO_SCALED(1); + ++y; + while (dy >= INT_TO_SCALED(1)) { + rle = rle_img_advance_line(rle, rle_limit, src_width); + dy -= INT_TO_SCALED(1); + ++y; + } + rle_start = rle; + } else { + rle = rle_start; /* y-scaling, reuse the last rle encoded line */ + } + } + rle_remainder = rlelen = rle->len; + clr_next = rle->color; + rle++; + if (rle >= rle_limit) { + zone_state = 6; + } + break; + default: + ; } } +#ifdef LOG_BLEND_RGB16 + printf("blend_rgb16 ended\n"); +#endif + } void blend_rgb24 (uint8_t * img, vo_overlay_t * img_overl, diff --git a/src/video_out/video_out_xshm.c b/src/video_out/video_out_xshm.c index 66cb205fc..a37b8777c 100644 --- a/src/video_out/video_out_xshm.c +++ b/src/video_out/video_out_xshm.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: video_out_xshm.c,v 1.90 2002/09/16 11:35:25 jcdutton Exp $ + * $Id: video_out_xshm.c,v 1.91 2002/09/30 05:16:45 jcdutton Exp $ * * video_out_xshm.c, X11 shared memory extension interface for xine * @@ -540,7 +540,11 @@ static void xshm_update_frame_format (xine_vo_driver_t *this_gen, frame->stripe_height = 16 * frame->sc.output_height / frame->sc.delivered_height; - /* printf ("video_out_xshm: stripe height is %d\n", frame->stripe_height); */ +#ifdef LOG + printf ("video_out_xshm: stripe out_ht=%i, deliv_ht=%i\n", + frame->sc.output_height, frame->sc.delivered_height); + printf ("video_out_xshm: stripe height is %d\n", frame->stripe_height); +#endif /* * set up colorspace converter diff --git a/src/video_out/yuv2rgb.c b/src/video_out/yuv2rgb.c index a6e7d195d..8342ddd5a 100644 --- a/src/video_out/yuv2rgb.c +++ b/src/video_out/yuv2rgb.c @@ -22,7 +22,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * $Id: yuv2rgb.c,v 1.32 2002/08/14 12:23:33 esnel Exp $ + * $Id: yuv2rgb.c,v 1.33 2002/09/30 05:16:45 jcdutton Exp $ */ #include "config.h" @@ -73,10 +73,10 @@ static int yuv2rgb_configure (yuv2rgb_t *this, int y_stride, int uv_stride, int dest_width, int dest_height, int rgb_stride) { - /* +/* printf ("yuv2rgb setup (%d x %d => %d x %d)\n", source_width, source_height, dest_width, dest_height); - */ +*/ if (prof_scale_line == -1) prof_scale_line = xine_profiler_allocate_slot("xshm scale line"); @@ -104,7 +104,10 @@ static int yuv2rgb_configure (yuv2rgb_t *this, this->step_dx = source_width * 32768 / dest_width; this->step_dy = source_height * 32768 / dest_height; - +/* + printf("yuv2rgb config: src_ht=%i, dst_ht=%i\n",source_height, dest_height); + printf("yuv2rgb config: step_dy=%i %f\n",this->step_dy, (float)this->step_dy / 32768.0); +*/ this->scale_line = find_scale_line_func(this->step_dx); if ((source_width == dest_width) && (source_height == dest_height)) { diff --git a/src/xine-engine/osd.c b/src/xine-engine/osd.c index 3e3eb521d..302e0ac8d 100644 --- a/src/xine-engine/osd.c +++ b/src/xine-engine/osd.c @@ -169,7 +169,7 @@ static int osd_show (osd_object_t *osd, int64_t vpts ) { this->event.object.overlay->width = osd->x2 - osd->x1 + 1; this->event.object.overlay->height = osd->y2 - osd->y1 + 1; - this->event.object.overlay->clip_top = 0; + this->event.object.overlay->clip_top = -1; this->event.object.overlay->clip_bottom = this->event.object.overlay->height + osd->display_x; this->event.object.overlay->clip_left = 0; |