author | zecke <zecke> | 2005-04-17 13:56:34 (UTC) |
---|---|---|
committer | zecke <zecke> | 2005-04-17 13:56:34 (UTC) |
commit | 3d5e5c098ccb686588380bc1f220beafbc5a6d76 (patch) (unidiff) | |
tree | 92fad8a98ea341ec290dc7f9fca7759470b795f6 /noncore/multimedia/opieplayer2/alphablend.c | |
parent | 49335d66d8e96b1fc86ecfe95cd343c8960126bc (diff) | |
download | opie-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) (ignore whitespace changes)
-rw-r--r-- | noncore/multimedia/opieplayer2/alphablend.c | 1567 |
1 files changed, 1298 insertions, 269 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,15 +1,12 @@ | |||
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 | /* | 1 | /* |
6 | * | 2 | * |
7 | * Copyright (C) James Courtier-Dutton James@superbug.demon.co.uk - July 2001 | 3 | * Copyright (C) James Courtier-Dutton James@superbug.demon.co.uk - July 2001 |
8 | * | 4 | * |
9 | * Copyright (C) 2000 Thomas Mirlacher | 5 | * Copyright (C) 2000 Thomas Mirlacher |
6 | * 2002-2004 the xine project | ||
10 | * | 7 | * |
11 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
13 | * the Free Software Foundation; either version 2 of the License, or | 10 | * the Free Software Foundation; either version 2 of the License, or |
14 | * (at your option) any later version. | 11 | * (at your option) any later version. |
15 | * | 12 | * |
@@ -27,23 +24,23 @@ | |||
27 | *------------------------------------------------------------ | 24 | *------------------------------------------------------------ |
28 | * | 25 | * |
29 | */ | 26 | */ |
30 | 27 | ||
31 | /* | 28 | /* |
32 | #define LOG_BLEND_YUV | 29 | #define LOG_BLEND_YUV |
30 | #define LOG_BLEND_RGB16 | ||
33 | */ | 31 | */ |
34 | 32 | ||
35 | #include <string.h> | 33 | #include <string.h> |
36 | #include <stdlib.h> | 34 | #include <stdlib.h> |
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> |
42 | #include <xine/video_out.h> | 38 | #include <xine/video_out.h> |
43 | #include "alphablend.h" | 39 | #include "alphablend.h" |
40 | #include "bswap.h" | ||
44 | 41 | ||
45 | 42 | ||
46 | #define BLEND_COLOR(dst, src, mask, o) ((((src&mask)*o + ((dst&mask)*(0x0f-o)))/0xf) & mask) | 43 | #define BLEND_COLOR(dst, src, mask, o) ((((src&mask)*o + ((dst&mask)*(0x0f-o)))/0xf) & mask) |
47 | 44 | ||
48 | #define BLEND_BYTE(dst, src, o) (((src)*o + ((dst)*(0xf-o)))/0xf) | 45 | #define BLEND_BYTE(dst, src, o) (((src)*o + ((dst)*(0xf-o)))/0xf) |
49 | 46 | ||
@@ -56,37 +53,24 @@ static void mem_blend16(uint16_t *mem, uint16_t clr, uint8_t o, int len) { | |||
56 | BLEND_COLOR(*mem, clr, 0x001f, o); | 53 | BLEND_COLOR(*mem, clr, 0x001f, o); |
57 | mem++; | 54 | mem++; |
58 | } | 55 | } |
59 | } | 56 | } |
60 | 57 | ||
61 | static void mem_blend24(uint8_t *mem, uint8_t r, uint8_t g, uint8_t b, | 58 | static void mem_blend24(uint8_t *mem, uint8_t r, uint8_t g, uint8_t b, |
62 | uint8_t o, int len) { | 59 | uint8_t o, int len) { |
63 | uint8_t *limit = mem + len*3; | 60 | uint8_t *limit = mem + len*3; |
64 | while (mem < limit) { | 61 | while (mem < limit) { |
65 | *mem = BLEND_BYTE(*mem, r, o); | 62 | *mem = BLEND_BYTE(*mem, r, o); |
66 | mem++; | 63 | mem++; |
67 | *mem = BLEND_BYTE(*mem, g, o); | 64 | *mem = BLEND_BYTE(*mem, g, o); |
68 | mem++; | 65 | mem++; |
69 | *mem = BLEND_BYTE(*mem, b, o); | 66 | *mem = BLEND_BYTE(*mem, b, o); |
70 | mem++; | 67 | mem++; |
71 | } | 68 | } |
72 | } | 69 | } |
73 | 70 | ||
74 | static 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 | |||
87 | static void mem_blend32(uint8_t *mem, uint8_t *src, uint8_t o, int len) { | 71 | static void mem_blend32(uint8_t *mem, uint8_t *src, uint8_t o, int len) { |
88 | uint8_t *limit = mem + len*4; | 72 | uint8_t *limit = mem + len*4; |
89 | while (mem < limit) { | 73 | while (mem < limit) { |
90 | *mem = BLEND_BYTE(*mem, src[0], o); | 74 | *mem = BLEND_BYTE(*mem, src[0], o); |
91 | mem++; | 75 | mem++; |
92 | *mem = BLEND_BYTE(*mem, src[1], o); | 76 | *mem = BLEND_BYTE(*mem, src[1], o); |
@@ -95,13 +79,12 @@ static void mem_blend32(uint8_t *mem, uint8_t *src, uint8_t o, int len) { | |||
95 | mem++; | 79 | mem++; |
96 | *mem = BLEND_BYTE(*mem, src[3], o); | 80 | *mem = BLEND_BYTE(*mem, src[3], o); |
97 | mem++; | 81 | mem++; |
98 | } | 82 | } |
99 | } | 83 | } |
100 | 84 | ||
101 | |||
102 | /* | 85 | /* |
103 | * Some macros for fixed point arithmetic. | 86 | * Some macros for fixed point arithmetic. |
104 | * | 87 | * |
105 | * The blend_rgb* routines perform rle image scaling using | 88 | * The blend_rgb* routines perform rle image scaling using |
106 | * scale factors that are expressed as integers scaled with | 89 | * scale factors that are expressed as integers scaled with |
107 | * a factor of 2**16. | 90 | * a factor of 2**16. |
@@ -124,116 +107,420 @@ rle_img_advance_line(rle_elem_t *rle, rle_elem_t *rle_limit, int w) | |||
124 | x += rle->len; | 107 | x += rle->len; |
125 | rle++; | 108 | rle++; |
126 | } | 109 | } |
127 | return rle; | 110 | return rle; |
128 | } | 111 | } |
129 | 112 | ||
130 | |||
131 | void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl, | 113 | void 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 | ||
138 | int src_width = img_overl->width; | 121 | int src_width = img_overl->width; |
139 | int src_height = img_overl->height; | 122 | int src_height = img_overl->height; |
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; |
142 | int x, y, x1_scaled, x2_scaled; | 126 | int x, y, x1_scaled, x2_scaled; |
143 | int dy, dy_step, x_scale;/* scaled 2**SCALE_SHIFT */ | 127 | int dy, dy_step, x_scale; /* scaled 2**SCALE_SHIFT */ |
144 | int clip_right; | 128 | int clip_right; |
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 | ||
156 | /* avoid wraping overlay if drawing to small image */ | 184 | /* avoid wraping overlay if drawing to small image */ |
157 | if( (img_overl->x + img_overl->clip_right) < dst_width ) | 185 | if( (img_overl->x + img_overl->clip_right) < dst_width ) |
158 | clip_right = img_overl->clip_right; | 186 | clip_right = img_overl->clip_right; |
159 | else | 187 | else |
160 | clip_right = dst_width - 1 - img_overl->x; | 188 | clip_right = dst_width - img_overl->x; |
161 | 189 | ||
162 | /* avoid buffer overflow */ | 190 | /* avoid buffer overflow */ |
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; | 204 | |
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 | ||
174 | 214 | ||
175 | clr = rle->color; | 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; |
178 | 247 | rle_remainder = 0; | |
179 | if (o && mask) { | 248 | rlelen -= rle_this_bite; |
180 | /* threat cases where clipping border is inside rle->len pixels */ | 249 | /*printf("(x,y) = (%03i,%03i), clr=%03x, len=%03i, zone=%i\n", x, y, clr, rle_this_bite, zone_state); */ |
181 | if ( img_overl->clip_left > x ) { | 250 | if (o) { |
182 | if( img_overl->clip_left < x + rlelen ) { | 251 | x1_scaled = SCALED_TO_INT( x * x_scale ); |
183 | x1_scaled = SCALED_TO_INT( img_overl->clip_left * x_scale ); | 252 | x2_scaled = SCALED_TO_INT( (x + rle_this_bite) * x_scale); |
184 | rlelen -= img_overl->clip_left - x; | 253 | mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled); |
185 | x += img_overl->clip_left - x; | 254 | } |
186 | } else { | 255 | x += rle_this_bite; |
187 | o = 0; | 256 | if (x >= src_width ) { |
257 | x -= src_width; | ||
258 | img_pix += img_width; | ||
259 | |||
260 | dy += dy_step; | ||
261 | if (dy >= INT_TO_SCALED(1)) { | ||
262 | dy -= INT_TO_SCALED(1); | ||
263 | ++y; | ||
264 | while (dy >= INT_TO_SCALED(1)) { | ||
265 | rle = rle_img_advance_line(rle, rle_limit, src_width); | ||
266 | dy -= INT_TO_SCALED(1); | ||
267 | ++y; | ||
188 | } | 268 | } |
189 | } else if( clip_right < x + rlelen ) { | 269 | rle_start = rle; |
190 | if( clip_right > x ) { | 270 | } else { |
191 | x2_scaled = SCALED_TO_INT( clip_right * x_scale); | 271 | rle = rle_start; /* y-scaling, reuse the last rle encoded line */ |
192 | mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, | 272 | } |
193 | x2_scaled-x1_scaled); | 273 | } |
194 | o = 0; | 274 | rle_remainder = rlelen = rle->len; |
195 | } else { | 275 | clr_next = rle->color; |
196 | o = 0; | 276 | rle++; |
277 | if (rle >= rle_limit) { | ||
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; | ||
197 | } | 290 | } |
198 | } | 291 | } |
199 | } | 292 | } |
200 | 293 | break; | |
201 | x2_scaled = SCALED_TO_INT((x + rlelen) * x_scale); | 294 | case 2: /* Left of button */ |
202 | if (o && mask) { | 295 | clut = (clut_t*) img_overl->color; |
203 | mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled); | 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; | ||
204 | } | 307 | } |
205 | 308 | if (o) { | |
206 | x1_scaled = x2_scaled; | 309 | x1_scaled = SCALED_TO_INT( x * x_scale ); |
207 | x += rlelen; | 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; | ||
327 | } else { | ||
328 | rle = rle_start; /* y-scaling, reuse the last rle encoded line */ | ||
329 | } | ||
330 | if (y >= img_overl->clip_bottom) { | ||
331 | zone_state = 5; | ||
332 | break; | ||
333 | } | ||
334 | } | ||
335 | if (rle >= rle_limit) { | ||
336 | zone_state = 6; | ||
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); | ||
356 | mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled); | ||
357 | } | ||
358 | x += rle_this_bite; | ||
359 | if (x >= src_width ) { | ||
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; | ||
392 | rle++; | ||
393 | } else { | ||
394 | rle_this_bite = src_width - x; | ||
395 | rle_remainder -= rle_this_bite; | ||
396 | zone_state = 2; | ||
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; | ||
208 | rle++; | 461 | rle++; |
209 | if (rle >= rle_limit) break; | 462 | if (rle >= rle_limit) { |
210 | } | 463 | zone_state = 6; |
464 | } | ||
465 | break; | ||
466 | case 6: /* Finished */ | ||
467 | _x_abort(); | ||
211 | 468 | ||
212 | img_pix += img_width; | 469 | case 7: /* No button */ |
213 | dy += dy_step; | 470 | clut = (clut_t*) img_overl->color; |
214 | if (dy >= INT_TO_SCALED(1)) { | 471 | trans = img_overl->trans; |
215 | dy -= INT_TO_SCALED(1); | 472 | o = trans[clr]; |
216 | ++y; | 473 | rle_this_bite = rle_remainder; |
217 | while (dy >= INT_TO_SCALED(1)) { | 474 | rle_remainder = 0; |
218 | rle = rle_img_advance_line(rle, rle_limit, src_width); | 475 | rlelen -= rle_this_bite; |
219 | dy -= INT_TO_SCALED(1); | 476 | if (o) { |
220 | ++y; | 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); | ||
221 | } | 480 | } |
222 | } else { | 481 | x += rle_this_bite; |
223 | rle = rle_start; /* y-scaling, reuse the last rle encoded line */ | 482 | if (x >= src_width ) { |
483 | x -= src_width; | ||
484 | img_pix += img_width; | ||
485 | dy += dy_step; | ||
486 | if (dy >= INT_TO_SCALED(1)) { | ||
487 | dy -= INT_TO_SCALED(1); | ||
488 | ++y; | ||
489 | while (dy >= INT_TO_SCALED(1)) { | ||
490 | rle = rle_img_advance_line(rle, rle_limit, src_width); | ||
491 | dy -= INT_TO_SCALED(1); | ||
492 | ++y; | ||
493 | } | ||
494 | rle_start = rle; | ||
495 | } else { | ||
496 | rle = rle_start; /* y-scaling, reuse the last rle encoded line */ | ||
497 | } | ||
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 | ; | ||
224 | } | 508 | } |
225 | } | 509 | } |
510 | #ifdef LOG_BLEND_RGB16 | ||
511 | printf("blend_rgb16 ended\n"); | ||
512 | #endif | ||
513 | |||
226 | } | 514 | } |
227 | 515 | ||
228 | void blend_rgb24 (uint8_t * img, vo_overlay_t * img_overl, | 516 | 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; |
235 | int src_height = img_overl->height; | 522 | int src_height = img_overl->height; |
236 | rle_elem_t *rle = img_overl->rle; | 523 | rle_elem_t *rle = img_overl->rle; |
237 | rle_elem_t *rle_limit = rle + img_overl->num_rle; | 524 | rle_elem_t *rle_limit = rle + img_overl->num_rle; |
238 | int x, y, x1_scaled, x2_scaled; | 525 | int x, y, x1_scaled, x2_scaled; |
239 | int dy, dy_step, x_scale;/* scaled 2**SCALE_SHIFT */ | 526 | int dy, dy_step, x_scale;/* scaled 2**SCALE_SHIFT */ |
@@ -243,71 +530,112 @@ void blend_rgb24 (uint8_t * img, vo_overlay_t * img_overl, | |||
243 | dy_step = INT_TO_SCALED(dst_height) / img_height; | 530 | dy_step = INT_TO_SCALED(dst_height) / img_height; |
244 | x_scale = INT_TO_SCALED(img_width) / dst_width; | 531 | x_scale = INT_TO_SCALED(img_width) / dst_width; |
245 | 532 | ||
246 | img_pix = img + 3 * ( (img_overl->y * img_height / dst_height) * img_width | 533 | img_pix = img + 3 * ( (img_overl->y * img_height / dst_height) * img_width |
247 | + (img_overl->x * img_width / dst_width)); | 534 | + (img_overl->x * img_width / dst_width)); |
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) { |
272 | rlelen = rle->len; | 561 | if (rle >= rle_limit) |
273 | 562 | break; | |
274 | if (o && mask) { | 563 | |
275 | /* threat cases where clipping border is inside rle->len pixels */ | 564 | rlelen = rle->len; |
276 | if ( img_overl->clip_left > x ) { | 565 | clr = rle->color; |
277 | if( img_overl->clip_left < x + rlelen ) { | 566 | rle++; |
278 | x1_scaled = SCALED_TO_INT( img_overl->clip_left * x_scale ); | 567 | } |
279 | rlelen -= img_overl->clip_left - x; | 568 | |
280 | x += img_overl->clip_left - x; | 569 | if (!mask) { |
570 | /* above or below clipping area */ | ||
571 | |||
572 | rle_bite = rlelen; | ||
573 | /* choose palette for surrounding area */ | ||
574 | colors = (clut_t*)img_overl->color; | ||
575 | trans = img_overl->trans; | ||
576 | } else { | ||
577 | /* treat cases where clipping border is inside rle->len pixels */ | ||
578 | if ( x < img_overl->clip_left ) { | ||
579 | /* starts left */ | ||
580 | if( x + rlelen > img_overl->clip_left ) { | ||
581 | /* ends not left */ | ||
582 | |||
583 | /* choose the largest "bite" up to palette change */ | ||
584 | rle_bite = img_overl->clip_left - x; | ||
585 | /* choose palette for surrounding area */ | ||
586 | colors = (clut_t*)img_overl->color; | ||
587 | trans = img_overl->trans; | ||
281 | } else { | 588 | } else { |
282 | o = 0; | 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; | ||
283 | } | 595 | } |
284 | } else if( clip_right < x + rlelen ) { | 596 | } else if( x + rlelen > clip_right ) { |
285 | if( clip_right > x ) { | 597 | /* ends right */ |
286 | x2_scaled = SCALED_TO_INT( clip_right * x_scale); | 598 | if( x < clip_right ) { |
287 | mem_blend24(img_pix + x1_scaled*3, clut[clr].cb, | 599 | /* starts not right */ |
288 | clut[clr].cr, clut[clr].y, | 600 | |
289 | o, x2_scaled-x1_scaled); | 601 | /* choose the largest "bite" up to palette change */ |
290 | o = 0; | 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 | } |
294 | } | 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; | ||
621 | } | ||
295 | } | 622 | } |
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); |
302 | } | 631 | } |
303 | 632 | ||
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 | } |
309 | 637 | ||
310 | img_pix += img_width * 3; | 638 | img_pix += img_width * 3; |
311 | dy += dy_step; | 639 | dy += dy_step; |
312 | if (dy >= INT_TO_SCALED(1)) { | 640 | if (dy >= INT_TO_SCALED(1)) { |
313 | dy -= INT_TO_SCALED(1); | 641 | dy -= INT_TO_SCALED(1); |
@@ -322,16 +650,15 @@ void blend_rgb24 (uint8_t * img, vo_overlay_t * img_overl, | |||
322 | } | 650 | } |
323 | } | 651 | } |
324 | } | 652 | } |
325 | 653 | ||
326 | void blend_rgb32 (uint8_t * img, vo_overlay_t * img_overl, | 654 | 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; |
333 | int src_height = img_overl->height; | 660 | int src_height = img_overl->height; |
334 | rle_elem_t *rle = img_overl->rle; | 661 | rle_elem_t *rle = img_overl->rle; |
335 | rle_elem_t *rle_limit = rle + img_overl->num_rle; | 662 | rle_elem_t *rle_limit = rle + img_overl->num_rle; |
336 | int x, y, x1_scaled, x2_scaled; | 663 | int x, y, x1_scaled, x2_scaled; |
337 | int dy, dy_step, x_scale;/* scaled 2**SCALE_SHIFT */ | 664 | int dy, dy_step, x_scale;/* scaled 2**SCALE_SHIFT */ |
@@ -341,71 +668,110 @@ void blend_rgb32 (uint8_t * img, vo_overlay_t * img_overl, | |||
341 | dy_step = INT_TO_SCALED(dst_height) / img_height; | 668 | dy_step = INT_TO_SCALED(dst_height) / img_height; |
342 | x_scale = INT_TO_SCALED(img_width) / dst_width; | 669 | x_scale = INT_TO_SCALED(img_width) / dst_width; |
343 | 670 | ||
344 | img_pix = img + 4 * ( (img_overl->y * img_height / dst_height) * img_width | 671 | img_pix = img + 4 * ( (img_overl->y * img_height / dst_height) * img_width |
345 | + (img_overl->x * img_width / dst_width)); | 672 | + (img_overl->x * img_width / dst_width)); |
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; | 696 | |
697 | /* take next element from rle list everytime an element is finished */ | ||
698 | if (rlelen <= 0) { | ||
699 | if (rle >= rle_limit) | ||
700 | break; | ||
701 | |||
702 | rlelen = rle->len; | ||
703 | clr = rle->color; | ||
704 | rle++; | ||
705 | } | ||
367 | 706 | ||
368 | clr = rle->color; | 707 | if (!mask) { |
369 | o = trans[clr]; | 708 | /* above or below clipping area */ |
370 | rlelen = rle->len; | 709 | |
371 | 710 | rle_bite = rlelen; | |
372 | if (o && mask) { | 711 | /* choose palette for surrounding area */ |
373 | /* threat cases where clipping border is inside rle->len pixels */ | 712 | colors = (clut_t*)img_overl->color; |
374 | if ( img_overl->clip_left > x ) { | 713 | trans = img_overl->trans; |
375 | if( img_overl->clip_left < x + rlelen ) { | 714 | } else { |
376 | x1_scaled = SCALED_TO_INT( img_overl->clip_left * x_scale ); | 715 | /* treat cases where clipping border is inside rle->len pixels */ |
377 | rlelen -= img_overl->clip_left - x; | 716 | if ( x < img_overl->clip_left ) { |
378 | x += img_overl->clip_left - x; | 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; | ||
379 | } else { | 726 | } else { |
380 | o = 0; | 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; | ||
381 | } | 733 | } |
382 | } else if( clip_right < x + rlelen ) { | 734 | } else if( x + rlelen > clip_right ) { |
383 | if( clip_right > x ) { | 735 | /* ends right */ |
384 | x2_scaled = SCALED_TO_INT( clip_right * x_scale); | 736 | if( x < clip_right ) { |
385 | mem_blend24_32(img_pix + x1_scaled*4, clut[clr].cb, | 737 | /* starts not right */ |
386 | clut[clr].cr, clut[clr].y, | 738 | |
387 | o, x2_scaled-x1_scaled); | 739 | /* choose the largest "bite" up to palette change */ |
388 | o = 0; | 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; | ||
389 | } else { | 744 | } else { |
390 | o = 0; | 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 | } |
392 | } | 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; | ||
759 | } | ||
393 | } | 760 | } |
761 | |||
762 | x2_scaled = SCALED_TO_INT((x + rle_bite) * x_scale); | ||
394 | 763 | ||
395 | x2_scaled = SCALED_TO_INT((x + rlelen) * x_scale); | 764 | o = trans[clr]; |
396 | if (o && mask) { | 765 | if (o) { |
397 | mem_blend24_32(img_pix + x1_scaled*4, clut[clr].cb, | 766 | mem_blend32(img_pix + x1_scaled*4, (uint8_t *)&colors[clr], o, x2_scaled-x1_scaled); |
398 | clut[clr].cr, clut[clr].y, | ||
399 | o, x2_scaled-x1_scaled); | ||
400 | } | 767 | } |
401 | 768 | ||
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 | } |
407 | 773 | ||
408 | img_pix += img_width * 4; | 774 | img_pix += img_width * 4; |
409 | dy += dy_step; | 775 | dy += dy_step; |
410 | if (dy >= INT_TO_SCALED(1)) { | 776 | if (dy >= INT_TO_SCALED(1)) { |
411 | dy -= INT_TO_SCALED(1); | 777 | dy -= INT_TO_SCALED(1); |
@@ -427,96 +793,233 @@ static void mem_blend8(uint8_t *mem, uint8_t val, uint8_t o, size_t sz) | |||
427 | while (mem < limit) { | 793 | while (mem < limit) { |
428 | *mem = BLEND_BYTE(*mem, val, o); | 794 | *mem = BLEND_BYTE(*mem, val, o); |
429 | mem++; | 795 | mem++; |
430 | } | 796 | } |
431 | } | 797 | } |
432 | 798 | ||
799 | static 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 | |||
858 | static 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 | |||
433 | void blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl, | 897 | void 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; |
437 | uint8_t *my_trans; | 903 | uint8_t *my_trans; |
438 | 904 | ||
439 | int src_width = img_overl->width; | 905 | int src_width = img_overl->width; |
440 | int src_height = img_overl->height; | 906 | int src_height = img_overl->height; |
441 | rle_elem_t *rle = img_overl->rle; | 907 | rle_elem_t *rle = img_overl->rle; |
442 | rle_elem_t *rle_limit = rle + img_overl->num_rle; | 908 | rle_elem_t *rle_limit = rle + img_overl->num_rle; |
443 | int x_off = img_overl->x; | 909 | int x_off = img_overl->x; |
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; |
446 | int rle_this_bite; | 914 | int rle_this_bite; |
447 | int rle_remainder; | 915 | int rle_remainder; |
448 | int rlelen; | 916 | int rlelen; |
449 | int x, y; | 917 | int x, y; |
450 | int clip_right; | 918 | int clip_right; |
451 | uint8_t clr=0; | 919 | uint8_t clr=0; |
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 |
459 | printf("overlay_blend started x=%d, y=%d, w=%d h=%d\n",img_overl->x,img_overl->y,img_overl->width,img_overl->height); | 930 | printf("overlay_blend started x=%d, y=%d, w=%d h=%d\n",img_overl->x,img_overl->y,img_overl->width,img_overl->height); |
460 | #endif | 931 | #endif |
461 | my_clut = (clut_t*) img_overl->clip_color; | 932 | my_clut = (clut_t*) img_overl->clip_color; |
462 | my_trans = img_overl->clip_trans; | 933 | my_trans = img_overl->clip_trans; |
463 | 934 | ||
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; |
473 | 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 | } | ||
960 | |||
474 | rlelen=rle_remainder=0; | 961 | rlelen=rle_remainder=0; |
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; |
478 | #ifdef LOG_BLEND_YUV | 972 | #ifdef LOG_BLEND_YUV |
479 | printf("X started ymask=%d y=%d src_height=%d\n",ymask, y, src_height); | 973 | printf("X started ymask=%d y=%d src_height=%d\n",ymask, y, src_height); |
480 | #endif | 974 | #endif |
481 | 975 | ||
482 | for (x = 0; x < src_width;) { | 976 | for (x = 0; x < src_width;) { |
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 |
485 | printf("1:rle_len=%d, remainder=%d, x=%d\n",rlelen, rle_remainder, x); | 987 | printf("1:rle_len=%d, remainder=%d, x=%d\n",rlelen, rle_remainder, x); |
486 | #endif | 988 | #endif |
487 | 989 | ||
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 | } |
491 | if (rlelen == 0) { | 995 | if (rlelen == 0) { |
492 | rle_remainder = rlelen = rle->len; | 996 | rle_remainder = rlelen = rle->len; |
493 | clr = rle->color; | 997 | clr = rle->color; |
494 | rle++; | 998 | rle++; |
495 | } | 999 | } |
496 | if (rle_remainder == 0) { | 1000 | if (rle_remainder == 0) { |
497 | rle_remainder = rlelen; | 1001 | rle_remainder = rlelen; |
498 | } | 1002 | } |
499 | if ((rle_remainder + x) > src_width) { | 1003 | if ((rle_remainder + x) > src_width) { |
500 | /* Do something for long rlelengths */ | 1004 | /* Do something for long rlelengths */ |
501 | rle_remainder = src_width - x; | 1005 | rle_remainder = src_width - x; |
502 | ; | ||
503 | } | 1006 | } |
504 | #ifdef LOG_BLEND_YUV | 1007 | #ifdef LOG_BLEND_YUV |
505 | printf("2:rle_len=%d, remainder=%d, x=%d\n",rlelen, rle_remainder, x); | 1008 | printf("2:rle_len=%d, remainder=%d, x=%d\n",rlelen, rle_remainder, x); |
506 | #endif | 1009 | #endif |
507 | 1010 | ||
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 |
513 | printf("Outside clip left %d, ending inside\n", img_overl->clip_left); | 1016 | printf("Outside clip left %d, ending inside\n", img_overl->clip_left); |
514 | #endif | 1017 | #endif |
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; |
518 | rlelen -= rle_this_bite; | 1021 | rlelen -= rle_this_bite; |
519 | my_clut = (clut_t*) img_overl->color; | 1022 | my_clut = (clut_t*) img_overl->color; |
520 | my_trans = img_overl->trans; | 1023 | my_trans = img_overl->trans; |
521 | xmask = 0; | 1024 | xmask = 0; |
522 | } else { | 1025 | } else { |
@@ -554,13 +1057,13 @@ void blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl, | |||
554 | rlelen -= rle_this_bite; | 1057 | rlelen -= rle_this_bite; |
555 | my_clut = (clut_t*) img_overl->clip_color; | 1058 | my_clut = (clut_t*) img_overl->clip_color; |
556 | my_trans = img_overl->clip_trans; | 1059 | my_trans = img_overl->clip_trans; |
557 | xmask++; | 1060 | xmask++; |
558 | } | 1061 | } |
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 ) { |
562 | #ifdef LOG_BLEND_YUV | 1065 | #ifdef LOG_BLEND_YUV |
563 | printf("Outside clip right %d, ending eol\n", clip_right); | 1066 | printf("Outside clip right %d, ending eol\n", clip_right); |
564 | #endif | 1067 | #endif |
565 | /* Cutting needed, starts outside, ends at right edge */ | 1068 | /* Cutting needed, starts outside, ends at right edge */ |
566 | /* It should never reach here due to the earlier test of src_width */ | 1069 | /* It should never reach here due to the earlier test of src_width */ |
@@ -594,162 +1097,688 @@ void blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl, | |||
594 | xmask = 0; | 1097 | xmask = 0; |
595 | } | 1098 | } |
596 | o = my_trans[clr]; | 1099 | o = my_trans[clr]; |
597 | #ifdef LOG_BLEND_YUV | 1100 | #ifdef LOG_BLEND_YUV |
598 | printf("Trans=%d clr=%d xmask=%d my_clut[clr]=%d\n",o, clr, xmask, my_clut[clr].y); | 1101 | printf("Trans=%d clr=%d xmask=%d my_clut[clr]=%d\n",o, clr, xmask, my_clut[clr].y); |
599 | #endif | 1102 | #endif |
600 | if (o) { | 1103 | |
601 | if(o >= 15) { | 1104 | if (x < (dst_width - x_off)) { |
602 | memset(dst_y + x, my_clut[clr].y, rle_this_bite); | 1105 | /* clip against right edge of destination area */ |
603 | if (y & 1) { | 1106 | if ((x + rle_this_bite) > (dst_width - x_off)) { |
604 | memset(dst_cr + (x >> 1), my_clut[clr].cr, (rle_this_bite+1) >> 1); | 1107 | int toClip = (x + rle_this_bite) - (dst_width - x_off); |
605 | memset(dst_cb + (x >> 1), my_clut[clr].cb, (rle_this_bite+1) >> 1); | 1108 | |
606 | } | 1109 | rle_this_bite -= toClip; |
607 | } else { | 1110 | rle_remainder += toClip; |
608 | mem_blend8(dst_y + x, my_clut[clr].y, o, rle_this_bite); | 1111 | rlelen += toClip; |
609 | if (y & 1) { | ||
610 | /* 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); | ||
612 | mem_blend8(dst_cb + (x >> 1), my_clut[clr].cb, o, (rle_this_bite+1) >> 1); | ||
613 | } | ||
614 | } | 1112 | } |
615 | 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 | |||
1120 | if (o) { | ||
1121 | if(o >= 15) { | ||
1122 | memset(dst_y + x, my_clut[clr].y, rle_this_bite); | ||
1123 | if (!enable_exact_blending) { | ||
1124 | if ((y + y_odd) & 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 | } | ||
1128 | } | ||
1129 | } else { | ||
1130 | mem_blend8(dst_y + x, my_clut[clr].y, o, rle_this_bite); | ||
1131 | if (!enable_exact_blending) { | ||
1132 | if ((y + y_odd) & 1) { | ||
1133 | /* Blending cr and cb should use a different function, with pre -128 to each sample */ | ||
1134 | mem_blend8(dst_cr + ((x + x_odd) >> 1), my_clut[clr].cr, 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 | } | ||
1137 | } | ||
1138 | } | ||
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 | } |
617 | #ifdef LOG_BLEND_YUV | 1147 | #ifdef LOG_BLEND_YUV |
618 | printf("rle_this_bite=%d, remainder=%d, x=%d\n",rle_this_bite, rle_remainder, x); | 1148 | printf("rle_this_bite=%d, remainder=%d, x=%d\n",rle_this_bite, rle_remainder, x); |
619 | #endif | 1149 | #endif |
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 | } | ||
627 | } | ||
628 | if (rle >= rle_limit) { | ||
629 | #ifdef LOG_BLEND_YUV | ||
630 | printf("x-rle_limit\n"); | ||
631 | #endif | ||
632 | break; | ||
633 | } | 1151 | } |
634 | 1152 | ||
635 | dst_y += dst_width; | 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; | ||
1165 | } | ||
1166 | } | ||
1167 | |||
1168 | dst_cr += dst_pitches[2]; | ||
1169 | dst_cb += dst_pitches[1]; | ||
1170 | } | ||
1171 | |||
1172 | dst_y += dst_pitches[0]; | ||
1173 | } | ||
636 | 1174 | ||
637 | if (y & 1) { | 1175 | if (enable_exact_blending) { |
638 | dst_cr += (dst_width + 1) / 2; | 1176 | /* blend buffered lines */ |
639 | dst_cb += (dst_width + 1) / 2; | 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); | ||
1181 | } | ||
1182 | |||
1183 | blend_yuv_exact(dst_cr, dst_cb, exact_blend_width, x_odd, blend_yuv_data); | ||
640 | } | 1184 | } |
641 | } | 1185 | } |
1186 | |||
642 | #ifdef LOG_BLEND_YUV | 1187 | #ifdef LOG_BLEND_YUV |
643 | printf("overlay_blend ended\n"); | 1188 | printf("overlay_blend ended\n"); |
644 | #endif | 1189 | #endif |
645 | } | 1190 | } |
646 | 1191 | ||
1192 | static 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 | |||
1243 | static 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 | |||
647 | void blend_yuy2 (uint8_t * dst_img, vo_overlay_t * img_overl, | 1279 | void 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; |
651 | uint8_t *my_trans; | 1285 | uint8_t *my_trans; |
652 | 1286 | ||
653 | int src_width = img_overl->width; | 1287 | int src_width = img_overl->width; |
654 | int src_height = img_overl->height; | 1288 | int src_height = img_overl->height; |
655 | rle_elem_t *rle = img_overl->rle; | 1289 | rle_elem_t *rle = img_overl->rle; |
656 | rle_elem_t *rle_limit = rle + img_overl->num_rle; | 1290 | rle_elem_t *rle_limit = rle + img_overl->num_rle; |
657 | int x_off = img_overl->x; | 1291 | int x_off = img_overl->x; |
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; | 1301 | |
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; | ||
664 | 1314 | ||
665 | uint8_t *dst_y = dst_img + 2 * (dst_width * y_off + x_off); | 1315 | uint8_t *dst_y = dst_img + dst_pitch * y_off + 2 * x_off; |
666 | uint8_t *dst; | 1316 | uint8_t *dst; |
667 | 1317 | ||
668 | my_clut = (clut_t*) img_overl->clip_color; | 1318 | my_clut = (clut_t*) img_overl->clip_color; |
669 | my_trans = img_overl->clip_trans; | 1319 | my_trans = img_overl->clip_trans; |
670 | 1320 | ||
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; | ||
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 | } | ||
680 | 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 | ||
684 | dst = dst_y; | 1353 | dst = dst_y; |
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 | ||
690 | clr = rle->color; | 1357 | if (rle >= rle_limit) |
691 | o = my_trans[clr]; | 1358 | break; |
692 | rlelen = rle->len; | 1359 | |
693 | 1360 | if ((rlelen < 0) || (rle_remainder < 0)) { | |
694 | if (o && mask) { | 1361 | #ifdef LOG_BLEND_YUV |
695 | /* threat cases where clipping border is inside rle->len pixels */ | 1362 | printf("alphablend: major bug in blend_yuv < 0\n"); |
696 | if ( img_overl->clip_left > x ) { | 1363 | #endif |
697 | if( img_overl->clip_left < x + rlelen ) { | 1364 | } |
698 | rlelen -= img_overl->clip_left - x; | 1365 | if (rlelen == 0) { |
699 | x += img_overl->clip_left - x; | 1366 | rle_remainder = rlelen = rle->len; |
1367 | clr = rle->color; | ||
1368 | rle++; | ||
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 | ||
1380 | |||
1381 | if (ymask == 0) { | ||
1382 | if (x < img_overl->clip_left) { | ||
1383 | /* Starts outside clip area */ | ||
1384 | if ((x + rle_remainder) > img_overl->clip_left ) { | ||
1385 | #ifdef LOG_BLEND_YUV | ||
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; | ||
700 | } else { | 1394 | } else { |
701 | o = 0; | 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; | ||
702 | } | 1404 | } |
703 | } else if( clip_right < x + rlelen ) { | 1405 | } else if (x < clip_right) { |
704 | if( clip_right > x ) { | 1406 | /* Starts inside clip area */ |
705 | /* fixme: case not implemented */ | 1407 | if ((x + rle_remainder) > clip_right ) { |
706 | o = 0; | 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; | ||
707 | } else { | 1417 | } else { |
708 | 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; | ||
709 | } | 1427 | } |
710 | } | 1428 | } else if (x >= clip_right) { |
1429 | /* Starts outside clip area, ends outsite clip area */ | ||
1430 | if ((x + rle_remainder ) > src_width ) { | ||
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; | ||
1441 | } else { | ||
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 | } | ||
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; | ||
711 | } | 1461 | } |
712 | 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; | ||
1472 | } | ||
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 | } | ||
1479 | |||
1480 | if (o) { | ||
1481 | if (!enable_exact_blending) { | ||
1482 | l = rle_this_bite>>1; | ||
1483 | if( !((x_odd+x) & 1) ) { | ||
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; | ||
1488 | } else { | ||
1489 | yuy2.b[0] = my_clut[clr].y; | ||
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 | } | ||
1494 | } | ||
1495 | if (o >= 15) { | ||
1496 | if (!enable_exact_blending) { | ||
1497 | while(l--) { | ||
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; | ||
1506 | } | ||
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) { | ||
1516 | if( l ) { | ||
1517 | mem_blend32(dst, &yuy2.b[0], o, l); | ||
1518 | dst += 4*l; | ||
1519 | } | ||
1520 | |||
1521 | if(rle_this_bite & 1) { | ||
1522 | *dst = BLEND_BYTE(*dst, yuy2.b[0], o); | ||
1523 | dst++; | ||
1524 | *dst = BLEND_BYTE(*dst, yuy2.b[1], o); | ||
1525 | dst++; | ||
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 | } | ||
713 | 1535 | ||
714 | if (o && mask) { | 1536 | if (enable_exact_blending) { |
715 | l = rlelen>>1; | 1537 | /* remember chroma of current line */ |
716 | if( !(x & 1) ) { | 1538 | memset(&(*blend_yuy2_data)[ 1 ][ x + x_odd ], my_clut[ clr ].cr, rle_this_bite); |
717 | yuy2 = my_clut[clr].y + (my_clut[clr].cb << 8) + | 1539 | memset(&(*blend_yuy2_data)[ 2 ][ x + x_odd ], my_clut[ clr ].cb, rle_this_bite); |
718 | (my_clut[clr].y << 16) + (my_clut[clr].cr << 24); | 1540 | } |
719 | } else { | 1541 | } else { |
720 | yuy2 = my_clut[clr].y + (my_clut[clr].cr << 8) + | 1542 | dst += rle_this_bite*2; |
721 | (my_clut[clr].y << 16) + (my_clut[clr].cb << 24); | ||
722 | } | 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); | ||
723 | 1553 | ||
724 | if (o >= 15) { | 1554 | any_line_buffered = 0; |
725 | while(l--) { | 1555 | } |
726 | *((uint32_t *)dst)++ = yuy2; | 1556 | } |
1557 | |||
1558 | dst_y += dst_pitch; | ||
1559 | } | ||
1560 | } | ||
1561 | |||
1562 | void 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 | |||
1577 | void init_xx44_palette(xx44_palette_t *p, unsigned num_entries) | ||
1578 | { | ||
1579 | p->size = (num_entries > XX44_PALETTE_SIZE) ? XX44_PALETTE_SIZE : num_entries; | ||
1580 | } | ||
1581 | |||
1582 | void dispose_xx44_palette(xx44_palette_t *p) | ||
1583 | { | ||
1584 | } | ||
1585 | |||
1586 | static 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 | |||
1603 | void 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 | |||
1618 | static 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 | |||
1640 | static 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 | |||
1650 | void 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; | ||
727 | } | 1736 | } |
728 | if(rlelen & 1) | ||
729 | *((uint16_t *)dst)++ = yuy2 & 0xffff; | ||
730 | } else { | 1737 | } else { |
731 | if( l ) { | 1738 | memblend_xx44(dst,norm_pixel,len, alphamask); |
732 | mem_blend32(dst, (uint8_t *)&yuy2, o, l); | 1739 | dst += len; |
733 | dst += 4*l; | ||
734 | } | ||
735 | |||
736 | if(rlelen & 1) { | ||
737 | *dst = BLEND_BYTE(*dst, *((uint8_t *)&yuy2), o); | ||
738 | dst++; | ||
739 | *dst = BLEND_BYTE(*dst, *((uint8_t *)&yuy2+1), o); | ||
740 | dst++; | ||
741 | } | ||
742 | } | 1740 | } |
743 | } else { | ||
744 | dst += rlelen*2; | ||
745 | } | 1741 | } |
746 | 1742 | x += rle->len; | |
747 | x += rlelen; | ||
748 | rle++; | 1743 | rle++; |
749 | if (rle >= rle_limit) break; | 1744 | if (rle >= rle_limit) break; |
750 | } | 1745 | } |
751 | if (rle >= rle_limit) break; | 1746 | if (rle >= rle_limit) break; |
1747 | dst_y += dst_pitch; | ||
1748 | } | ||
1749 | } | ||
1750 | |||
1751 | static 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; | ||
1756 | } | ||
752 | 1757 | ||
753 | dst_y += dst_width*2; | 1758 | void _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); | ||
1773 | } | ||
1774 | |||
1775 | void _x_alphablend_free(alphablend_t *extra_data) | ||
1776 | { | ||
1777 | if (extra_data->buffer) { | ||
1778 | free(extra_data->buffer); | ||
1779 | extra_data->buffer = NULL; | ||
754 | } | 1780 | } |
1781 | |||
1782 | extra_data->buffer_size = 0; | ||
755 | } | 1783 | } |
1784 | |||