summaryrefslogtreecommitdiff
path: root/noncore/multimedia/opieplayer2/alphablend.c
authorzecke <zecke>2005-04-17 13:56:34 (UTC)
committer zecke <zecke>2005-04-17 13:56:34 (UTC)
commit3d5e5c098ccb686588380bc1f220beafbc5a6d76 (patch) (unidiff)
tree92fad8a98ea341ec290dc7f9fca7759470b795f6 /noncore/multimedia/opieplayer2/alphablend.c
parent49335d66d8e96b1fc86ecfe95cd343c8960126bc (diff)
downloadopie-3d5e5c098ccb686588380bc1f220beafbc5a6d76.zip
opie-3d5e5c098ccb686588380bc1f220beafbc5a6d76.tar.gz
opie-3d5e5c098ccb686588380bc1f220beafbc5a6d76.tar.bz2
Opie Player2 XINE update:
-update xine code alphablend, yuv2rgb to be up to date -XINELib: -use the XINE infrastructure to change the gui width/height -use the XINE infrastructure to change the brightness -Update the NULL Video Driver: -make use of frame_dest_cb and and dest_size_cb (callback) to update the size of the gui -use alphablend -merge the video_out_fb xine driver To Alwin: your testvideo now lockups op2. with valgrind I see it has to do with the yuv2rgb conversion methods
Diffstat (limited to 'noncore/multimedia/opieplayer2/alphablend.c') (more/less context) (show whitespace changes)
-rw-r--r--noncore/multimedia/opieplayer2/alphablend.c1469
1 files changed, 1249 insertions, 220 deletions
diff --git a/noncore/multimedia/opieplayer2/alphablend.c b/noncore/multimedia/opieplayer2/alphablend.c
index cdd7b28..ab80531 100644
--- a/noncore/multimedia/opieplayer2/alphablend.c
+++ b/noncore/multimedia/opieplayer2/alphablend.c
@@ -1,5 +1 @@
1//TOAST_SPU will define ALL spu entries - no matter the tranparency
2//#define TOAST_SPU
3/* #define PRIV_CLUT */
4/* Currently only blend_yuv(..) works */
5/* /*
@@ -9,2 +5,3 @@
9 * Copyright (C) 2000 Thomas Mirlacher 5 * Copyright (C) 2000 Thomas Mirlacher
6 * 2002-2004 the xine project
10 * 7 *
@@ -32,2 +29,3 @@
32#define LOG_BLEND_YUV 29#define LOG_BLEND_YUV
30#define LOG_BLEND_RGB16
33*/ 31*/
@@ -37,5 +35,3 @@
37#include <stdio.h> 35#include <stdio.h>
38#include <inttypes.h>
39 36
40#include <xine.h>
41#include <xine/xine_internal.h> 37#include <xine/xine_internal.h>
@@ -43,2 +39,3 @@
43#include "alphablend.h" 39#include "alphablend.h"
40#include "bswap.h"
44 41
@@ -73,15 +70,2 @@ static void mem_blend24(uint8_t *mem, uint8_t r, uint8_t g, uint8_t b,
73 70
74static void mem_blend24_32(uint8_t *mem, uint8_t r, uint8_t g, uint8_t b,
75 uint8_t o, int len) {
76 uint8_t *limit = mem + len*4;
77 while (mem < limit) {
78 *mem = BLEND_BYTE(*mem, r, o);
79 mem++;
80 *mem = BLEND_BYTE(*mem, g, o);
81 mem++;
82 *mem = BLEND_BYTE(*mem, b, o);
83 mem += 2;
84 }
85}
86
87static void mem_blend32(uint8_t *mem, uint8_t *src, uint8_t o, int len) { 71static void mem_blend32(uint8_t *mem, uint8_t *src, uint8_t o, int len) {
@@ -100,3 +84,2 @@ static void mem_blend32(uint8_t *mem, uint8_t *src, uint8_t o, int len) {
100 84
101
102/* 85/*
@@ -129,9 +112,9 @@ rle_img_advance_line(rle_elem_t *rle, rle_elem_t *rle_limit, int w)
129 112
130
131void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl, 113void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl,
132 int img_width, int img_height, 114 int img_width, int img_height,
133 int dst_width, int dst_height) 115 int dst_width, int dst_height,
116 alphablend_t *extra_data)
134{ 117{
135 uint8_t *trans; 118 uint8_t *trans;
136 clut_t* clut = (clut_t*) img_overl->clip_color; 119 clut_t *clut;
137 120
@@ -140,2 +123,3 @@ void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl,
140 rle_elem_t *rle = img_overl->rle; 123 rle_elem_t *rle = img_overl->rle;
124 rle_elem_t *rle_start = img_overl->rle;
141 rle_elem_t *rle_limit = rle + img_overl->num_rle; 125 rle_elem_t *rle_limit = rle + img_overl->num_rle;
@@ -145,11 +129,55 @@ void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl,
145 uint16_t *img_pix; 129 uint16_t *img_pix;
130 int rlelen;
131 int rle_this_bite;
132 int rle_remainder;
133 int zone_state=0;
134 uint8_t clr_next,clr;
135 uint16_t o;
136 double img_offset;
137 int stripe_height;
138/*
139 * Let zone_state keep state.
140 * 0 = Starting.
141 * 1 = Above button.
142 * 2 = Left of button.
143 * 3 = Inside of button.
144 * 4 = Right of button.
145 * 5 = Below button.
146 * 6 = Finished.
147 *
148 * Each time round the loop, update the state.
149 * We can do this easily and cheaply(fewer IF statements per cycle) as we are testing rle end position anyway.
150 * Possible optimization is to ensure that rle never overlaps from outside to inside a button.
151 * Possible optimization is to pre-scale the RLE overlay, so that no scaling is needed here.
152 */
146 153
147 dy_step = INT_TO_SCALED(dst_height) / img_height; 154#ifdef LOG_BLEND_RGB16
148 x_scale = INT_TO_SCALED(img_width) / dst_width; 155 printf("blend_rgb16: img_height=%i, dst_height=%i\n", img_height, dst_height);
156 printf("blend_rgb16: img_width=%i, dst_width=%i\n", img_width, dst_width);
157 if (img_width & 1) { printf("blend_rgb16s: odd\n");}
158 else { printf("blend_rgb16s: even\n");}
149 159
150 img_pix = (uint16_t *) img 160#endif
161/* stripe_height is used in yuv2rgb scaling, so use the same scale factor here for overlays. */
162 stripe_height = 16 * img_height / dst_height;
163/* dy_step = INT_TO_SCALED(dst_height) / img_height; */
164 dy_step = INT_TO_SCALED(16) / stripe_height;
165 x_scale = INT_TO_SCALED(img_width) / dst_width;
166#ifdef LOG_BLEND_RGB16
167 printf("blend_rgb16: dy_step=%i, x_scale=%i\n", dy_step, x_scale);
168#endif
169 if (img_width & 1) img_width++;
170 img_offset = ( ( (img_overl->y * img_height) / dst_height) * img_width)
171 + ( (img_overl->x * img_width) / dst_width);
172#ifdef LOG_BLEND_RGB16
173 printf("blend_rgb16: x=%i, y=%i, w=%i, h=%i, img_offset=%lf\n", img_overl->x, img_overl->y,
174 img_overl->width,
175 img_overl->height,
176 img_offset);
177#endif
178 img_pix = (uint16_t *) img + (int)img_offset;
179/*
151 + (img_overl->y * img_height / dst_height) * img_width 180 + (img_overl->y * img_height / dst_height) * img_width
152 + (img_overl->x * img_width / dst_width); 181 + (img_overl->x * img_width / dst_width);
153 182*/
154 trans = img_overl->clip_trans;
155 183
@@ -159,3 +187,3 @@ void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl,
159 else 187 else
160 clip_right = dst_width - 1 - img_overl->x; 188 clip_right = dst_width - img_overl->x;
161 189
@@ -163,50 +191,294 @@ void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl,
163 if( (src_height + img_overl->y) >= dst_height ) 191 if( (src_height + img_overl->y) >= dst_height )
164 src_height = dst_height - 1 - img_overl->y; 192 src_height = dst_height - img_overl->y;
165 193
166 for (y = dy = 0; y < src_height && rle < rle_limit;) { 194 rlelen = rle_remainder = rle_this_bite = 0;
167 int mask = !(img_overl->clip_top > y || img_overl->clip_bottom < y); 195 rle_remainder = rlelen = rle->len;
168 rle_elem_t *rle_start = rle; 196 clr_next = rle->color;
197 rle++;
198 y = dy = 0;
199 x = x1_scaled = x2_scaled = 0;
169 200
170 for (x = x1_scaled = 0; x < src_width;) { 201#ifdef LOG_BLEND_RGB16
171 uint8_t clr; 202 printf("blend_rgb16 started\n");
172 uint16_t o; 203#endif
173 int rlelen;
174 204
175 clr = rle->color; 205 while (zone_state != 6) {
206 clr = clr_next;
207 switch (zone_state) {
208 case 0: /* Starting */
209 /* FIXME: Get libspudec to set clip_top to -1 if no button */
210 if (img_overl->clip_top < 0) {
211#ifdef LOG_BLEND_RGB16
212 printf("blend_rgb16: No button clip area\n");
213#endif
214
215 zone_state = 7;
216 break;
217 }
218#ifdef LOG_BLEND_RGB16
219 printf("blend_rgb16: Button clip area found. (%d,%d) .. (%d,%d)\n",
220 img_overl->clip_left,
221 img_overl->clip_top,
222 img_overl->clip_right,
223 img_overl->clip_bottom);
224#endif
225 if (y < img_overl->clip_top) {
226 zone_state = 1;
227 break;
228 } else if (y >= img_overl->clip_bottom) {
229 zone_state = 5;
230 break;
231 } else if (x < img_overl->clip_left) {
232 zone_state = 2;
233 break;
234 } else if (x >= img_overl->clip_right) {
235 zone_state = 4;
236 break;
237 } else {
238 zone_state = 3;
239 break;
240 }
241 break;
242 case 1: /* Above clip area */
243 clut = (clut_t*) img_overl->color;
244 trans = img_overl->trans;
176 o = trans[clr]; 245 o = trans[clr];
177 rlelen = rle->len; 246 rle_this_bite = rle_remainder;
247 rle_remainder = 0;
248 rlelen -= rle_this_bite;
249 /*printf("(x,y) = (%03i,%03i), clr=%03x, len=%03i, zone=%i\n", x, y, clr, rle_this_bite, zone_state); */
250 if (o) {
251 x1_scaled = SCALED_TO_INT( x * x_scale );
252 x2_scaled = SCALED_TO_INT( (x + rle_this_bite) * x_scale);
253 mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled);
254 }
255 x += rle_this_bite;
256 if (x >= src_width ) {
257 x -= src_width;
258 img_pix += img_width;
178 259
179 if (o && mask) { 260 dy += dy_step;
180 /* threat cases where clipping border is inside rle->len pixels */ 261 if (dy >= INT_TO_SCALED(1)) {
181 if ( img_overl->clip_left > x ) { 262 dy -= INT_TO_SCALED(1);
182 if( img_overl->clip_left < x + rlelen ) { 263 ++y;
183 x1_scaled = SCALED_TO_INT( img_overl->clip_left * x_scale ); 264 while (dy >= INT_TO_SCALED(1)) {
184 rlelen -= img_overl->clip_left - x; 265 rle = rle_img_advance_line(rle, rle_limit, src_width);
185 x += img_overl->clip_left - x; 266 dy -= INT_TO_SCALED(1);
267 ++y;
268 }
269 rle_start = rle;
186 } else { 270 } else {
187 o = 0; 271 rle = rle_start; /* y-scaling, reuse the last rle encoded line */
188 } 272 }
189 } else if( clip_right < x + rlelen ) { 273 }
190 if( clip_right > x ) { 274 rle_remainder = rlelen = rle->len;
191 x2_scaled = SCALED_TO_INT( clip_right * x_scale); 275 clr_next = rle->color;
192 mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, 276 rle++;
193 x2_scaled-x1_scaled); 277 if (rle >= rle_limit) {
194 o = 0; 278 zone_state = 6;
279 }
280 if (y >= img_overl->clip_top) {
281 zone_state = 2;
282#ifdef LOG_BLEND_RGB16
283 printf("blend_rgb16: Button clip top reached. y=%i, top=%i\n",
284 y, img_overl->clip_top);
285#endif
286 if (x >= img_overl->clip_left) {
287 zone_state = 3;
288 if (x >= img_overl->clip_right) {
289 zone_state = 4;
290 }
291 }
292 }
293 break;
294 case 2: /* Left of button */
295 clut = (clut_t*) img_overl->color;
296 trans = img_overl->trans;
297 o = trans[clr];
298 if (x + rle_remainder <= img_overl->clip_left) {
299 rle_this_bite = rle_remainder;
300 rle_remainder = rlelen = rle->len;
301 clr_next = rle->color;
302 rle++;
303 } else {
304 rle_this_bite = img_overl->clip_left - x;
305 rle_remainder -= rle_this_bite;
306 zone_state = 3;
307 }
308 if (o) {
309 x1_scaled = SCALED_TO_INT( x * x_scale );
310 x2_scaled = SCALED_TO_INT( (x + rle_this_bite) * x_scale);
311 mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled);
312 }
313 x += rle_this_bite;
314 if (x >= src_width ) {
315 x -= src_width;
316 img_pix += img_width;
317 dy += dy_step;
318 if (dy >= INT_TO_SCALED(1)) {
319 dy -= INT_TO_SCALED(1);
320 ++y;
321 while (dy >= INT_TO_SCALED(1)) {
322 rle = rle_img_advance_line(rle, rle_limit, src_width);
323 dy -= INT_TO_SCALED(1);
324 ++y;
325 }
326 rle_start = rle;
195 } else { 327 } else {
196 o = 0; 328 rle = rle_start; /* y-scaling, reuse the last rle encoded line */
197 } 329 }
330 if (y >= img_overl->clip_bottom) {
331 zone_state = 5;
332 break;
198 } 333 }
199 } 334 }
200 335 if (rle >= rle_limit) {
201 x2_scaled = SCALED_TO_INT((x + rlelen) * x_scale); 336 zone_state = 6;
202 if (o && mask) { 337 }
338 break;
339 case 3: /* In button */
340 clut = (clut_t*) img_overl->clip_color;
341 trans = img_overl->clip_trans;
342 o = trans[clr];
343 if (x + rle_remainder <= img_overl->clip_right) {
344 rle_this_bite = rle_remainder;
345 rle_remainder = rlelen = rle->len;
346 clr_next = rle->color;
347 rle++;
348 } else {
349 rle_this_bite = img_overl->clip_right - x;
350 rle_remainder -= rle_this_bite;
351 zone_state = 4;
352 }
353 if (o) {
354 x1_scaled = SCALED_TO_INT( x * x_scale );
355 x2_scaled = SCALED_TO_INT( (x + rle_this_bite) * x_scale);
203 mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled); 356 mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled);
204 } 357 }
205 358 x += rle_this_bite;
206 x1_scaled = x2_scaled; 359 if (x >= src_width ) {
207 x += rlelen; 360 x -= src_width;
361 img_pix += img_width;
362 dy += dy_step;
363 if (dy >= INT_TO_SCALED(1)) {
364 dy -= INT_TO_SCALED(1);
365 ++y;
366 while (dy >= INT_TO_SCALED(1)) {
367 rle = rle_img_advance_line(rle, rle_limit, src_width);
368 dy -= INT_TO_SCALED(1);
369 ++y;
370 }
371 rle_start = rle;
372 } else {
373 rle = rle_start; /* y-scaling, reuse the last rle encoded line */
374 }
375 if (y >= img_overl->clip_bottom) {
376 zone_state = 5;
377 break;
378 }
379 }
380 if (rle >= rle_limit) {
381 zone_state = 6;
382 }
383 break;
384 case 4: /* Right of button */
385 clut = (clut_t*) img_overl->color;
386 trans = img_overl->trans;
387 o = trans[clr];
388 if (x + rle_remainder <= src_width) {
389 rle_this_bite = rle_remainder;
390 rle_remainder = rlelen = rle->len;
391 clr_next = rle->color;
208 rle++; 392 rle++;
209 if (rle >= rle_limit) break; 393 } else {
394 rle_this_bite = src_width - x;
395 rle_remainder -= rle_this_bite;
396 zone_state = 2;
210 } 397 }
398 if (o) {
399 x1_scaled = SCALED_TO_INT( x * x_scale );
400 x2_scaled = SCALED_TO_INT( (x + rle_this_bite) * x_scale);
401 mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled);
402 }
403 x += rle_this_bite;
404 if (x >= src_width ) {
405 x -= src_width;
406 img_pix += img_width;
407 dy += dy_step;
408 if (dy >= INT_TO_SCALED(1)) {
409 dy -= INT_TO_SCALED(1);
410 ++y;
411 while (dy >= INT_TO_SCALED(1)) {
412 rle = rle_img_advance_line(rle, rle_limit, src_width);
413 dy -= INT_TO_SCALED(1);
414 ++y;
415 }
416 rle_start = rle;
417 } else {
418 rle = rle_start; /* y-scaling, reuse the last rle encoded line */
419 }
420 if (y >= img_overl->clip_bottom) {
421 zone_state = 5;
422 break;
423 }
424 }
425 if (rle >= rle_limit) {
426 zone_state = 6;
427 }
428 break;
429 case 5: /* Below button */
430 clut = (clut_t*) img_overl->color;
431 trans = img_overl->trans;
432 o = trans[clr];
433 rle_this_bite = rle_remainder;
434 rle_remainder = 0;
435 rlelen -= rle_this_bite;
436 if (o) {
437 x1_scaled = SCALED_TO_INT( x * x_scale );
438 x2_scaled = SCALED_TO_INT( (x + rle_this_bite) * x_scale);
439 mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled);
440 }
441 x += rle_this_bite;
442 if (x >= src_width ) {
443 x -= src_width;
444 img_pix += img_width;
445 dy += dy_step;
446 if (dy >= INT_TO_SCALED(1)) {
447 dy -= INT_TO_SCALED(1);
448 ++y;
449 while (dy >= INT_TO_SCALED(1)) {
450 rle = rle_img_advance_line(rle, rle_limit, src_width);
451 dy -= INT_TO_SCALED(1);
452 ++y;
453 }
454 rle_start = rle;
455 } else {
456 rle = rle_start; /* y-scaling, reuse the last rle encoded line */
457 }
458 }
459 rle_remainder = rlelen = rle->len;
460 clr_next = rle->color;
461 rle++;
462 if (rle >= rle_limit) {
463 zone_state = 6;
464 }
465 break;
466 case 6: /* Finished */
467 _x_abort();
211 468
469 case 7: /* No button */
470 clut = (clut_t*) img_overl->color;
471 trans = img_overl->trans;
472 o = trans[clr];
473 rle_this_bite = rle_remainder;
474 rle_remainder = 0;
475 rlelen -= rle_this_bite;
476 if (o) {
477 x1_scaled = SCALED_TO_INT( x * x_scale );
478 x2_scaled = SCALED_TO_INT( (x + rle_this_bite) * x_scale);
479 mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled);
480 }
481 x += rle_this_bite;
482 if (x >= src_width ) {
483 x -= src_width;
212 img_pix += img_width; 484 img_pix += img_width;
@@ -221,2 +493,3 @@ void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl,
221 } 493 }
494 rle_start = rle;
222 } else { 495 } else {
@@ -225,2 +498,17 @@ void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl,
225 } 498 }
499 rle_remainder = rlelen = rle->len;
500 clr_next = rle->color;
501 rle++;
502 if (rle >= rle_limit) {
503 zone_state = 6;
504 }
505 break;
506 default:
507 ;
508 }
509 }
510#ifdef LOG_BLEND_RGB16
511 printf("blend_rgb16 ended\n");
512#endif
513
226} 514}
@@ -229,6 +517,5 @@ void blend_rgb24 (uint8_t * img, vo_overlay_t * img_overl,
229 int img_width, int img_height, 517 int img_width, int img_height,
230 int dst_width, int dst_height) 518 int dst_width, int dst_height,
519 alphablend_t *extra_data)
231{ 520{
232 clut_t* clut = (clut_t*) img_overl->clip_color;
233 uint8_t *trans;
234 int src_width = img_overl->width; 521 int src_width = img_overl->width;
@@ -248,47 +535,87 @@ void blend_rgb24 (uint8_t * img, vo_overlay_t * img_overl,
248 535
249 trans = img_overl->clip_trans;
250
251 /* avoid wraping overlay if drawing to small image */ 536 /* avoid wraping overlay if drawing to small image */
252 if( (img_overl->x + img_overl->clip_right) < dst_width ) 537 if( (img_overl->x + img_overl->clip_right) <= dst_width )
253 clip_right = img_overl->clip_right; 538 clip_right = img_overl->clip_right;
254 else 539 else
255 clip_right = dst_width - 1 - img_overl->x; 540 clip_right = dst_width - img_overl->x;
256 541
257 /* avoid buffer overflow */ 542 /* avoid buffer overflow */
258 if( (src_height + img_overl->y) >= dst_height ) 543 if( (src_height + img_overl->y) > dst_height )
259 src_height = dst_height - 1 - img_overl->y; 544 src_height = dst_height - img_overl->y;
260 545
261 for (dy = y = 0; y < src_height && rle < rle_limit; ) { 546 for (dy = y = 0; y < src_height && rle < rle_limit; ) {
262 int mask = !(img_overl->clip_top > y || img_overl->clip_bottom < y); 547 int mask = !(y < img_overl->clip_top || y >= img_overl->clip_bottom);
263 rle_elem_t *rle_start = rle; 548 rle_elem_t *rle_start = rle;
264 549
550 int rlelen = 0;
551 uint8_t clr = 0;
552
265 for (x = x1_scaled = 0; x < src_width;) { 553 for (x = x1_scaled = 0; x < src_width;) {
266 uint8_t clr; 554 int rle_bite;
555 clut_t *colors;
556 uint8_t *trans;
267 uint16_t o; 557 uint16_t o;
268 int rlelen;
269 558
270 clr = rle->color; 559 /* take next element from rle list everytime an element is finished */
271 o = trans[clr]; 560 if (rlelen <= 0) {
561 if (rle >= rle_limit)
562 break;
563
272 rlelen = rle->len; 564 rlelen = rle->len;
565 clr = rle->color;
566 rle++;
567 }
273 568
274 if (o && mask) { 569 if (!mask) {
275 /* threat cases where clipping border is inside rle->len pixels */ 570 /* above or below clipping area */
276 if ( img_overl->clip_left > x ) { 571
277 if( img_overl->clip_left < x + rlelen ) { 572 rle_bite = rlelen;
278 x1_scaled = SCALED_TO_INT( img_overl->clip_left * x_scale ); 573 /* choose palette for surrounding area */
279 rlelen -= img_overl->clip_left - x; 574 colors = (clut_t*)img_overl->color;
280 x += img_overl->clip_left - x; 575 trans = img_overl->trans;
281 } else { 576 } else {
282 o = 0; 577 /* treat cases where clipping border is inside rle->len pixels */
283 } 578 if ( x < img_overl->clip_left ) {
284 } else if( clip_right < x + rlelen ) { 579 /* starts left */
285 if( clip_right > x ) { 580 if( x + rlelen > img_overl->clip_left ) {
286 x2_scaled = SCALED_TO_INT( clip_right * x_scale); 581 /* ends not left */
287 mem_blend24(img_pix + x1_scaled*3, clut[clr].cb, 582
288 clut[clr].cr, clut[clr].y, 583 /* choose the largest "bite" up to palette change */
289 o, x2_scaled-x1_scaled); 584 rle_bite = img_overl->clip_left - x;
290 o = 0; 585 /* choose palette for surrounding area */
586 colors = (clut_t*)img_overl->color;
587 trans = img_overl->trans;
588 } else {
589 /* ends left */
590
591 rle_bite = rlelen;
592 /* choose palette for surrounding area */
593 colors = (clut_t*)img_overl->color;
594 trans = img_overl->trans;
595 }
596 } else if( x + rlelen > clip_right ) {
597 /* ends right */
598 if( x < clip_right ) {
599 /* starts not right */
600
601 /* choose the largest "bite" up to palette change */
602 rle_bite = clip_right - x;
603 /* we're in the center area so choose clip palette */
604 colors = (clut_t*)img_overl->clip_color;
605 trans = img_overl->clip_trans;
291 } else { 606 } else {
292 o = 0; 607 /* starts right */
608
609 rle_bite = rlelen;
610 /* choose palette for surrounding area */
611 colors = (clut_t*)img_overl->color;
612 trans = img_overl->trans;
293 } 613 }
614 } else {
615 /* starts not left and ends not right */
616
617 rle_bite = rlelen;
618 /* we're in the center area so choose clip palette */
619 colors = (clut_t*)img_overl->clip_color;
620 trans = img_overl->clip_trans;
294 } 621 }
@@ -296,6 +623,8 @@ void blend_rgb24 (uint8_t * img, vo_overlay_t * img_overl,
296 623
297 x2_scaled = SCALED_TO_INT((x + rlelen) * x_scale); 624 x2_scaled = SCALED_TO_INT((x + rle_bite) * x_scale);
298 if (o && mask) { 625
299 mem_blend24(img_pix + x1_scaled*3, clut[clr].cb, 626 o = trans[clr];
300 clut[clr].cr, clut[clr].y, 627 if (o) {
628 mem_blend24(img_pix + x1_scaled*3,
629 colors[clr].cb, colors[clr].cr, colors[clr].y,
301 o, x2_scaled-x1_scaled); 630 o, x2_scaled-x1_scaled);
@@ -304,5 +633,4 @@ void blend_rgb24 (uint8_t * img, vo_overlay_t * img_overl,
304 x1_scaled = x2_scaled; 633 x1_scaled = x2_scaled;
305 x += rlelen; 634 x += rle_bite;
306 rle++; 635 rlelen -= rle_bite;
307 if (rle >= rle_limit) break;
308 } 636 }
@@ -327,6 +655,5 @@ void blend_rgb32 (uint8_t * img, vo_overlay_t * img_overl,
327 int img_width, int img_height, 655 int img_width, int img_height,
328 int dst_width, int dst_height) 656 int dst_width, int dst_height,
657 alphablend_t *extra_data)
329{ 658{
330 clut_t* clut = (clut_t*) img_overl->clip_color;
331 uint8_t *trans;
332 int src_width = img_overl->width; 659 int src_width = img_overl->width;
@@ -346,47 +673,87 @@ void blend_rgb32 (uint8_t * img, vo_overlay_t * img_overl,
346 673
347 trans = img_overl->clip_trans;
348
349 /* avoid wraping overlay if drawing to small image */ 674 /* avoid wraping overlay if drawing to small image */
350 if( (img_overl->x + img_overl->clip_right) < dst_width ) 675 if( (img_overl->x + img_overl->clip_right) <= dst_width )
351 clip_right = img_overl->clip_right; 676 clip_right = img_overl->clip_right;
352 else 677 else
353 clip_right = dst_width - 1 - img_overl->x; 678 clip_right = dst_width - img_overl->x;
354 679
355 /* avoid buffer overflow */ 680 /* avoid buffer overflow */
356 if( (src_height + img_overl->y) >= dst_height ) 681 if( (src_height + img_overl->y) > dst_height )
357 src_height = dst_height - 1 - img_overl->y; 682 src_height = dst_height - img_overl->y;
358 683
359 for (y = dy = 0; y < src_height && rle < rle_limit; ) { 684 for (y = dy = 0; y < src_height && rle < rle_limit; ) {
360 int mask = !(img_overl->clip_top > y || img_overl->clip_bottom < y); 685 int mask = !(y < img_overl->clip_top || y >= img_overl->clip_bottom);
361 rle_elem_t *rle_start = rle; 686 rle_elem_t *rle_start = rle;
362 687
688 int rlelen = 0;
689 uint8_t clr = 0;
690
363 for (x = x1_scaled = 0; x < src_width;) { 691 for (x = x1_scaled = 0; x < src_width;) {
364 uint8_t clr; 692 int rle_bite;
693 clut_t *colors;
694 uint8_t *trans;
365 uint16_t o; 695 uint16_t o;
366 int rlelen;
367 696
368 clr = rle->color; 697 /* take next element from rle list everytime an element is finished */
369 o = trans[clr]; 698 if (rlelen <= 0) {
699 if (rle >= rle_limit)
700 break;
701
370 rlelen = rle->len; 702 rlelen = rle->len;
703 clr = rle->color;
704 rle++;
705 }
371 706
372 if (o && mask) { 707 if (!mask) {
373 /* threat cases where clipping border is inside rle->len pixels */ 708 /* above or below clipping area */
374 if ( img_overl->clip_left > x ) { 709
375 if( img_overl->clip_left < x + rlelen ) { 710 rle_bite = rlelen;
376 x1_scaled = SCALED_TO_INT( img_overl->clip_left * x_scale ); 711 /* choose palette for surrounding area */
377 rlelen -= img_overl->clip_left - x; 712 colors = (clut_t*)img_overl->color;
378 x += img_overl->clip_left - x; 713 trans = img_overl->trans;
379 } else {
380 o = 0;
381 }
382 } else if( clip_right < x + rlelen ) {
383 if( clip_right > x ) {
384 x2_scaled = SCALED_TO_INT( clip_right * x_scale);
385 mem_blend24_32(img_pix + x1_scaled*4, clut[clr].cb,
386 clut[clr].cr, clut[clr].y,
387 o, x2_scaled-x1_scaled);
388 o = 0;
389 } else { 714 } else {
390 o = 0; 715 /* treat cases where clipping border is inside rle->len pixels */
716 if ( x < img_overl->clip_left ) {
717 /* starts left */
718 if( x + rlelen > img_overl->clip_left ) {
719 /* ends not left */
720
721 /* choose the largest "bite" up to palette change */
722 rle_bite = img_overl->clip_left - x;
723 /* choose palette for surrounding area */
724 colors = (clut_t*)img_overl->color;
725 trans = img_overl->trans;
726 } else {
727 /* ends left */
728
729 rle_bite = rlelen;
730 /* choose palette for surrounding area */
731 colors = (clut_t*)img_overl->color;
732 trans = img_overl->trans;
733 }
734 } else if( x + rlelen > clip_right ) {
735 /* ends right */
736 if( x < clip_right ) {
737 /* starts not right */
738
739 /* choose the largest "bite" up to palette change */
740 rle_bite = clip_right - x;
741 /* we're in the center area so choose clip palette */
742 colors = (clut_t*)img_overl->clip_color;
743 trans = img_overl->clip_trans;
744 } else {
745 /* starts right */
746
747 rle_bite = rlelen;
748 /* choose palette for surrounding area */
749 colors = (clut_t*)img_overl->color;
750 trans = img_overl->trans;
391 } 751 }
752 } else {
753 /* starts not left and ends not right */
754
755 rle_bite = rlelen;
756 /* we're in the center area so choose clip palette */
757 colors = (clut_t*)img_overl->clip_color;
758 trans = img_overl->clip_trans;
392 } 759 }
@@ -394,7 +761,7 @@ void blend_rgb32 (uint8_t * img, vo_overlay_t * img_overl,
394 761
395 x2_scaled = SCALED_TO_INT((x + rlelen) * x_scale); 762 x2_scaled = SCALED_TO_INT((x + rle_bite) * x_scale);
396 if (o && mask) { 763
397 mem_blend24_32(img_pix + x1_scaled*4, clut[clr].cb, 764 o = trans[clr];
398 clut[clr].cr, clut[clr].y, 765 if (o) {
399 o, x2_scaled-x1_scaled); 766 mem_blend32(img_pix + x1_scaled*4, (uint8_t *)&colors[clr], o, x2_scaled-x1_scaled);
400 } 767 }
@@ -402,5 +769,4 @@ void blend_rgb32 (uint8_t * img, vo_overlay_t * img_overl,
402 x1_scaled = x2_scaled; 769 x1_scaled = x2_scaled;
403 x += rlelen; 770 x += rle_bite;
404 rle++; 771 rlelen -= rle_bite;
405 if (rle >= rle_limit) break;
406 } 772 }
@@ -432,5 +798,105 @@ static void mem_blend8(uint8_t *mem, uint8_t val, uint8_t o, size_t sz)
432 798
799static void blend_yuv_exact(uint8_t *dst_cr, uint8_t *dst_cb,
800 int src_width, int x_odd,
801 uint8_t *(*blend_yuv_data)[ 3 ][ 2 ])
802{
803 int x;
804
805 for (x = 0; x < src_width; x += 2) {
806 /* get opacity of the 4 pixels that share chroma */
807 int o00 = (*blend_yuv_data)[ 0 ][ 0 ][ x + 0 ];
808 int o01 = (*blend_yuv_data)[ 0 ][ 0 ][ x + 1 ];
809 int o10 = (*blend_yuv_data)[ 0 ][ 1 ][ x + 0 ];
810 int o11 = (*blend_yuv_data)[ 0 ][ 1 ][ x + 1 ];
811
812 /* are there any pixels a little bit opaque? */
813 if (o00 || o01 || o10 || o11) {
814 /* get the chroma components of the 4 pixels */
815 int cr00 = -128 + (*blend_yuv_data)[ 1 ][ 0 ][ x + 0 ];
816 int cr01 = -128 + (*blend_yuv_data)[ 1 ][ 0 ][ x + 1 ];
817 int cr10 = -128 + (*blend_yuv_data)[ 1 ][ 1 ][ x + 0 ];
818 int cr11 = -128 + (*blend_yuv_data)[ 1 ][ 1 ][ x + 1 ];
819
820 int cb00 = -128 + (*blend_yuv_data)[ 2 ][ 0 ][ x + 0 ];
821 int cb01 = -128 + (*blend_yuv_data)[ 2 ][ 0 ][ x + 1 ];
822 int cb10 = -128 + (*blend_yuv_data)[ 2 ][ 1 ][ x + 0 ];
823 int cb11 = -128 + (*blend_yuv_data)[ 2 ][ 1 ][ x + 1 ];
824
825 /* are all pixels completely opaque? */
826 if (o00 >= 0xf && o01 >= 0xf && o10 >= 0xf && o11 >= 0xf) {
827 /* set the output chroma to the average of the four pixels */
828 *dst_cr = 128 + (cr00 + cr01 + cr10 + cr11) / 4;
829 *dst_cb = 128 + (cb00 + cb01 + cb10 + cb11) / 4;
830 } else {
831 int t4, cr, cb;
832
833 /* blending required, so clamp opacity values to allowed range */
834 if (o00 > 0xf) o00 = 0xf;
835 if (o01 > 0xf) o01 = 0xf;
836 if (o10 > 0xf) o10 = 0xf;
837 if (o11 > 0xf) o11 = 0xf;
838
839 /* calculate transparency of background over the four pixels */
840 t4 = (0xf - o00) + (0xf - o01) + (0xf - o10) + (0xf - o11);
841
842 /* get background chroma */
843 cr = -128 + *dst_cr;
844 cb = -128 + *dst_cb;
845
846 /* blend the output chroma to the average of the four pixels */
847 *dst_cr = 128 + (cr * t4 + cr00 * o00 + cr01 * o01 + cr10 * o10 + cr11 * o11) / (4 * 0xf);
848 *dst_cb = 128 + (cb * t4 + cb00 * o00 + cb01 * o01 + cb10 * o10 + cb11 * o11) / (4 * 0xf);
849 }
850 }
851
852 /* next chroma sample */
853 dst_cr++;
854 dst_cb++;
855 }
856}
857
858static uint8_t *(*blend_yuv_grow_extra_data(alphablend_t *extra_data, int osd_width))[ 3 ][ 2 ]
859{
860 struct __attribute__((packed)) header_s {
861 int id;
862 int max_width;
863 uint8_t *data[ 3 ][ 2 ];
864 } **header = (struct header_s **)&extra_data->buffer;
865
866 int needed_buffer_size = sizeof (**header) + sizeof (uint8_t[ 3 ][ 2 ][ osd_width ]);
867
868 if (extra_data->buffer_size < needed_buffer_size) {
869
870 free(extra_data->buffer);
871 extra_data->buffer = xine_xmalloc(needed_buffer_size);
872
873 if (!extra_data->buffer) {
874 extra_data->buffer_size = 0;
875 return 0;
876 }
877
878 extra_data->buffer_size = needed_buffer_size;
879 (*header)->max_width = 0;
880 }
881
882 if ((*header)->id != ME_FOURCC('y', 'u', 'v', 0) || (*header)->max_width < osd_width) {
883 (*header)->id = ME_FOURCC('y', 'u', 'v', 0);
884 (*header)->max_width = osd_width;
885
886 (*header)->data[ 0 ][ 0 ] = ((uint8_t *)extra_data->buffer) + sizeof (**header);
887 (*header)->data[ 0 ][ 1 ] = (*header)->data[ 0 ][ 0 ] + osd_width;
888 (*header)->data[ 1 ][ 0 ] = (*header)->data[ 0 ][ 1 ] + osd_width;
889 (*header)->data[ 1 ][ 1 ] = (*header)->data[ 1 ][ 0 ] + osd_width;
890 (*header)->data[ 2 ][ 0 ] = (*header)->data[ 1 ][ 1 ] + osd_width;
891 (*header)->data[ 2 ][ 1 ] = (*header)->data[ 2 ][ 0 ] + osd_width;
892 }
893
894 return &(*header)->data;
895}
896
433void blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl, 897void blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl,
434 int dst_width, int dst_height) 898 int dst_width, int dst_height, int dst_pitches[3],
899 alphablend_t *extra_data)
435{ 900{
901 int enable_exact_blending = !extra_data->disable_exact_blending;
436 clut_t *my_clut; 902 clut_t *my_clut;
@@ -444,2 +910,4 @@ void blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl,
444 int y_off = img_overl->y; 910 int y_off = img_overl->y;
911 int x_odd = x_off & 1;
912 int y_odd = y_off & 1;
445 int ymask,xmask; 913 int ymask,xmask;
@@ -452,7 +920,10 @@ void blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl,
452 920
453 uint8_t *dst_y = dst_base[0] + dst_width * y_off + x_off; 921 int any_line_buffered = 0;
454 uint8_t *dst_cr = dst_base[2] + 922 int exact_blend_width = ((src_width <= (dst_width - x_off)) ? src_width : (dst_width - x_off));
455 (y_off / 2) * (dst_width / 2) + (x_off / 2) + 1; 923 int exact_blend_width_m2 = (x_odd + exact_blend_width + 1) & ~1; /* make it a (larger) multiple of 2 */
456 uint8_t *dst_cb = dst_base[1] + 924 uint8_t *(*blend_yuv_data)[ 3 ][ 2 ] = 0;
457 (y_off / 2) * (dst_width / 2) + (x_off / 2) + 1; 925
926 uint8_t *dst_y = dst_base[0] + dst_pitches[0] * y_off + x_off;
927 uint8_t *dst_cr = dst_base[2] + (y_off / 2) * dst_pitches[1] + (x_off / 2);
928 uint8_t *dst_cb = dst_base[1] + (y_off / 2) * dst_pitches[2] + (x_off / 2);
458#ifdef LOG_BLEND_YUV 929#ifdef LOG_BLEND_YUV
@@ -464,10 +935,26 @@ void blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl,
464 /* avoid wraping overlay if drawing to small image */ 935 /* avoid wraping overlay if drawing to small image */
465 if( (x_off + img_overl->clip_right) < dst_width ) 936 if( (x_off + img_overl->clip_right) <= dst_width )
466 clip_right = img_overl->clip_right; 937 clip_right = img_overl->clip_right;
467 else 938 else
468 clip_right = dst_width - 1 - x_off; 939 clip_right = dst_width - x_off;
469 940
470 /* avoid buffer overflow */ 941 /* avoid buffer overflow */
471 if( (src_height + y_off) >= dst_height ) 942 if( (src_height + y_off) > dst_height )
472 src_height = dst_height - 1 - y_off; 943 src_height = dst_height - y_off;
944
945 if (src_height <= 0)
946 return;
947
948 if (enable_exact_blending) {
949 if (exact_blend_width <= 0)
950 return;
951
952 blend_yuv_data = blend_yuv_grow_extra_data(extra_data, exact_blend_width_m2);
953 if (!blend_yuv_data)
954 return;
955
956 /* make linebuffer transparent */
957 memset(&(*blend_yuv_data)[ 0 ][ 0 ][ 0 ], 0, exact_blend_width_m2);
958 memset(&(*blend_yuv_data)[ 0 ][ 1 ][ 0 ], 0, exact_blend_width_m2);
959 }
473 960
@@ -475,3 +962,10 @@ void blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl,
475 for (y = 0; y < src_height; y++) { 962 for (y = 0; y < src_height; y++) {
476 ymask = ((img_overl->clip_top > y) || (img_overl->clip_bottom < y)); 963 if (rle >= rle_limit) {
964#ifdef LOG_BLEND_YUV
965 printf("y-rle_limit\n");
966#endif
967 break;
968 }
969
970 ymask = ((y < img_overl->clip_top) || (y >= img_overl->clip_bottom));
477 xmask = 0; 971 xmask = 0;
@@ -483,2 +977,10 @@ void blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl,
483 uint16_t o; 977 uint16_t o;
978
979 if (rle >= rle_limit) {
980#ifdef LOG_BLEND_YUV
981 printf("x-rle_limit\n");
982#endif
983 break;
984 }
985
484#ifdef LOG_BLEND_YUV 986#ifdef LOG_BLEND_YUV
@@ -488,3 +990,5 @@ void blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl,
488 if ((rlelen < 0) || (rle_remainder < 0)) { 990 if ((rlelen < 0) || (rle_remainder < 0)) {
991#ifdef LOG_BLEND_YUV
489 printf("alphablend: major bug in blend_yuv < 0\n"); 992 printf("alphablend: major bug in blend_yuv < 0\n");
993#endif
490 } 994 }
@@ -501,3 +1005,2 @@ void blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl,
501 rle_remainder = src_width - x; 1005 rle_remainder = src_width - x;
502 ;
503 } 1006 }
@@ -508,5 +1011,5 @@ void blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl,
508 if (ymask == 0) { 1011 if (ymask == 0) {
509 if (x <= img_overl->clip_left) { 1012 if (x < img_overl->clip_left) {
510 /* Starts outside clip area */ 1013 /* Starts outside clip area */
511 if ((x + rle_remainder - 1) > img_overl->clip_left ) { 1014 if ((x + rle_remainder) > img_overl->clip_left ) {
512#ifdef LOG_BLEND_YUV 1015#ifdef LOG_BLEND_YUV
@@ -515,3 +1018,3 @@ void blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl,
515 /* Cutting needed, starts outside, ends inside */ 1018 /* Cutting needed, starts outside, ends inside */
516 rle_this_bite = (img_overl->clip_left - x + 1); 1019 rle_this_bite = (img_overl->clip_left - x);
517 rle_remainder -= rle_this_bite; 1020 rle_remainder -= rle_this_bite;
@@ -559,3 +1062,3 @@ void blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl,
559 } else if (x >= clip_right) { 1062 } else if (x >= clip_right) {
560 /* Starts outside clip area, ends outsite clip area */ 1063 /* Starts outside clip area, ends outside clip area */
561 if ((x + rle_remainder ) > src_width ) { 1064 if ((x + rle_remainder ) > src_width ) {
@@ -599,2 +1102,19 @@ void blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl,
599#endif 1102#endif
1103
1104 if (x < (dst_width - x_off)) {
1105 /* clip against right edge of destination area */
1106 if ((x + rle_this_bite) > (dst_width - x_off)) {
1107 int toClip = (x + rle_this_bite) - (dst_width - x_off);
1108
1109 rle_this_bite -= toClip;
1110 rle_remainder += toClip;
1111 rlelen += toClip;
1112 }
1113
1114 if (enable_exact_blending) {
1115 /* remember opacity of current line */
1116 memset(&(*blend_yuv_data)[ 0 ][ (y + y_odd) & 1 ][ x + x_odd ], o, rle_this_bite);
1117 any_line_buffered |= ((y + y_odd) & 1) ? 2 : 1;
1118 }
1119
600 if (o) { 1120 if (o) {
@@ -602,5 +1122,7 @@ void blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl,
602 memset(dst_y + x, my_clut[clr].y, rle_this_bite); 1122 memset(dst_y + x, my_clut[clr].y, rle_this_bite);
603 if (y & 1) { 1123 if (!enable_exact_blending) {
604 memset(dst_cr + (x >> 1), my_clut[clr].cr, (rle_this_bite+1) >> 1); 1124 if ((y + y_odd) & 1) {
605 memset(dst_cb + (x >> 1), my_clut[clr].cb, (rle_this_bite+1) >> 1); 1125 memset(dst_cr + ((x + x_odd) >> 1), my_clut[clr].cr, (rle_this_bite+1) >> 1);
1126 memset(dst_cb + ((x + x_odd) >> 1), my_clut[clr].cb, (rle_this_bite+1) >> 1);
1127 }
606 } 1128 }
@@ -608,6 +1130,8 @@ void blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl,
608 mem_blend8(dst_y + x, my_clut[clr].y, o, rle_this_bite); 1130 mem_blend8(dst_y + x, my_clut[clr].y, o, rle_this_bite);
609 if (y & 1) { 1131 if (!enable_exact_blending) {
1132 if ((y + y_odd) & 1) {
610 /* Blending cr and cb should use a different function, with pre -128 to each sample */ 1133 /* Blending cr and cb should use a different function, with pre -128 to each sample */
611 mem_blend8(dst_cr + (x >> 1), my_clut[clr].cr, o, (rle_this_bite+1) >> 1); 1134 mem_blend8(dst_cr + ((x + x_odd) >> 1), my_clut[clr].cr, o, (rle_this_bite+1) >> 1);
612 mem_blend8(dst_cb + (x >> 1), my_clut[clr].cb, o, (rle_this_bite+1) >> 1); 1135 mem_blend8(dst_cb + ((x + x_odd) >> 1), my_clut[clr].cb, o, (rle_this_bite+1) >> 1);
1136 }
613 } 1137 }
@@ -615,2 +1139,8 @@ void blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl,
615 1139
1140 if (enable_exact_blending) {
1141 /* remember chroma of current line */
1142 memset(&(*blend_yuv_data)[ 1 ][ (y + y_odd) & 1 ][ x + x_odd ], my_clut[ clr ].cr, rle_this_bite);
1143 memset(&(*blend_yuv_data)[ 2 ][ (y + y_odd) & 1 ][ x + x_odd ], my_clut[ clr ].cb, rle_this_bite);
1144 }
1145 }
616 } 1146 }
@@ -620,23 +1150,38 @@ void blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl,
620 x += rle_this_bite; 1150 x += rle_this_bite;
621 if (rle >= rle_limit) {
622#ifdef LOG_BLEND_YUV
623 printf("x-rle_limit\n");
624#endif
625 break;
626 } 1151 }
1152
1153 if ((y + y_odd) & 1) {
1154 if (enable_exact_blending) {
1155 /* blend buffered lines */
1156 if (any_line_buffered) {
1157 if (!(any_line_buffered & 2)) {
1158 /* make second line transparent */
1159 memset(&(*blend_yuv_data)[ 0 ][ 1 ][ 0 ], 0, exact_blend_width_m2);
1160 }
1161
1162 blend_yuv_exact(dst_cr, dst_cb, exact_blend_width, x_odd, blend_yuv_data);
1163
1164 any_line_buffered = 0;
627 } 1165 }
628 if (rle >= rle_limit) {
629#ifdef LOG_BLEND_YUV
630 printf("x-rle_limit\n");
631#endif
632 break;
633 } 1166 }
634 1167
635 dst_y += dst_width; 1168 dst_cr += dst_pitches[2];
1169 dst_cb += dst_pitches[1];
1170 }
636 1171
637 if (y & 1) { 1172 dst_y += dst_pitches[0];
638 dst_cr += (dst_width + 1) / 2;
639 dst_cb += (dst_width + 1) / 2;
640 } 1173 }
1174
1175 if (enable_exact_blending) {
1176 /* blend buffered lines */
1177 if (any_line_buffered) {
1178 if (!(any_line_buffered & 2)) {
1179 /* make second line transparent */
1180 memset(&(*blend_yuv_data)[ 0 ][ 1 ][ 0 ], 0, exact_blend_width_m2);
641 } 1181 }
1182
1183 blend_yuv_exact(dst_cr, dst_cb, exact_blend_width, x_odd, blend_yuv_data);
1184 }
1185 }
1186
642#ifdef LOG_BLEND_YUV 1187#ifdef LOG_BLEND_YUV
@@ -646,5 +1191,94 @@ void blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl,
646 1191
1192static void blend_yuy2_exact(uint8_t *dst_cr, uint8_t *dst_cb,
1193 int src_width, int x_odd,
1194 uint8_t *(*blend_yuy2_data)[ 3 ])
1195{
1196 int x;
1197
1198 for (x = 0; x < src_width; x += 2) {
1199 /* get opacity of the 2 pixels that share chroma */
1200 int o0 = (*blend_yuy2_data)[ 0 ][ x + 0 ];
1201 int o1 = (*blend_yuy2_data)[ 0 ][ x + 1 ];
1202
1203 /* are there any pixels a little bit opaque? */
1204 if (o0 || o1) {
1205 /* get the chroma components of the 2 pixels */
1206 int cr0 = -128 + (*blend_yuy2_data)[ 1 ][ x + 0 ];
1207 int cr1 = -128 + (*blend_yuy2_data)[ 1 ][ x + 1 ];
1208
1209 int cb0 = -128 + (*blend_yuy2_data)[ 2 ][ x + 0 ];
1210 int cb1 = -128 + (*blend_yuy2_data)[ 2 ][ x + 1 ];
1211
1212 /* are all pixels completely opaque? */
1213 if (o0 >= 0xf && o1 >= 0xf) {
1214 /* set the output chroma to the average of the two pixels */
1215 *dst_cr = 128 + (cr0 + cr1) / 2;
1216 *dst_cb = 128 + (cb0 + cb1) / 2;
1217 } else {
1218 int t2, cr, cb;
1219
1220 /* blending required, so clamp opacity values to allowed range */
1221 if (o0 > 0xf) o0 = 0xf;
1222 if (o1 > 0xf) o1 = 0xf;
1223
1224 /* calculate transparency of background over the two pixels */
1225 t2 = (0xf - o0) + (0xf - o1);
1226
1227 /* get background chroma */
1228 cr = -128 + *dst_cr;
1229 cb = -128 + *dst_cb;
1230
1231 /* blend the output chroma to the average of the two pixels */
1232 *dst_cr = 128 + (cr * t2 + cr0 * o0 + cr1 * o1) / (2 * 0xf);
1233 *dst_cb = 128 + (cb * t2 + cb0 * o0 + cb1 * o1) / (2 * 0xf);
1234 }
1235 }
1236
1237 /* next chroma sample */
1238 dst_cr += 4;
1239 dst_cb += 4;
1240 }
1241}
1242
1243static uint8_t *(*blend_yuy2_grow_extra_data(alphablend_t *extra_data, int osd_width))[ 3 ]
1244{
1245 struct __attribute__((packed)) header_s {
1246 int id;
1247 int max_width;
1248 uint8_t *data[ 3 ];
1249 } **header = (struct header_s **)&extra_data->buffer;
1250
1251 int needed_buffer_size = sizeof (**header) + sizeof (uint8_t[ 3 ][ osd_width ]);
1252
1253 if (extra_data->buffer_size < needed_buffer_size) {
1254
1255 free(extra_data->buffer);
1256 extra_data->buffer = xine_xmalloc(needed_buffer_size);
1257
1258 if (!extra_data->buffer) {
1259 extra_data->buffer_size = 0;
1260 return 0;
1261 }
1262
1263 extra_data->buffer_size = needed_buffer_size;
1264 (*header)->max_width = 0;
1265 }
1266
1267 if ((*header)->id != ME_FOURCC('y', 'u', 'y', '2') || (*header)->max_width < osd_width) {
1268 (*header)->id = ME_FOURCC('y', 'u', 'y', '2');
1269 (*header)->max_width = osd_width;
1270
1271 (*header)->data[ 0 ] = ((uint8_t *)extra_data->buffer) + sizeof (**header);
1272 (*header)->data[ 1 ] = (*header)->data[ 0 ] + osd_width;
1273 (*header)->data[ 2 ] = (*header)->data[ 1 ] + osd_width;
1274 }
1275
1276 return &(*header)->data;
1277}
1278
647void blend_yuy2 (uint8_t * dst_img, vo_overlay_t * img_overl, 1279void blend_yuy2 (uint8_t * dst_img, vo_overlay_t * img_overl,
648 int dst_width, int dst_height) 1280 int dst_width, int dst_height, int dst_pitch,
1281 alphablend_t *extra_data)
649{ 1282{
1283 int enable_exact_blending = !extra_data->disable_exact_blending;
650 clut_t *my_clut; 1284 clut_t *my_clut;
@@ -658,9 +1292,25 @@ void blend_yuy2 (uint8_t * dst_img, vo_overlay_t * img_overl,
658 int y_off = img_overl->y; 1292 int y_off = img_overl->y;
659 int mask; 1293 int x_odd = x_off & 1;
1294 int ymask;
1295 int rle_this_bite;
1296 int rle_remainder;
1297 int rlelen;
660 int x, y; 1298 int x, y;
661 int l; 1299 int l = 0;
662 int clip_right; 1300 int clip_right;
663 uint32_t yuy2;
664 1301
665 uint8_t *dst_y = dst_img + 2 * (dst_width * y_off + x_off); 1302 union {
1303 uint32_t value;
1304 uint8_t b[4];
1305 uint16_t h[2];
1306 } yuy2;
1307
1308 uint8_t clr = 0;
1309
1310 int any_line_buffered = 0;
1311 int exact_blend_width = ((src_width <= (dst_width - x_off)) ? src_width : (dst_width - x_off));
1312 int exact_blend_width_m2 = (x_odd + exact_blend_width + 1) & ~1; /* make it a (larger) multiple of 2 */
1313 uint8_t *(*blend_yuy2_data)[ 3 ] = 0;
1314
1315 uint8_t *dst_y = dst_img + dst_pitch * y_off + 2 * x_off;
666 uint8_t *dst; 1316 uint8_t *dst;
@@ -671,13 +1321,32 @@ void blend_yuy2 (uint8_t * dst_img, vo_overlay_t * img_overl,
671 /* avoid wraping overlay if drawing to small image */ 1321 /* avoid wraping overlay if drawing to small image */
672 if( (x_off + img_overl->clip_right) < dst_width ) 1322 if( (x_off + img_overl->clip_right) <= dst_width )
673 clip_right = img_overl->clip_right; 1323 clip_right = img_overl->clip_right;
674 else 1324 else
675 clip_right = dst_width - 1 - x_off; 1325 clip_right = dst_width - x_off;
676 1326
677 /* avoid buffer overflow */ 1327 /* avoid buffer overflow */
678 if( (src_height + y_off) >= dst_height ) 1328 if( (src_height + y_off) > dst_height )
679 src_height = dst_height - 1 - y_off; 1329 src_height = dst_height - y_off;
1330
1331 if (src_height <= 0)
1332 return;
1333
1334 if (enable_exact_blending) {
1335 if (exact_blend_width <= 0)
1336 return;
680 1337
1338 blend_yuy2_data = blend_yuy2_grow_extra_data(extra_data, exact_blend_width_m2);
1339 if (!blend_yuy2_data)
1340 return;
1341
1342 /* make linebuffer transparent */
1343 memset(&(*blend_yuy2_data)[ 0 ][ 0 ], 0, exact_blend_width_m2);
1344 }
1345
1346 rlelen=rle_remainder=0;
681 for (y = 0; y < src_height; y++) { 1347 for (y = 0; y < src_height; y++) {
682 mask = !(img_overl->clip_top > y || img_overl->clip_bottom < y); 1348 if (rle >= rle_limit)
1349 break;
1350
1351 ymask = ((y < img_overl->clip_top) || (y >= img_overl->clip_bottom));
683 1352
@@ -685,49 +1354,165 @@ void blend_yuy2 (uint8_t * dst_img, vo_overlay_t * img_overl,
685 for (x = 0; x < src_width;) { 1354 for (x = 0; x < src_width;) {
686 uint8_t clr;
687 uint16_t o; 1355 uint16_t o;
688 int rlelen;
689 1356
1357 if (rle >= rle_limit)
1358 break;
1359
1360 if ((rlelen < 0) || (rle_remainder < 0)) {
1361#ifdef LOG_BLEND_YUV
1362 printf("alphablend: major bug in blend_yuv < 0\n");
1363#endif
1364 }
1365 if (rlelen == 0) {
1366 rle_remainder = rlelen = rle->len;
690 clr = rle->color; 1367 clr = rle->color;
691 o = my_trans[clr]; 1368 rle++;
692 rlelen = rle->len; 1369 }
1370 if (rle_remainder == 0) {
1371 rle_remainder = rlelen;
1372 }
1373 if ((rle_remainder + x) > src_width) {
1374 /* Do something for long rlelengths */
1375 rle_remainder = src_width - x;
1376 }
1377#ifdef LOG_BLEND_YUV
1378 printf("2:rle_len=%d, remainder=%d, x=%d\n",rlelen, rle_remainder, x);
1379#endif
693 1380
694 if (o && mask) { 1381 if (ymask == 0) {
695 /* threat cases where clipping border is inside rle->len pixels */ 1382 if (x < img_overl->clip_left) {
696 if ( img_overl->clip_left > x ) { 1383 /* Starts outside clip area */
697 if( img_overl->clip_left < x + rlelen ) { 1384 if ((x + rle_remainder) > img_overl->clip_left ) {
698 rlelen -= img_overl->clip_left - x; 1385#ifdef LOG_BLEND_YUV
699 x += img_overl->clip_left - x; 1386 printf("Outside clip left %d, ending inside\n", img_overl->clip_left);
1387#endif
1388 /* Cutting needed, starts outside, ends inside */
1389 rle_this_bite = (img_overl->clip_left - x);
1390 rle_remainder -= rle_this_bite;
1391 rlelen -= rle_this_bite;
1392 my_clut = (clut_t*) img_overl->color;
1393 my_trans = img_overl->trans;
1394 } else {
1395#ifdef LOG_BLEND_YUV
1396 printf("Outside clip left %d, ending outside\n", img_overl->clip_left);
1397#endif
1398 /* no cutting needed, starts outside, ends outside */
1399 rle_this_bite = rle_remainder;
1400 rle_remainder = 0;
1401 rlelen -= rle_this_bite;
1402 my_clut = (clut_t*) img_overl->color;
1403 my_trans = img_overl->trans;
1404 }
1405 } else if (x < clip_right) {
1406 /* Starts inside clip area */
1407 if ((x + rle_remainder) > clip_right ) {
1408#ifdef LOG_BLEND_YUV
1409 printf("Inside clip right %d, ending outside\n", clip_right);
1410#endif
1411 /* Cutting needed, starts inside, ends outside */
1412 rle_this_bite = (clip_right - x);
1413 rle_remainder -= rle_this_bite;
1414 rlelen -= rle_this_bite;
1415 my_clut = (clut_t*) img_overl->clip_color;
1416 my_trans = img_overl->clip_trans;
700 } else { 1417 } else {
701 o = 0; 1418#ifdef LOG_BLEND_YUV
1419 printf("Inside clip right %d, ending inside\n", clip_right);
1420#endif
1421 /* no cutting needed, starts inside, ends inside */
1422 rle_this_bite = rle_remainder;
1423 rle_remainder = 0;
1424 rlelen -= rle_this_bite;
1425 my_clut = (clut_t*) img_overl->clip_color;
1426 my_trans = img_overl->clip_trans;
702 } 1427 }
703 } else if( clip_right < x + rlelen ) { 1428 } else if (x >= clip_right) {
704 if( clip_right > x ) { 1429 /* Starts outside clip area, ends outsite clip area */
705 /* fixme: case not implemented */ 1430 if ((x + rle_remainder ) > src_width ) {
706 o = 0; 1431#ifdef LOG_BLEND_YUV
1432 printf("Outside clip right %d, ending eol\n", clip_right);
1433#endif
1434 /* Cutting needed, starts outside, ends at right edge */
1435 /* It should never reach here due to the earlier test of src_width */
1436 rle_this_bite = (src_width - x );
1437 rle_remainder -= rle_this_bite;
1438 rlelen -= rle_this_bite;
1439 my_clut = (clut_t*) img_overl->color;
1440 my_trans = img_overl->trans;
707 } else { 1441 } else {
708 o = 0; 1442 /* no cutting needed, starts outside, ends outside */
1443#ifdef LOG_BLEND_YUV
1444 printf("Outside clip right %d, ending outside\n", clip_right);
1445#endif
1446 rle_this_bite = rle_remainder;
1447 rle_remainder = 0;
1448 rlelen -= rle_this_bite;
1449 my_clut = (clut_t*) img_overl->color;
1450 my_trans = img_overl->trans;
1451 }
709 } 1452 }
1453 } else {
1454 /* Outside clip are due to y */
1455 /* no cutting needed, starts outside, ends outside */
1456 rle_this_bite = rle_remainder;
1457 rle_remainder = 0;
1458 rlelen -= rle_this_bite;
1459 my_clut = (clut_t*) img_overl->color;
1460 my_trans = img_overl->trans;
710 } 1461 }
1462 o = my_trans[clr];
1463
1464 if (x < (dst_width - x_off)) {
1465 /* clip against right edge of destination area */
1466 if ((x + rle_this_bite) > (dst_width - x_off)) {
1467 int toClip = (x + rle_this_bite) - (dst_width - x_off);
1468
1469 rle_this_bite -= toClip;
1470 rle_remainder += toClip;
1471 rlelen += toClip;
711 } 1472 }
712 1473
1474 if (enable_exact_blending) {
1475 /* remember opacity of current line */
1476 memset(&(*blend_yuy2_data)[ 0 ][ x + x_odd ], o, rle_this_bite);
1477 any_line_buffered = 1;
1478 }
713 1479
714 if (o && mask) { 1480 if (o) {
715 l = rlelen>>1; 1481 if (!enable_exact_blending) {
716 if( !(x & 1) ) { 1482 l = rle_this_bite>>1;
717 yuy2 = my_clut[clr].y + (my_clut[clr].cb << 8) + 1483 if( !((x_odd+x) & 1) ) {
718 (my_clut[clr].y << 16) + (my_clut[clr].cr << 24); 1484 yuy2.b[0] = my_clut[clr].y;
1485 yuy2.b[1] = my_clut[clr].cb;
1486 yuy2.b[2] = my_clut[clr].y;
1487 yuy2.b[3] = my_clut[clr].cr;
719 } else { 1488 } else {
720 yuy2 = my_clut[clr].y + (my_clut[clr].cr << 8) + 1489 yuy2.b[0] = my_clut[clr].y;
721 (my_clut[clr].y << 16) + (my_clut[clr].cb << 24); 1490 yuy2.b[1] = my_clut[clr].cr;
1491 yuy2.b[2] = my_clut[clr].y;
1492 yuy2.b[3] = my_clut[clr].cb;
1493 }
722 } 1494 }
723
724 if (o >= 15) { 1495 if (o >= 15) {
1496 if (!enable_exact_blending) {
725 while(l--) { 1497 while(l--) {
726 *((uint32_t *)dst)++ = yuy2; 1498 *(uint16_t *)dst = yuy2.h[0];
1499 dst += 2;
1500 *(uint16_t *)dst = yuy2.h[1];
1501 dst += 2;
1502 }
1503 if(rle_this_bite & 1) {
1504 *(uint16_t *)dst = yuy2.h[0];
1505 dst += 2;
727 } 1506 }
728 if(rlelen & 1)
729 *((uint16_t *)dst)++ = yuy2 & 0xffff;
730 } else { 1507 } else {
1508 l = rle_this_bite;
1509 while (l--) {
1510 *dst = my_clut[clr].y;
1511 dst += 2;
1512 }
1513 }
1514 } else {
1515 if (!enable_exact_blending) {
731 if( l ) { 1516 if( l ) {
732 mem_blend32(dst, (uint8_t *)&yuy2, o, l); 1517 mem_blend32(dst, &yuy2.b[0], o, l);
733 dst += 4*l; 1518 dst += 4*l;
@@ -735,14 +1520,224 @@ void blend_yuy2 (uint8_t * dst_img, vo_overlay_t * img_overl,
735 1520
736 if(rlelen & 1) { 1521 if(rle_this_bite & 1) {
737 *dst = BLEND_BYTE(*dst, *((uint8_t *)&yuy2), o); 1522 *dst = BLEND_BYTE(*dst, yuy2.b[0], o);
738 dst++; 1523 dst++;
739 *dst = BLEND_BYTE(*dst, *((uint8_t *)&yuy2+1), o); 1524 *dst = BLEND_BYTE(*dst, yuy2.b[1], o);
740 dst++; 1525 dst++;
741 } 1526 }
1527 } else {
1528 l = rle_this_bite;
1529 while (l--) {
1530 *dst = BLEND_BYTE(*dst, my_clut[clr].y, o);
1531 dst += 2;
1532 }
1533 }
1534 }
1535
1536 if (enable_exact_blending) {
1537 /* remember chroma of current line */
1538 memset(&(*blend_yuy2_data)[ 1 ][ x + x_odd ], my_clut[ clr ].cr, rle_this_bite);
1539 memset(&(*blend_yuy2_data)[ 2 ][ x + x_odd ], my_clut[ clr ].cb, rle_this_bite);
742 } 1540 }
743 } else { 1541 } else {
744 dst += rlelen*2; 1542 dst += rle_this_bite*2;
1543 }
1544 }
1545
1546 x += rle_this_bite;
1547 }
1548
1549 if (enable_exact_blending) {
1550 /* blend buffered line */
1551 if (any_line_buffered) {
1552 blend_yuy2_exact(dst_y - x_odd * 2 + 3, dst_y - x_odd * 2 + 1, exact_blend_width, x_odd, blend_yuy2_data);
1553
1554 any_line_buffered = 0;
1555 }
1556 }
1557
1558 dst_y += dst_pitch;
1559 }
1560}
1561
1562void clear_xx44_palette(xx44_palette_t *p)
1563{
1564 register int i;
1565 register uint32_t *cluts = p->cluts;
1566 register int *ids = p->lookup_cache;
1567
1568 i= p->size;
1569 while(i--)
1570 *cluts++ = 0;
1571 i = 2*OVL_PALETTE_SIZE;
1572 while(i--)
1573 *ids++ = -1;
1574 p->max_used=1;
1575}
1576
1577void init_xx44_palette(xx44_palette_t *p, unsigned num_entries)
1578{
1579 p->size = (num_entries > XX44_PALETTE_SIZE) ? XX44_PALETTE_SIZE : num_entries;
745 } 1580 }
746 1581
747 x += rlelen; 1582void dispose_xx44_palette(xx44_palette_t *p)
1583{
1584}
1585
1586static void colorToPalette(const uint32_t *icolor, unsigned char *palette_p,
1587 unsigned num_xvmc_components, char *xvmc_components)
1588{
1589 const clut_t *color = (const clut_t *) icolor;
1590 int i;
1591 for (i=0; i<num_xvmc_components; ++i) {
1592 switch(xvmc_components[i]) {
1593 case 'V': *palette_p = color->cr; break;
1594 case 'U': *palette_p = color->cb; break;
1595 case 'Y':
1596 default: *palette_p = color->y; break;
1597 }
1598 *palette_p++;
1599 }
1600}
1601
1602
1603void xx44_to_xvmc_palette(const xx44_palette_t *p,unsigned char *xvmc_palette,
1604 unsigned first_xx44_entry, unsigned num_xx44_entries,
1605 unsigned num_xvmc_components, char *xvmc_components)
1606{
1607 register int i;
1608 register const uint32_t *cluts = p->cluts + first_xx44_entry;
1609
1610 for (i=0; i<num_xx44_entries; ++i) {
1611 if ((cluts - p->cluts) < p->size) {
1612 colorToPalette(cluts++, xvmc_palette, num_xvmc_components, xvmc_components);
1613 xvmc_palette += num_xvmc_components;
1614 }
1615 }
1616}
1617
1618static int xx44_paletteIndex(xx44_palette_t *p, int color, uint32_t clut)
1619{
1620
1621 register int i;
1622 register uint32_t *cluts = p->cluts;
1623 register int tmp;
1624
1625 if ((tmp = p->lookup_cache[color]) >= 0)
1626 if (cluts[tmp] == clut) return tmp;
1627
1628 for (i=0; i<p->max_used; ++i) {
1629 if (*cluts++ == clut) return p->lookup_cache[color] = i;
1630 }
1631
1632 if (p->max_used == p->size -1) {
1633 printf("video_out: Warning! Out of xx44 palette colors!\n");
1634 return 1;
1635 }
1636 p->cluts[p->max_used] = clut;
1637 return p->lookup_cache[color] = p->max_used++;
1638}
1639
1640static void memblend_xx44(uint8_t *mem,uint8_t val, register size_t size, uint8_t mask)
1641{
1642 register uint8_t masked_val = val & mask;
1643
1644 while(size--) {
1645 if ((*mem & mask) <= masked_val ) *mem = val;
1646 mem++;
1647 }
1648}
1649
1650void blend_xx44 (uint8_t *dst_img, vo_overlay_t *img_overl,
1651 int dst_width, int dst_height, int dst_pitch,
1652 alphablend_t *extra_data,
1653 xx44_palette_t *palette,int ia44)
1654{
1655 int src_width = img_overl->width;
1656 int src_height = img_overl->height;
1657 rle_elem_t *rle = img_overl->rle;
1658 rle_elem_t *rle_limit = rle + img_overl->num_rle;
1659 int mask;
1660 int x_off = img_overl->x;
1661 int y_off = img_overl->y;
1662 int x, y;
1663 uint8_t norm_pixel,clip_pixel;
1664 uint8_t *dst_y;
1665 uint8_t *dst;
1666 uint8_t alphamask = (ia44) ? 0x0F : 0xF0;
1667 int clip_right;
1668
1669 if (!img_overl)
1670 return;
1671
1672 dst_y = dst_img + dst_pitch*y_off + x_off;
1673
1674 if( (x_off + img_overl->width) <= dst_width )
1675 clip_right = img_overl->width;
1676 else
1677 clip_right = dst_width - x_off;
1678
1679 if ((src_height + y_off) > dst_height)
1680 src_height = dst_height - y_off;
1681
1682 for (y = 0; y < src_height; y++) {
1683
1684 mask = !(y < img_overl->clip_top || y >= img_overl->clip_bottom);
1685 dst = dst_y;
1686
1687 for (x = 0; x < src_width;) {
1688 int len = (x + rle->len > clip_right) ? clip_right - x : rle->len;
1689
1690 if (len > 0) {
1691 norm_pixel = (uint8_t)((xx44_paletteIndex(palette,rle->color,
1692 img_overl->color[rle->color]) << 4) |
1693 (img_overl->trans[rle->color] & 0x0F));
1694 clip_pixel = (uint8_t)((xx44_paletteIndex(palette,rle->color+OVL_PALETTE_SIZE,
1695 img_overl->clip_color[rle->color]) << 4) |
1696 (img_overl->clip_trans[rle->color] & 0x0F));
1697 if (!ia44) {
1698 norm_pixel = ((norm_pixel & 0x0F) << 4) | ((norm_pixel & 0xF0) >> 4);
1699 clip_pixel = ((clip_pixel & 0x0F) << 4) | ((clip_pixel & 0xF0) >> 4);
1700 }
1701 if (mask) {
1702 if (x < img_overl->clip_left) {
1703 if (x + len <= img_overl->clip_left) {
1704 memblend_xx44(dst,norm_pixel,len, alphamask);
1705 dst += len;
1706 } else {
1707 memblend_xx44(dst,norm_pixel,img_overl->clip_left -x, alphamask);
1708 dst += img_overl->clip_left - x;
1709 len -= img_overl->clip_left - x;
1710 if (len <= img_overl->clip_right - img_overl->clip_left) {
1711 memblend_xx44(dst,clip_pixel,len, alphamask);
1712 dst += len;
1713 } else {
1714 memblend_xx44(dst,clip_pixel,img_overl->clip_right - img_overl->clip_left,
1715 alphamask);
1716 dst += img_overl->clip_right - img_overl->clip_left;
1717 len -= img_overl->clip_right - img_overl->clip_left;
1718 memblend_xx44(dst,norm_pixel,len, alphamask);
1719 dst += len;
1720 }
1721 }
1722 } else if (x < img_overl->clip_right) {
1723 if (len <= img_overl->clip_right - x) {
1724 memblend_xx44(dst,clip_pixel,len, alphamask);
1725 dst += len;
1726 } else {
1727 memblend_xx44(dst,clip_pixel,img_overl->clip_right - x,alphamask);
1728 dst += img_overl->clip_right - x;
1729 len -= img_overl->clip_right - x;
1730 memblend_xx44(dst,norm_pixel,len, alphamask);
1731 dst += len;
1732 }
1733 } else {
1734 memblend_xx44(dst,norm_pixel,len, alphamask);
1735 dst += len;
1736 }
1737 } else {
1738 memblend_xx44(dst,norm_pixel,len, alphamask);
1739 dst += len;
1740 }
1741 }
1742 x += rle->len;
748 rle++; 1743 rle++;
@@ -751,5 +1746,39 @@ void blend_yuy2 (uint8_t * dst_img, vo_overlay_t * img_overl,
751 if (rle >= rle_limit) break; 1746 if (rle >= rle_limit) break;
1747 dst_y += dst_pitch;
1748 }
1749}
752 1750
753 dst_y += dst_width*2; 1751static void alphablend_disable_exact_osd_alpha_blending_changed(void *user_data, xine_cfg_entry_t *entry)
1752{
1753 alphablend_t *extra_data = (alphablend_t *)user_data;
1754
1755 extra_data->disable_exact_blending = entry->num_value;
754 } 1756 }
1757
1758void _x_alphablend_init(alphablend_t *extra_data, xine_t *xine)
1759{
1760 config_values_t *config = xine->config;
1761
1762 extra_data->buffer = 0;
1763 extra_data->buffer_size = 0;
1764
1765 extra_data->disable_exact_blending =
1766 config->register_bool(config, "video.output.disable_exact_alphablend", 0,
1767 _("disable exact alpha blending of overlays"),
1768 _("If you experience a performance impact when an On Screen Display or other "
1769 "overlays like DVD subtitles are active, then you might want to enable this option.\n"
1770 "The result is that alpha blending of overlays is less accurate than before, "
1771 "but the CPU usage will be decreased as well."),
1772 10, alphablend_disable_exact_osd_alpha_blending_changed, extra_data);
755} 1773}
1774
1775void _x_alphablend_free(alphablend_t *extra_data)
1776{
1777 if (extra_data->buffer) {
1778 free(extra_data->buffer);
1779 extra_data->buffer = NULL;
1780 }
1781
1782 extra_data->buffer_size = 0;
1783}
1784