/src/gpac/src/evg/raster_yuv.c
Line | Count | Source |
1 | | /* |
2 | | * GPAC - Multimedia Framework C SDK |
3 | | * |
4 | | * Authors: Jean Le Feuvre |
5 | | * Copyright (c) Telecom ParisTech 2019-2025 |
6 | | * All rights reserved |
7 | | * |
8 | | * This file is part of GPAC / software 2D rasterizer module |
9 | | * |
10 | | * GPAC is free software; you can redistribute it and/or modify |
11 | | * it under the terms of the GNU Lesser General Public License as published by |
12 | | * the Free Software Foundation; either version 2, or (at your option) |
13 | | * any later version. |
14 | | * |
15 | | * GPAC is distributed in the hope that it will be useful, |
16 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 | | * GNU Lesser General Public License for more details. |
19 | | * |
20 | | * You should have received a copy of the GNU Lesser General Public |
21 | | * License along with this library; see the file COPYING. If not, write to |
22 | | * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. |
23 | | * |
24 | | * |
25 | | * |
26 | | */ |
27 | | |
28 | | #include "rast_soft.h" |
29 | | |
30 | | #ifndef GPAC_DISABLE_EVG |
31 | | |
32 | | //TODO: support for color spaces, support for more than 10 bits and BigEndian format ? |
33 | | |
34 | | #if 1 |
35 | | |
36 | 0 | #define mul255(_a, _b) ( (((u32)(_a) + 1) * (u32)(_b) ) >> 8) |
37 | | |
38 | | #else |
39 | | static s32 |
40 | | mul255(s32 a, s32 b) |
41 | | { |
42 | | return ((a + 1) * b) >> 8; |
43 | | } |
44 | | #endif |
45 | | |
46 | | static s32 |
47 | | mul255_zero(s32 a, s32 b) |
48 | 0 | { |
49 | 0 | if (!a) return 0; |
50 | 0 | return ((a + 1) * b) >> 8; |
51 | 0 | } |
52 | | |
53 | | //RGB <-> YUV full range conversion, using integer (1024 factor) |
54 | | #define YUV_USE_INT |
55 | | |
56 | | void gf_evg_rgb_to_yuv(GF_EVGSurface *surf, GF_Color col, u8*y, u8*cb, u8*cr) |
57 | 0 | { |
58 | 0 | u32 r = GF_COL_R(col); |
59 | 0 | u32 g = GF_COL_G(col); |
60 | 0 | u32 b = GF_COL_B(col); |
61 | |
|
62 | | #ifndef YUV_USE_INT |
63 | | *y = (u8) (0.299*r + 0.587 * g + 0.114 * b); |
64 | | *cb = (u8) (-0.169*(s32)r - 0.331*(s32)g + 0.499*b + 128); |
65 | | *cr = (u8) (0.499 * r - 0.418*(s32)g - 0.0813*(s32)b + 128); |
66 | | #else |
67 | 0 | u32 _v = 306*r + 601 * g + 117 * b; |
68 | 0 | *y = (u8) (_v >> 10); |
69 | 0 | _v = (-173*(s32)r - 339*(s32)g + 511*b + 131072); |
70 | 0 | *cb = (u8) (_v >> 10); |
71 | 0 | _v = (511 * r - 428*(s32)g - 83*(s32)b + 131072); |
72 | 0 | *cr = (u8) (_v >> 10); |
73 | 0 | #endif |
74 | 0 | } |
75 | | GF_Color gf_evg_argb_to_ayuv(GF_EVGSurface *surf, GF_Color col) |
76 | 0 | { |
77 | 0 | u8 a, y, cb, cr; |
78 | 0 | a = GF_COL_A(col); |
79 | 0 | u32 r = GF_COL_R(col); |
80 | 0 | u32 g = GF_COL_G(col); |
81 | 0 | u32 b = GF_COL_B(col); |
82 | |
|
83 | | #ifndef YUV_USE_INT |
84 | | y = (u8) (0.299*r + 0.587 * g + 0.114 * b); |
85 | | cb = (u8) (-0.169*(s32)r - 0.331*(s32)g + 0.499*b + 128); |
86 | | cr = (u8) (0.499 * r - 0.418*(s32)g - 0.0813*(s32)b + 128); |
87 | | #else |
88 | 0 | u32 _v = 306*r + 601 * g + 117 * b; |
89 | 0 | y = (u8) (_v >> 10); |
90 | 0 | _v = (-173*(s32)r - 339*(s32)g + 511*b + 131072); |
91 | 0 | cb = (u8) (_v >> 10); |
92 | 0 | _v = (511 * r - 428*(s32)g - 83*(s32)b + 131072); |
93 | 0 | cr = (u8) (_v >> 10); |
94 | 0 | #endif |
95 | 0 | return GF_COL_ARGB(a, y, cb, cr); |
96 | 0 | } |
97 | | |
98 | | GF_Err gf_gf_evg_rgb_to_yuv_f(GF_EVGSurface *surf, Float r, Float g, Float b, Float *y, Float *cb, Float *cr) |
99 | 0 | { |
100 | 0 | *y = (0.299f * r + 0.587f * g + 0.114f * b); |
101 | 0 | *cb = (-0.169f * (s32)r - 0.331f * (s32)g + 0.499f * b + 128.0f); |
102 | 0 | *cr = (0.499f * r - 0.418f * (s32)g - 0.0813f * (s32)b + 128.0f); |
103 | 0 | return GF_OK; |
104 | 0 | } |
105 | | GF_Err gf_evg_yuv_to_rgb_f(GF_EVGSurface *surf, Float y, Float cb, Float cr, Float *r, Float *g, Float *b) |
106 | 0 | { |
107 | 0 | *r = (y + 1.402f * (cr - 128.0f)); |
108 | 0 | *g = (y - 0.344136f * (cb - 128.0f) - 0.714136f * (cr-128.0f) ); |
109 | 0 | *b = (y + 1.772f * (cb - 128.0f) ); |
110 | 0 | return GF_OK; |
111 | 0 | } |
112 | | |
113 | | GF_Color gf_evg_ayuv_to_argb(GF_EVGSurface *surf, GF_Color col) |
114 | 0 | { |
115 | 0 | u32 a; |
116 | 0 | s32 y, cb, cr; |
117 | 0 | s32 r, g, b; |
118 | 0 | a = GF_COL_A(col); |
119 | 0 | y = GF_COL_R(col); |
120 | 0 | cb = GF_COL_G(col); |
121 | 0 | cr = GF_COL_B(col); |
122 | |
|
123 | | #ifndef YUV_USE_INT |
124 | | r = (s32) (y + 1.402 * (cr - 128)); |
125 | | g = (s32) (y - 0.344136 * (cb - 128) - 0.714136*(cr-128) ); |
126 | | b = (s32) (y + 1.772 * (cb - 128) ); |
127 | | |
128 | | #define TRUNC_8BIT(_a) if (_a<0) {_a = 0;} else if (_a>255) {_a=255;} |
129 | | TRUNC_8BIT(r) |
130 | | TRUNC_8BIT(g) |
131 | | TRUNC_8BIT(b) |
132 | | |
133 | | #else |
134 | 0 | y *= 1024; |
135 | 0 | r = (s32) (y + 1436 * (cr - 128)); |
136 | 0 | g = (s32) (y - 352 * (cb - 128) - 731*(cr-128) ); |
137 | 0 | b = (s32) (y + 1814 * (cb - 128) ); |
138 | |
|
139 | 0 | #define TRUNC_8BIT(_a) if (_a<0) {_a = 0;} else { u32 __a = (u32) _a; __a>>=10; if (__a>255) {__a=255;} _a = __a; } |
140 | 0 | TRUNC_8BIT(r) |
141 | 0 | TRUNC_8BIT(g) |
142 | 0 | TRUNC_8BIT(b) |
143 | |
|
144 | 0 | #endif |
145 | | |
146 | |
|
147 | 0 | return GF_COL_ARGB(a, r, g, b); |
148 | 0 | } |
149 | | |
150 | | u64 gf_evg_argb_to_ayuv_wide(GF_EVGSurface *surf, u64 col) |
151 | 0 | { |
152 | 0 | u16 a, y, cb, cr; |
153 | 0 | u32 r, g, b; |
154 | |
|
155 | 0 | a = (col>>48)&0xFFFF; |
156 | 0 | r = (col>>32)&0xFFFF; |
157 | 0 | g = (col>>16)&0xFFFF; |
158 | 0 | b = (col)&0xFFFF; |
159 | |
|
160 | | #ifndef YUV_USE_INT |
161 | | y = (u16) (0.299*r + 0.587 * g + 0.114 * b); |
162 | | cb = (u16) (-0.169*(s32)r - 0.331*(s32)g + 0.499*b + 32768); |
163 | | cr = (u16) (0.499 * r - 0.418*(s32)g - 0.0813*(s32)b + 32768); |
164 | | #else |
165 | 0 | u32 _v = 306*r + 601 * g + 117 * b; |
166 | 0 | y = (u16) (_v >> 10); |
167 | 0 | _v = (-173*(s32)r - 339*(s32)g + 511*b + 33554432); |
168 | 0 | cb = (u16) (_v >> 10); |
169 | 0 | _v = (511 * r - 428*(s32)g - 83*(s32)b + 33554432); |
170 | 0 | cr = (u16) (_v >> 10); |
171 | 0 | #endif |
172 | | |
173 | |
|
174 | 0 | return GF_COLW_ARGB(a, y, cb, cr); |
175 | 0 | } |
176 | | u64 gf_evg_ayuv_to_argb_wide(GF_EVGSurface *surf, u64 col) |
177 | 0 | { |
178 | 0 | u32 a; |
179 | 0 | s64 y, cb, cr; |
180 | 0 | s32 r, g, b; |
181 | 0 | a = (col>>48)&0xFFFF; |
182 | 0 | y = (col>>32)&0xFFFF; |
183 | 0 | cb = (col>>16)&0xFFFF; |
184 | 0 | cr = (col)&0xFFFF; |
185 | |
|
186 | | #ifndef YUV_USE_INT |
187 | | r = (s32) (y + 1.402 * (cr - 32768)); |
188 | | g = (s32) (y - 0.344136 * (cb - 32768) - 0.714136*(cr-32768) ); |
189 | | b = (s32) (y + 1.772 * (cb - 32768) ); |
190 | | #define TRUNC_16BIT(_a) if (_a<0) {_a = 0;} else if (_a>32768) {_a=32768;} |
191 | | TRUNC_16BIT(r) |
192 | | TRUNC_16BIT(g) |
193 | | TRUNC_16BIT(b) |
194 | | |
195 | | #else |
196 | 0 | y *= 1024; |
197 | 0 | r = (s32) (y + 1436 * (cr - 32768)); |
198 | 0 | g = (s32) (y - 352 * (cb - 32768) - 731*(cr-32768) ); |
199 | 0 | b = (s32) (y + 1814 * (cb - 32768) ); |
200 | |
|
201 | 0 | #define TRUNC_16BIT(_a) if (_a<0) {_a = 0;} else { u32 __a = (u32) _a; __a>>=10; if (__a>32768) {__a=32768;} _a = __a; } |
202 | 0 | TRUNC_16BIT(r) |
203 | 0 | TRUNC_16BIT(g) |
204 | 0 | TRUNC_16BIT(b) |
205 | |
|
206 | 0 | #endif |
207 | |
|
208 | 0 | return GF_COLW_ARGB(a, r, g, b); |
209 | 0 | } |
210 | | |
211 | | #if 0 //unused |
212 | | void evg_make_ayuv_color_mx(GF_ColorMatrix *cmat, GF_ColorMatrix *yuv_cmat) |
213 | | { |
214 | | GF_ColorMatrix cmx_y2r, cmx_r2y; |
215 | | gf_cmx_init(&cmx_r2y); |
216 | | gf_cmx_init(&cmx_y2r); |
217 | | cmx_r2y.identity = cmx_y2r.identity = GF_FALSE; |
218 | | |
219 | | //r = (s32) (y + 1.402 * (cr - 128)); |
220 | | cmx_y2r.m[0] = FIX_ONE; //y |
221 | | cmx_y2r.m[2] = FLT2FIX(1.402); //cr |
222 | | cmx_y2r.m[4] = FLT2FIX(-1.402 * 0.504); //tr |
223 | | |
224 | | //g = (s32) (y - 0.344136 * (cb - 128) - 0.714136*(cr-128) ); |
225 | | cmx_y2r.m[5] = FIX_ONE; //y |
226 | | cmx_y2r.m[6] = FLT2FIX(- 0.344136); //cb |
227 | | cmx_y2r.m[7] = FLT2FIX(- 0.714136); //cr |
228 | | cmx_y2r.m[9] = FLT2FIX(0.344136 * 0.504 + 0.714136*0.504); //tr |
229 | | |
230 | | //b = (s32) (y + 1.772 * (cb - 128) ); |
231 | | cmx_y2r.m[10] = FIX_ONE; //y |
232 | | cmx_y2r.m[11] = FLT2FIX(1.772); //cb |
233 | | cmx_y2r.m[14] = FLT2FIX(-1.772 * 0.504); //tr |
234 | | |
235 | | |
236 | | //y = (u8) (0.299*r + 0.587 * g + 0.114 * b); |
237 | | cmx_r2y.m[0] = FLT2FIX(0.299); //r |
238 | | cmx_r2y.m[1] = FLT2FIX(0.587); //g |
239 | | cmx_r2y.m[2] = FLT2FIX(0.114); //b |
240 | | |
241 | | |
242 | | //cb = (u8) (-0.169*(s32)r - 0.331*(s32)g + 0.499*b + 128); |
243 | | cmx_r2y.m[5] = FLT2FIX(-0.169); //r |
244 | | cmx_r2y.m[6] = FLT2FIX(-0.331); //g |
245 | | cmx_r2y.m[7] = FLT2FIX(0.499); //b |
246 | | cmx_r2y.m[9] = FLT2FIX(0.504); //tr |
247 | | |
248 | | //cr = (u8) (0.499 * r - 0.418*(s32)g - 0.0813*(s32)b + 128); |
249 | | cmx_r2y.m[10] = FLT2FIX(0.499); //r |
250 | | cmx_r2y.m[11] = FLT2FIX(-0.418); //g |
251 | | cmx_r2y.m[12] = FLT2FIX(-0.0813); //b |
252 | | cmx_r2y.m[14] = FLT2FIX(0.504); //tr |
253 | | |
254 | | gf_cmx_copy(yuv_cmat, &cmx_r2y); |
255 | | gf_cmx_multiply(yuv_cmat, cmat); |
256 | | gf_cmx_multiply(yuv_cmat, &cmx_y2r); |
257 | | } |
258 | | #endif |
259 | | |
260 | | /* |
261 | | YUV420p part |
262 | | */ |
263 | | |
264 | | static void overmask_yuv420p(u8 col_a, u8 cy, u8 *dst, u32 alpha) |
265 | 0 | { |
266 | 0 | s32 srca = col_a; |
267 | 0 | u32 srcc = cy; |
268 | 0 | s32 dstc = (*dst) & 0xFF; |
269 | |
|
270 | 0 | srca = mul255(srca, alpha); |
271 | 0 | *dst = mul255(srca, srcc - dstc) + dstc; |
272 | 0 | } |
273 | | |
274 | | static void overmask_yuv420p_const_run(u8 a, u8 val, u8 *ptr, u32 count, short x) |
275 | 0 | { |
276 | 0 | while (count) { |
277 | 0 | u8 dst = *(ptr); |
278 | 0 | *ptr = (u8) mul255(a, val - dst) + dst; |
279 | 0 | ptr ++; |
280 | 0 | count--; |
281 | 0 | } |
282 | 0 | } |
283 | | void evg_yuv420p_flush_uv_const(GF_EVGSurface *surf, EVGRasterCtx *rctx, u8 *surf_uv_alpha, s32 cu, s32 cv, s32 y) |
284 | 0 | { |
285 | 0 | u32 i, a; |
286 | 0 | u8 *pU = rctx->surf->pixels + rctx->surf->height * rctx->surf->pitch_y; |
287 | 0 | u8 *pV; |
288 | 0 | pU += y/2 * rctx->surf->pitch_y/2; |
289 | 0 | pV = pU + rctx->surf->height/2 * rctx->surf->pitch_y/2; |
290 | | |
291 | | //no need to swap u and V in const flush, they have been swaped when setting up the brush |
292 | | |
293 | | //we are at an odd line, write uv |
294 | 0 | for (i=0; i<rctx->surf->width; i+=2) { |
295 | 0 | u8 dst; |
296 | | |
297 | | //even line |
298 | 0 | a = rctx->uv_alpha[i] + rctx->uv_alpha[i+1]; |
299 | | //odd line |
300 | 0 | a += surf_uv_alpha[i] + surf_uv_alpha[i+1]; |
301 | |
|
302 | 0 | if (a) { |
303 | 0 | u8 *s_ptr_u, *s_ptr_v; |
304 | |
|
305 | 0 | a /= 4; |
306 | |
|
307 | 0 | s_ptr_u = pU + i / 2; |
308 | 0 | s_ptr_v = pV + i / 2; |
309 | 0 | if (a==0xFF) { |
310 | 0 | *s_ptr_u = (u8) cu; |
311 | 0 | *s_ptr_v = (u8) cv; |
312 | 0 | } else { |
313 | 0 | dst = *(s_ptr_u); |
314 | 0 | *s_ptr_u = (u8) mul255(a, cu - dst) + dst; |
315 | |
|
316 | 0 | dst = *(s_ptr_v); |
317 | 0 | *s_ptr_v = (u8) mul255(a, cv - dst) + dst; |
318 | 0 | } |
319 | 0 | } |
320 | 0 | } |
321 | 0 | memset(rctx->uv_alpha, 0, rctx->surf->uv_alpha_alloc); |
322 | 0 | } |
323 | | |
324 | | void evg_yuv420p_fill_const(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf, EVGRasterCtx *rctx) |
325 | 0 | { |
326 | 0 | u8 *pY = surf->pixels; |
327 | 0 | u8 *surf_uv_alpha; |
328 | 0 | s32 i; |
329 | 0 | u8 cy, cu, cv; |
330 | 0 | Bool write_uv = (y%2) ? GF_TRUE : GF_FALSE; |
331 | |
|
332 | 0 | if (surf->is_422) { |
333 | 0 | write_uv = GF_TRUE; |
334 | 0 | surf_uv_alpha = rctx->uv_alpha; |
335 | 0 | } |
336 | 0 | else if (write_uv) { |
337 | 0 | surf_uv_alpha = rctx->uv_alpha + surf->width; |
338 | 0 | } else { |
339 | 0 | surf_uv_alpha = rctx->uv_alpha; |
340 | 0 | } |
341 | |
|
342 | 0 | pY += y * surf->pitch_y; |
343 | |
|
344 | 0 | cy = GF_COL_R(surf->fill_col); |
345 | 0 | cu = GF_COL_G(surf->fill_col); |
346 | 0 | cv = GF_COL_B(surf->fill_col); |
347 | |
|
348 | 0 | for (i=0; i<count; i++) { |
349 | 0 | u32 a; |
350 | 0 | u8 *s_pY; |
351 | 0 | u32 len; |
352 | 0 | len = spans[i].len; |
353 | 0 | s_pY = pY + spans[i].x; |
354 | |
|
355 | 0 | a = spans[i].coverage; |
356 | 0 | if (a != 0xFF) { |
357 | 0 | overmask_yuv420p_const_run((u8)a, cy, s_pY, len, 0); |
358 | 0 | memset(surf_uv_alpha + spans[i].x, (u8)a, len); |
359 | 0 | } else { |
360 | 0 | while (len--) { |
361 | 0 | *(s_pY) = cy; |
362 | 0 | s_pY ++; |
363 | 0 | } |
364 | 0 | memset(surf_uv_alpha + spans[i].x, 0xFF, spans[i].len); |
365 | 0 | } |
366 | 0 | } |
367 | 0 | if (write_uv && !rctx->no_yuv_flush) { |
368 | 0 | surf->yuv_flush_uv(surf, rctx, surf_uv_alpha, cu, cv, y); |
369 | 0 | } |
370 | |
|
371 | 0 | } |
372 | | |
373 | | void evg_yuv420p_fill_const_a(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf, EVGRasterCtx *rctx) |
374 | 0 | { |
375 | 0 | u32 a; |
376 | 0 | u8 *pY = surf->pixels; |
377 | 0 | u8 *surf_uv_alpha; |
378 | 0 | s32 i; |
379 | 0 | u8 cy, cu, cv; |
380 | 0 | Bool write_uv = (y%2) ? GF_TRUE : GF_FALSE; |
381 | |
|
382 | 0 | if (surf->is_422) { |
383 | 0 | write_uv = GF_TRUE; |
384 | 0 | surf_uv_alpha = rctx->uv_alpha; |
385 | 0 | } else if (write_uv) { |
386 | 0 | surf_uv_alpha = rctx->uv_alpha + surf->width; |
387 | 0 | } else { |
388 | 0 | surf_uv_alpha = rctx->uv_alpha; |
389 | 0 | } |
390 | |
|
391 | 0 | pY += y * surf->pitch_y; |
392 | |
|
393 | 0 | cy = GF_COL_R(surf->fill_col); |
394 | 0 | cu = GF_COL_G(surf->fill_col); |
395 | 0 | cv = GF_COL_B(surf->fill_col); |
396 | 0 | a = GF_COL_A(surf->fill_col); |
397 | |
|
398 | 0 | if (surf->get_alpha) { |
399 | 0 | for (i=0; i<count; i++) { |
400 | 0 | u32 fin, j; |
401 | 0 | for (j=0; j<spans[i].len; j++) { |
402 | 0 | s32 x = spans[i].x + j; |
403 | 0 | u8 *s_pY = pY + x; |
404 | 0 | u8 aa = surf->get_alpha(surf->get_alpha_udta, a, x, y); |
405 | 0 | fin = mul255(aa, spans[i].coverage); |
406 | |
|
407 | 0 | overmask_yuv420p_const_run((u8)fin, cy, s_pY, 1, 0); |
408 | |
|
409 | 0 | memset(surf_uv_alpha + x, (u8)fin, 1); |
410 | 0 | } |
411 | 0 | } |
412 | 0 | } else { |
413 | 0 | for (i=0; i<count; i++) { |
414 | 0 | u8 *s_pY; |
415 | 0 | u32 fin, len; |
416 | 0 | len = spans[i].len; |
417 | 0 | s_pY = pY + spans[i].x; |
418 | 0 | fin = mul255(a, spans[i].coverage); |
419 | |
|
420 | 0 | overmask_yuv420p_const_run((u8)fin, cy, s_pY, len, 0); |
421 | |
|
422 | 0 | memset(surf_uv_alpha + spans[i].x, (u8)fin, len); |
423 | 0 | } |
424 | 0 | } |
425 | | //we are at an odd line, write uv |
426 | 0 | if (write_uv && !rctx->no_yuv_flush) |
427 | 0 | surf->yuv_flush_uv(surf, rctx, surf_uv_alpha, cu, cv, y); |
428 | 0 | } |
429 | | |
430 | | |
431 | | void evg_yuv420p_flush_uv_var(GF_EVGSurface *surf, EVGRasterCtx *rctx, u8 *surf_uv_alpha, s32 _cu, s32 _cv, s32 y) |
432 | 0 | { |
433 | 0 | u32 i; |
434 | 0 | u8 *pU, *pV; |
435 | 0 | pU = surf->pixels + surf->height *surf->pitch_y; |
436 | 0 | pU += y/2 * surf->pitch_y/2; |
437 | 0 | pV = pU + surf->height/2 * surf->pitch_y/2; |
438 | |
|
439 | 0 | if (surf->swap_uv) { |
440 | 0 | u8 *tmp = pU; |
441 | 0 | pU = pV; |
442 | 0 | pV = tmp; |
443 | 0 | } |
444 | |
|
445 | 0 | for (i=0; i<surf->width; i+=2) { |
446 | 0 | u32 a, a11, a12, a21, a22; |
447 | 0 | u32 idx1 = 3*i; |
448 | 0 | u32 idx2 = idx1 + 3; |
449 | 0 | gf_assert(idx1 < surf->uv_alpha_alloc ); |
450 | 0 | gf_assert(idx2 < surf->uv_alpha_alloc ); |
451 | | //get alpha |
452 | 0 | a11 = (u32)rctx->uv_alpha[idx1]; |
453 | 0 | a12 = (u32)rctx->uv_alpha[idx2]; |
454 | 0 | a21 = (u32)surf_uv_alpha[idx1]; |
455 | 0 | a22 = (u32)surf_uv_alpha[idx2]; |
456 | |
|
457 | 0 | a = a11 + a12 + a21 + a22; |
458 | 0 | if (a) { |
459 | 0 | u8 cdst=0; |
460 | 0 | u32 chroma_u, chroma_v, c11, c12, c21, c22; |
461 | |
|
462 | 0 | a /= 4; |
463 | | //get cb |
464 | 0 | idx1 += 1; |
465 | 0 | idx2 += 1; |
466 | |
|
467 | 0 | if (a!=0xFF) { |
468 | 0 | cdst = *pU; |
469 | 0 | } |
470 | 0 | c11 = (u32)rctx->uv_alpha[idx1]; |
471 | 0 | if (a11!=0xFF) c11 = mul255_zero(a11, c11 - cdst) + cdst; |
472 | 0 | c12 = (u32)rctx->uv_alpha[idx2]; |
473 | 0 | if (a12!=0xFF) c12 = mul255_zero(a12, c12 - cdst) + cdst; |
474 | 0 | c21 = (u32)surf_uv_alpha[idx1]; |
475 | 0 | if (a21!=0xFF) c21 = mul255_zero(a21, c21 - cdst) + cdst; |
476 | 0 | c22 = (u32)surf_uv_alpha[idx2]; |
477 | 0 | if (a22!=0xFF) c22 = mul255_zero(a22, c22 - cdst) + cdst; |
478 | |
|
479 | 0 | chroma_u = c11 + c12 + c21 + c22; |
480 | 0 | chroma_u /= 4; |
481 | | |
482 | | //get cr |
483 | 0 | idx1 += 1; |
484 | 0 | idx2 += 1; |
485 | |
|
486 | 0 | if (a!=0xFF) { |
487 | 0 | cdst = *pV; |
488 | 0 | } |
489 | 0 | c11 = (u32)rctx->uv_alpha[idx1]; |
490 | 0 | if (a11!=0xFF) c11 = mul255_zero(a11, c11 - cdst) + cdst; |
491 | 0 | c12 = (u32)rctx->uv_alpha[idx2]; |
492 | 0 | if (a12!=0xFF) c12 = mul255_zero(a12, c12 - cdst) + cdst; |
493 | 0 | c21 = (u32)surf_uv_alpha[idx1]; |
494 | 0 | if (a21!=0xFF) c21 = mul255_zero(a21, c21 - cdst) + cdst; |
495 | 0 | c22 = (u32)surf_uv_alpha[idx2]; |
496 | 0 | if (a22!=0xFF) c22 = mul255_zero(a22, c22 - cdst) + cdst; |
497 | |
|
498 | 0 | chroma_v = c11 + c12 + c21 + c22; |
499 | 0 | chroma_v /= 4; |
500 | |
|
501 | 0 | *pU = chroma_u; |
502 | 0 | *pV = chroma_v; |
503 | 0 | } |
504 | 0 | pU++; |
505 | 0 | pV++; |
506 | 0 | } |
507 | | //reset for next pass |
508 | 0 | memset(rctx->uv_alpha, 0, surf->uv_alpha_alloc); |
509 | |
|
510 | 0 | } |
511 | | |
512 | | void evg_yuv420p_fill_var(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf, EVGRasterCtx *rctx) |
513 | 0 | { |
514 | 0 | s32 i; |
515 | 0 | u8 *pY = surf->pixels; |
516 | 0 | u8 *surf_uv_alpha; |
517 | 0 | Bool write_uv = (y%2) ? GF_TRUE : GF_FALSE; |
518 | |
|
519 | 0 | if (surf->is_422) { |
520 | 0 | write_uv = GF_TRUE; |
521 | 0 | surf_uv_alpha = rctx->uv_alpha; |
522 | 0 | } else if (write_uv) { |
523 | | //second line of storage (we store alpha, cr, cb for each pixel) |
524 | 0 | surf_uv_alpha = rctx->uv_alpha + 3*surf->width; |
525 | 0 | } else { |
526 | | //first line of storage |
527 | 0 | surf_uv_alpha = rctx->uv_alpha; |
528 | 0 | } |
529 | |
|
530 | 0 | pY += y * surf->pitch_y; |
531 | |
|
532 | 0 | for (i=0; i<count; i++) { |
533 | 0 | u8 spanalpha, col_a; |
534 | 0 | u8 *s_pY; |
535 | 0 | short x; |
536 | 0 | u32 *p_col; |
537 | 0 | u32 len; |
538 | 0 | len = spans[i].len; |
539 | 0 | p_col = surf->fill_run(surf->sten, rctx, &spans[i], y); |
540 | 0 | spanalpha = spans[i].coverage; |
541 | |
|
542 | 0 | s_pY = pY + spans[i].x; |
543 | 0 | x = spans[i].x; |
544 | |
|
545 | 0 | while (len--) { |
546 | 0 | u32 col = *p_col; |
547 | 0 | col_a = GF_COL_A(col); |
548 | 0 | if (col_a) { |
549 | 0 | u8 cy, cb, cr; |
550 | 0 | u32 idx=3*x; |
551 | | //col is directly packed as AYCbCr |
552 | 0 | cy = GF_COL_R(col); |
553 | 0 | cb = GF_COL_G(col); |
554 | 0 | cr = GF_COL_B(col); |
555 | |
|
556 | 0 | if ((spanalpha!=0xFF) || (col_a != 0xFF)) { |
557 | 0 | overmask_yuv420p(col_a, cy, s_pY, spanalpha); |
558 | |
|
559 | 0 | u8 a = mul255(col_a, spanalpha); |
560 | 0 | surf_uv_alpha[idx] = a; |
561 | 0 | } else { |
562 | 0 | *s_pY = cy; |
563 | 0 | surf_uv_alpha[idx] = 0xFF; |
564 | 0 | } |
565 | 0 | surf_uv_alpha[idx+1] = cb; |
566 | 0 | surf_uv_alpha[idx+2] = cr; |
567 | 0 | } |
568 | 0 | s_pY++; |
569 | 0 | p_col++; |
570 | 0 | x++; |
571 | 0 | } |
572 | 0 | } |
573 | | //compute final u,v for both lines |
574 | 0 | if (write_uv && !rctx->no_yuv_flush) { |
575 | 0 | surf->yuv_flush_uv(surf, rctx, surf_uv_alpha, 0, 0, y); |
576 | 0 | } |
577 | 0 | } |
578 | | |
579 | | GF_Err evg_surface_clear_yuv420p(GF_EVGSurface *_surf, GF_IRect rc, GF_Color col) |
580 | 0 | { |
581 | 0 | s32 i; |
582 | 0 | u8 cy, cb, cr; |
583 | 0 | GF_EVGSurface *surf = (GF_EVGSurface *)_surf; |
584 | 0 | u8 *pY, *pU, *pV; |
585 | |
|
586 | 0 | pY = surf->pixels + rc.y * surf->pitch_y + rc.x; |
587 | 0 | pU = surf->pixels + surf->height * surf->pitch_y + rc.y/2 * surf->pitch_y/2 + rc.x/2; |
588 | 0 | pV = surf->pixels + 5*surf->height * surf->pitch_y/4 + rc.y/2 * surf->pitch_y/2 + rc.x/2; |
589 | 0 | if (surf->swap_uv) { |
590 | 0 | u8 *tmp = pU; |
591 | 0 | pU = pV; |
592 | 0 | pV = tmp; |
593 | 0 | } |
594 | |
|
595 | 0 | gf_evg_rgb_to_yuv(surf, col, &cy, &cb, &cr); |
596 | |
|
597 | 0 | if (!rc.x && !rc.y && ((u32) rc.width==_surf->width) && ((u32) rc.height==_surf->height)) { |
598 | 0 | memset(pY, cy, _surf->pitch_y * _surf->height); |
599 | 0 | memset(pU, cb, _surf->pitch_y/2 * _surf->height/2); |
600 | 0 | memset(pV, cr, _surf->pitch_y/2 * _surf->height/2); |
601 | 0 | return GF_OK; |
602 | 0 | } |
603 | | |
604 | 0 | for (i = 0; i < rc.height; i++) { |
605 | 0 | memset(pY, cy, rc.width); |
606 | 0 | pY += surf->pitch_y; |
607 | 0 | if (i%2) { |
608 | 0 | memset(pU, cb, rc.width/2); |
609 | 0 | pU += surf->pitch_y/2; |
610 | 0 | memset(pV, cr, rc.width/2); |
611 | 0 | pV += surf->pitch_y/2; |
612 | 0 | } |
613 | 0 | } |
614 | 0 | return GF_OK; |
615 | 0 | } |
616 | | |
617 | | |
618 | | /* |
619 | | NV12 / NV21 part |
620 | | */ |
621 | | |
622 | | |
623 | | void evg_nv12_flush_uv_const(GF_EVGSurface *surf, EVGRasterCtx *rctx, u8 *surf_uv_alpha, s32 cu, s32 cv, s32 y) |
624 | 0 | { |
625 | 0 | u32 i, a; |
626 | 0 | u8 *pU = surf->pixels + surf->height *surf->pitch_y; |
627 | 0 | pU += y/2 * surf->pitch_y; |
628 | |
|
629 | 0 | for (i=0; i<surf->width; i+=2) { |
630 | 0 | u8 dst; |
631 | | |
632 | | //even line |
633 | 0 | a = rctx->uv_alpha[i] + rctx->uv_alpha[i+1]; |
634 | | //odd line |
635 | 0 | a += surf_uv_alpha[i] + surf_uv_alpha[i+1]; |
636 | |
|
637 | 0 | if (a) { |
638 | 0 | u8 *s_ptr; |
639 | 0 | a /= 4; |
640 | |
|
641 | 0 | s_ptr = pU + i; |
642 | 0 | if (a==0xFF) { |
643 | 0 | *s_ptr = cu; |
644 | |
|
645 | 0 | s_ptr++; |
646 | 0 | *s_ptr = cv; |
647 | 0 | } else { |
648 | 0 | dst = *(s_ptr); |
649 | 0 | *s_ptr = (u8) mul255(a, cu - dst) + dst; |
650 | |
|
651 | 0 | s_ptr++; |
652 | 0 | dst = *(s_ptr); |
653 | 0 | *s_ptr = (u8) mul255(a, cv - dst) + dst; |
654 | 0 | } |
655 | 0 | } |
656 | 0 | } |
657 | 0 | memset(rctx->uv_alpha, 0, surf->uv_alpha_alloc); |
658 | 0 | } |
659 | | |
660 | | void evg_nv12_flush_uv_var(GF_EVGSurface *surf, EVGRasterCtx *rctx, u8 *surf_uv_alpha, s32 cu, s32 cv, s32 y) |
661 | 0 | { |
662 | 0 | u32 i; |
663 | 0 | u8 *pU; |
664 | 0 | pU = surf->pixels + surf->height *surf->pitch_y; |
665 | 0 | pU += y/2 * surf->pitch_y; |
666 | |
|
667 | 0 | for (i=0; i<surf->width; i+=2) { |
668 | 0 | u32 a, a11, a12, a21, a22; |
669 | |
|
670 | 0 | u32 idx1=3*i; |
671 | 0 | u32 idx2=3*i + 3; |
672 | | |
673 | | //get alpha |
674 | 0 | a11 = (u32)rctx->uv_alpha[idx1]; |
675 | 0 | a12 = (u32)rctx->uv_alpha[idx2]; |
676 | 0 | a21 = (u32)surf_uv_alpha[idx1]; |
677 | 0 | a22 = (u32)surf_uv_alpha[idx2]; |
678 | 0 | a = a11+a12+a21+a22; |
679 | |
|
680 | 0 | if (a) { |
681 | 0 | u8 cdst=0; |
682 | 0 | u32 chroma_u, chroma_v, c11, c12, c21, c22; |
683 | |
|
684 | 0 | a /= 4; |
685 | | |
686 | | //get cb |
687 | 0 | idx1 += 1; |
688 | 0 | idx2 += 1; |
689 | 0 | if (a!=0xFF) |
690 | 0 | cdst = pU[surf->idx_u]; |
691 | |
|
692 | 0 | c11 = (u32)rctx->uv_alpha[idx1]; |
693 | 0 | if (a11!=0xFF) c11 = mul255_zero(a11, c11 - cdst) + cdst; |
694 | 0 | c12 = (u32)rctx->uv_alpha[idx2]; |
695 | 0 | if (a12!=0xFF) c12 = mul255_zero(a12, c12 - cdst) + cdst; |
696 | 0 | c21 = (u32)surf_uv_alpha[idx1]; |
697 | 0 | if (a21!=0xFF) c21 = mul255_zero(a21, c21 - cdst) + cdst; |
698 | 0 | c22 = (u32)surf_uv_alpha[idx2]; |
699 | 0 | if (a22!=0xFF) c22 = mul255_zero(a22, c22 - cdst) + cdst; |
700 | |
|
701 | 0 | chroma_u = c11 + c12 + c21 + c22; |
702 | 0 | chroma_u /= 4; |
703 | | |
704 | | //get cr |
705 | 0 | idx1 += 1; |
706 | 0 | idx2 += 1; |
707 | |
|
708 | 0 | if (a!=0xFF) |
709 | 0 | cdst = pU[surf->idx_v]; |
710 | |
|
711 | 0 | c11 = (u32)rctx->uv_alpha[idx1]; |
712 | 0 | if (a11!=0xFF) c11 = mul255_zero(a11, c11 - cdst) + cdst; |
713 | 0 | c12 = (u32)rctx->uv_alpha[idx2]; |
714 | 0 | if (a12!=0xFF) c12 = mul255_zero(a12, c12 - cdst) + cdst; |
715 | 0 | c21 = (u32)surf_uv_alpha[idx1]; |
716 | 0 | if (a21!=0xFF) c21 = mul255_zero(a21, c21 - cdst) + cdst; |
717 | 0 | c22 = (u32)surf_uv_alpha[idx2]; |
718 | 0 | if (a22!=0xFF) c22 = mul255_zero(a22, c22 - cdst) + cdst; |
719 | |
|
720 | 0 | chroma_v = c11 + c12 + c21 + c22; |
721 | 0 | chroma_v /= 4; |
722 | |
|
723 | 0 | pU[surf->idx_u] = chroma_u; |
724 | 0 | pU[surf->idx_v] = chroma_v; |
725 | 0 | } |
726 | 0 | pU+=2; |
727 | 0 | } |
728 | | //reset for next pass |
729 | 0 | memset(rctx->uv_alpha, 0, surf->uv_alpha_alloc); |
730 | 0 | } |
731 | | |
732 | | |
733 | | GF_Err evg_surface_clear_nv12(GF_EVGSurface *_surf, GF_IRect rc, GF_Color col, Bool swap_uv) |
734 | 0 | { |
735 | 0 | s32 i; |
736 | 0 | u8 cy, cb, cr; |
737 | 0 | GF_EVGSurface *surf = (GF_EVGSurface *)_surf; |
738 | 0 | u8 *pY = surf->pixels; |
739 | 0 | u8 *pU = surf->pixels + surf->height *surf->pitch_y; |
740 | 0 | u8 *pU_first; |
741 | |
|
742 | 0 | pY += rc.y * surf->pitch_y; |
743 | 0 | pU += rc.y/2 * surf->pitch_y; |
744 | |
|
745 | 0 | pY += rc.x; |
746 | 0 | pU += rc.x/2; |
747 | 0 | pU_first = pU; |
748 | |
|
749 | 0 | gf_evg_rgb_to_yuv(surf, col, &cy, &cb, &cr); |
750 | |
|
751 | 0 | if (swap_uv) { |
752 | 0 | u8 t = cb; |
753 | 0 | cb = cr; |
754 | 0 | cr = t; |
755 | 0 | } |
756 | 0 | for (i = 0; i < rc.height; i++) { |
757 | 0 | memset(pY, cy, rc.width); |
758 | 0 | pY += surf->pitch_y; |
759 | 0 | if (i%2) { |
760 | | //first uv line, build it |
761 | 0 | if (i==1) { |
762 | 0 | s32 j; |
763 | 0 | for (j=0; j<rc.width/2; j++) { |
764 | 0 | *pU = cb; |
765 | 0 | pU++; |
766 | 0 | *pU = cr; |
767 | 0 | pU++; |
768 | 0 | } |
769 | 0 | } |
770 | | //non-first uv line recopy from first |
771 | 0 | else { |
772 | 0 | memcpy(pU, pU_first, rc.width); |
773 | 0 | pU += surf->pitch_y; |
774 | 0 | } |
775 | 0 | } |
776 | 0 | } |
777 | 0 | return GF_OK; |
778 | 0 | } |
779 | | |
780 | | |
781 | | /* |
782 | | YUV422 part |
783 | | */ |
784 | | |
785 | | void evg_yuv422p_flush_uv_const(GF_EVGSurface *surf, EVGRasterCtx *rctx, u8 *surf_uv_alpha, s32 cu, s32 cv, s32 y) |
786 | 0 | { |
787 | 0 | u32 i, a; |
788 | 0 | u8 *pU = surf->pixels + surf->height *surf->pitch_y; |
789 | 0 | u8 *pV; |
790 | 0 | pU += y * surf->pitch_y/2; |
791 | 0 | pV = pU + surf->height * surf->pitch_y/2; |
792 | |
|
793 | 0 | for (i=0; i<surf->width; i+=2) { |
794 | 0 | u8 dst; |
795 | |
|
796 | 0 | a = rctx->uv_alpha[i] + rctx->uv_alpha[i+1]; |
797 | |
|
798 | 0 | if (a) { |
799 | 0 | u8 *s_ptr_u, *s_ptr_v; |
800 | |
|
801 | 0 | a /= 2; |
802 | 0 | s_ptr_u = pU + i / 2; |
803 | 0 | s_ptr_v = pV + i / 2; |
804 | 0 | if (a==0xFF) { |
805 | 0 | *s_ptr_u = (u8) cu; |
806 | 0 | *s_ptr_v = (u8) cv; |
807 | 0 | } else { |
808 | 0 | dst = *(s_ptr_u); |
809 | 0 | *s_ptr_u = (u8) mul255(a, cu - dst) + dst; |
810 | |
|
811 | 0 | dst = *(s_ptr_v); |
812 | 0 | *s_ptr_v = (u8) mul255(a, cv - dst) + dst; |
813 | 0 | } |
814 | 0 | } |
815 | 0 | } |
816 | 0 | memset(rctx->uv_alpha, 0, surf->uv_alpha_alloc); |
817 | 0 | } |
818 | | |
819 | | void evg_yuv422p_flush_uv_var(GF_EVGSurface *surf, EVGRasterCtx *rctx, u8 *surf_uv_alpha, s32 _cu, s32 _cv, s32 y) |
820 | 0 | { |
821 | 0 | u32 i; |
822 | 0 | u8 *pU, *pV; |
823 | 0 | pU = surf->pixels + surf->height *surf->pitch_y; |
824 | 0 | pU += y * surf->pitch_y/2; |
825 | 0 | pV = pU + surf->height * surf->pitch_y/2; |
826 | |
|
827 | 0 | for (i=0; i<surf->width; i+=2) { |
828 | 0 | u32 a, a1, a2; |
829 | 0 | u32 idx1=3*i; |
830 | 0 | u32 idx2=3*i + 3; |
831 | | //get alpha |
832 | 0 | a1 = (u32)rctx->uv_alpha[idx1]; |
833 | 0 | a2 = (u32)rctx->uv_alpha[idx2]; |
834 | 0 | a = a1+a2; |
835 | 0 | if (a) { |
836 | 0 | u8 cdst=0; |
837 | 0 | u32 chroma_u, chroma_v, c1, c2; |
838 | |
|
839 | 0 | a /= 2; |
840 | | |
841 | | //get cb |
842 | 0 | if (a != 0xFF) |
843 | 0 | cdst = *pU; |
844 | |
|
845 | 0 | c1 = (u32)rctx->uv_alpha[idx1+1]; |
846 | 0 | if (a1!=0xFF) c1 = mul255_zero(a1, c1 - cdst) + cdst; |
847 | 0 | c2 = (u32)rctx->uv_alpha[idx2+1]; |
848 | 0 | if (a2!=0xFF) c2 = mul255_zero(a2, c1 - cdst) + cdst; |
849 | 0 | chroma_u = c1 + c2; |
850 | 0 | chroma_u /= 2; |
851 | | |
852 | | //get cb |
853 | 0 | if (a != 0xFF) |
854 | 0 | cdst = *pV; |
855 | |
|
856 | 0 | c1 = (u32)rctx->uv_alpha[idx1+2]; |
857 | 0 | if (a1!=0xFF) c1 = mul255_zero(a1, c1 - cdst) + cdst; |
858 | 0 | c2 = (u32)rctx->uv_alpha[idx2+2]; |
859 | 0 | if (a2!=0xFF) c2 = mul255_zero(a2, c1 - cdst) + cdst; |
860 | 0 | chroma_v = c1 + c2; |
861 | 0 | chroma_v /= 2; |
862 | | |
863 | |
|
864 | 0 | *pU = chroma_u; |
865 | 0 | *pV = chroma_v; |
866 | 0 | } |
867 | 0 | pU++; |
868 | 0 | pV++; |
869 | 0 | } |
870 | | //reset for next pass |
871 | 0 | memset(rctx->uv_alpha, 0, surf->uv_alpha_alloc); |
872 | 0 | } |
873 | | |
874 | | |
875 | | GF_Err evg_surface_clear_yuv422p(GF_EVGSurface *_surf, GF_IRect rc, GF_Color col) |
876 | 0 | { |
877 | 0 | s32 i; |
878 | 0 | u8 cy, cb, cr; |
879 | 0 | GF_EVGSurface *surf = (GF_EVGSurface *)_surf; |
880 | 0 | u8 *pY = surf->pixels; |
881 | 0 | u8 *pU = surf->pixels + surf->height *surf->pitch_y; |
882 | 0 | u8 *pV; |
883 | |
|
884 | 0 | pY += rc.y * surf->pitch_y; |
885 | 0 | pU += rc.y/2 * surf->pitch_y/2; |
886 | 0 | pV = pU + surf->height/2 * surf->pitch_y/2; |
887 | |
|
888 | 0 | pY += rc.x; |
889 | 0 | pU += rc.x/2; |
890 | 0 | pV += rc.x/2; |
891 | |
|
892 | 0 | gf_evg_rgb_to_yuv(surf, col, &cy, &cb, &cr); |
893 | |
|
894 | 0 | if (!rc.x && !rc.y && ((u32) rc.width==_surf->width) && ((u32) rc.height==_surf->height)) { |
895 | 0 | memset(pY, cy, _surf->pitch_y * _surf->height); |
896 | 0 | memset(pU, cb, _surf->pitch_y/2 * _surf->height); |
897 | 0 | memset(pV, cr, _surf->pitch_y/2 * _surf->height); |
898 | 0 | return GF_OK; |
899 | 0 | } |
900 | | |
901 | | |
902 | 0 | for (i = 0; i < rc.height; i++) { |
903 | 0 | memset(pY, cy, rc.width); |
904 | 0 | pY += surf->pitch_y; |
905 | 0 | memset(pU, cb, rc.width/2); |
906 | 0 | pU += surf->pitch_y/2; |
907 | 0 | memset(pV, cr, rc.width/2); |
908 | 0 | pV += surf->pitch_y/2; |
909 | 0 | } |
910 | 0 | return GF_OK; |
911 | 0 | } |
912 | | |
913 | | /* |
914 | | YUV444 part |
915 | | */ |
916 | | |
917 | | void evg_yuv444p_fill_const(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf, EVGRasterCtx *rctx) |
918 | 0 | { |
919 | 0 | u8 *pY, *pU, *pV; |
920 | 0 | s32 i; |
921 | 0 | u8 cy, cu, cv; |
922 | |
|
923 | 0 | pY = surf->pixels + y * surf->pitch_y; |
924 | 0 | pU = surf->pixels + surf->height*surf->pitch_y + y * surf->pitch_y; |
925 | 0 | pV = surf->pixels + 2*surf->height*surf->pitch_y + y * surf->pitch_y; |
926 | |
|
927 | 0 | cy = GF_COL_R(surf->fill_col); |
928 | 0 | cu = GF_COL_G(surf->fill_col); |
929 | 0 | cv = GF_COL_B(surf->fill_col); |
930 | |
|
931 | 0 | for (i=0; i<count; i++) { |
932 | 0 | u32 a; |
933 | 0 | u8 *s_pY, *s_pU, *s_pV; |
934 | 0 | u32 len; |
935 | 0 | len = spans[i].len; |
936 | 0 | s_pY = pY + spans[i].x; |
937 | 0 | s_pU = pU + spans[i].x; |
938 | 0 | s_pV = pV + spans[i].x; |
939 | |
|
940 | 0 | a = spans[i].coverage; |
941 | 0 | if (a != 0xFF) { |
942 | 0 | overmask_yuv420p_const_run((u8)a, cy, s_pY, len, 0); |
943 | 0 | overmask_yuv420p_const_run((u8)a, cu, s_pU, len, 0); |
944 | 0 | overmask_yuv420p_const_run((u8)a, cv, s_pV, len, 0); |
945 | 0 | } else { |
946 | 0 | while (len--) { |
947 | 0 | *(s_pY) = cy; |
948 | 0 | s_pY ++; |
949 | 0 | *(s_pU) = cu; |
950 | 0 | s_pU ++; |
951 | 0 | *(s_pV) = cv; |
952 | 0 | s_pV ++; |
953 | 0 | } |
954 | 0 | } |
955 | 0 | } |
956 | 0 | } |
957 | | |
958 | | void evg_yuv444p_fill_const_a(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf, EVGRasterCtx *rctx) |
959 | 0 | { |
960 | 0 | u32 a; |
961 | 0 | u8 *pY, *pU, *pV; |
962 | 0 | s32 i; |
963 | 0 | u8 cy, cu, cv; |
964 | |
|
965 | 0 | pY = surf->pixels + y * surf->pitch_y; |
966 | 0 | pU = surf->pixels + surf->height*surf->pitch_y + y * surf->pitch_y; |
967 | 0 | pV = surf->pixels + 2*surf->height*surf->pitch_y + y * surf->pitch_y; |
968 | |
|
969 | 0 | cy = GF_COL_R(surf->fill_col); |
970 | 0 | cu = GF_COL_G(surf->fill_col); |
971 | 0 | cv = GF_COL_B(surf->fill_col); |
972 | 0 | a = GF_COL_A(surf->fill_col); |
973 | |
|
974 | 0 | if (surf->get_alpha) { |
975 | 0 | for (i=0; i<count; i++) { |
976 | 0 | u32 j; |
977 | 0 | for (j=0; j<spans[i].len; j++) { |
978 | 0 | u8 *s_pY, *s_pU, *s_pV; |
979 | 0 | u32 fin; |
980 | 0 | s32 x = spans[i].x + j; |
981 | 0 | s_pY = pY + x; |
982 | 0 | s_pU = pU + x; |
983 | 0 | s_pV = pV + x; |
984 | 0 | u8 aa = surf->get_alpha(surf->get_alpha_udta, a, x, y); |
985 | 0 | fin = mul255(aa, spans[i].coverage); |
986 | |
|
987 | 0 | overmask_yuv420p_const_run((u8)fin, cy, s_pY, 1, 0); |
988 | 0 | overmask_yuv420p_const_run((u8)fin, cu, s_pU, 1, 0); |
989 | 0 | overmask_yuv420p_const_run((u8)fin, cv, s_pV, 1, 0); |
990 | 0 | } |
991 | 0 | } |
992 | 0 | } else { |
993 | 0 | for (i=0; i<count; i++) { |
994 | 0 | u8 *s_pY, *s_pU, *s_pV; |
995 | 0 | u32 fin, len; |
996 | 0 | len = spans[i].len; |
997 | 0 | s_pY = pY + spans[i].x; |
998 | 0 | s_pU = pU + spans[i].x; |
999 | 0 | s_pV = pV + spans[i].x; |
1000 | 0 | fin = mul255(a, spans[i].coverage); |
1001 | |
|
1002 | 0 | overmask_yuv420p_const_run((u8)fin, cy, s_pY, len, 0); |
1003 | 0 | overmask_yuv420p_const_run((u8)fin, cu, s_pU, len, 0); |
1004 | 0 | overmask_yuv420p_const_run((u8)fin, cv, s_pV, len, 0); |
1005 | 0 | } |
1006 | 0 | } |
1007 | 0 | } |
1008 | | |
1009 | | void evg_yuv444p_fill_var(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf, EVGRasterCtx *rctx) |
1010 | 0 | { |
1011 | 0 | s32 i; |
1012 | 0 | u8 *pY, *pU, *pV; |
1013 | |
|
1014 | 0 | pY = surf->pixels + y * surf->pitch_y; |
1015 | 0 | pU = pY + surf->height*surf->pitch_y; |
1016 | 0 | pV = pU + surf->height*surf->pitch_y; |
1017 | |
|
1018 | 0 | for (i=0; i<count; i++) { |
1019 | 0 | u8 spanalpha, col_a; |
1020 | 0 | u32 len; |
1021 | 0 | u32 *p_col; |
1022 | 0 | u8 *s_pY, *s_pU, *s_pV; |
1023 | 0 | len = spans[i].len; |
1024 | 0 | p_col = surf->fill_run(surf->sten, rctx, &spans[i], y); |
1025 | 0 | spanalpha = spans[i].coverage; |
1026 | |
|
1027 | 0 | s_pY = pY + spans[i].x; |
1028 | 0 | s_pU = pU + spans[i].x; |
1029 | 0 | s_pV = pV + spans[i].x; |
1030 | |
|
1031 | 0 | while (len--) { |
1032 | 0 | u32 col = *p_col; |
1033 | 0 | col_a = GF_COL_A(col); |
1034 | 0 | if (col_a) { |
1035 | 0 | u8 cy, cb, cr; |
1036 | 0 | cy = GF_COL_R(col); |
1037 | 0 | cb = GF_COL_G(col); |
1038 | 0 | cr = GF_COL_B(col); |
1039 | |
|
1040 | 0 | if ((spanalpha!=0xFF) || (col_a != 0xFF)) { |
1041 | 0 | overmask_yuv420p(col_a, cy, s_pY, spanalpha); |
1042 | 0 | overmask_yuv420p(col_a, cb, s_pU, spanalpha); |
1043 | 0 | overmask_yuv420p(col_a, cr, s_pV, spanalpha); |
1044 | 0 | } else { |
1045 | 0 | *s_pY = cy; |
1046 | 0 | *s_pU = cb; |
1047 | 0 | *s_pV = cr; |
1048 | 0 | } |
1049 | 0 | } |
1050 | 0 | s_pY++; |
1051 | 0 | s_pU++; |
1052 | 0 | s_pV++; |
1053 | 0 | p_col++; |
1054 | 0 | } |
1055 | 0 | } |
1056 | 0 | } |
1057 | | |
1058 | | GF_Err evg_surface_clear_yuv444p(GF_EVGSurface *_surf, GF_IRect rc, GF_Color col) |
1059 | 0 | { |
1060 | 0 | s32 i; |
1061 | 0 | u8 cy, cb, cr; |
1062 | 0 | GF_EVGSurface *surf = (GF_EVGSurface *)_surf; |
1063 | 0 | u8 *pY = surf->pixels; |
1064 | 0 | u8 *pU = surf->pixels + surf->height *surf->pitch_y; |
1065 | 0 | u8 *pV; |
1066 | |
|
1067 | 0 | pY += rc.y * surf->pitch_y; |
1068 | 0 | pU += rc.y * surf->pitch_y; |
1069 | 0 | pV = pU + surf->height * surf->pitch_y; |
1070 | |
|
1071 | 0 | pY += rc.x; |
1072 | 0 | pU += rc.x; |
1073 | 0 | pV += rc.x; |
1074 | |
|
1075 | 0 | gf_evg_rgb_to_yuv(surf, col, &cy, &cb, &cr); |
1076 | |
|
1077 | 0 | if (!rc.x && !rc.y && ((u32) rc.width==_surf->width) && ((u32) rc.height==_surf->height)) { |
1078 | 0 | memset(pY, cy, _surf->pitch_y * _surf->height); |
1079 | 0 | memset(pU, cb, _surf->pitch_y * _surf->height); |
1080 | 0 | memset(pV, cr, _surf->pitch_y * _surf->height); |
1081 | 0 | return GF_OK; |
1082 | 0 | } |
1083 | | |
1084 | 0 | for (i = 0; i < rc.height; i++) { |
1085 | 0 | memset(pY, cy, rc.width); |
1086 | 0 | pY += surf->pitch_y; |
1087 | 0 | memset(pU, cb, rc.width); |
1088 | 0 | pU += surf->pitch_y; |
1089 | 0 | memset(pV, cr, rc.width); |
1090 | 0 | pV += surf->pitch_y; |
1091 | 0 | } |
1092 | 0 | return GF_OK; |
1093 | 0 | } |
1094 | | |
1095 | | |
1096 | | /* |
1097 | | YUYV part |
1098 | | */ |
1099 | | |
1100 | | static void overmask_yuvy(u8 *dst, u8 c, u32 alpha) |
1101 | 0 | { |
1102 | 0 | s32 srca = alpha; |
1103 | 0 | u32 srcc = c; |
1104 | 0 | s32 dstc = (*dst) & 0xFF; |
1105 | 0 | *dst = mul255(srca, srcc - dstc) + dstc; |
1106 | 0 | } |
1107 | | void evg_yuyv_fill_const(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf, EVGRasterCtx *rctx) |
1108 | 0 | { |
1109 | 0 | u8 *pY; |
1110 | 0 | s32 i; |
1111 | 0 | u8 cy, cu, cv; |
1112 | |
|
1113 | 0 | if (!count) return; |
1114 | | |
1115 | 0 | pY = surf->pixels + y * surf->pitch_y; |
1116 | 0 | cy = GF_COL_R(surf->fill_col); |
1117 | 0 | cu = GF_COL_G(surf->fill_col); |
1118 | 0 | cv = GF_COL_B(surf->fill_col); |
1119 | |
|
1120 | 0 | for (i=0; i<count; i++) { |
1121 | 0 | u8 *s_pY; |
1122 | 0 | u32 len; |
1123 | 0 | len = spans[i].len; |
1124 | | //get start of yuyv block: devide x by 2, multiply by 4 (two Y pix packed in 4 bytes) |
1125 | 0 | s_pY = pY + (spans[i].x/2) * 4; |
1126 | | //move to first Y in block |
1127 | 0 | s_pY += surf->idx_y1; |
1128 | | //if odd pixel move to next one |
1129 | 0 | if (spans[i].x%2) s_pY += 2; |
1130 | |
|
1131 | 0 | if (spans[i].coverage != 0xFF) { |
1132 | 0 | memset(rctx->uv_alpha + spans[i].x, spans[i].coverage, len); |
1133 | 0 | while (len--) { |
1134 | 0 | overmask_yuvy(s_pY, cy, spans[i].coverage); |
1135 | 0 | s_pY += 2; |
1136 | 0 | } |
1137 | 0 | } else { |
1138 | 0 | memset(rctx->uv_alpha + spans[i].x, 0xFF, len); |
1139 | |
|
1140 | 0 | while (len--) { |
1141 | 0 | *s_pY = cy; |
1142 | 0 | s_pY += 2; |
1143 | 0 | } |
1144 | 0 | } |
1145 | 0 | } |
1146 | |
|
1147 | 0 | for (i=0; i<(s32) surf->width; i+=2) { |
1148 | 0 | u32 a = (u32)rctx->uv_alpha[i]; |
1149 | 0 | a += (u32)rctx->uv_alpha[i + 1]; |
1150 | 0 | if (a) { |
1151 | 0 | a /=2; |
1152 | 0 | if (a==0xFF) { |
1153 | 0 | pY[surf->idx_u] = cu; |
1154 | 0 | pY[surf->idx_v] = cv; |
1155 | 0 | } else if (a) { |
1156 | 0 | overmask_yuvy(pY + surf->idx_u, cu, a); |
1157 | 0 | overmask_yuvy(pY + surf->idx_v, cv, a); |
1158 | 0 | } |
1159 | 0 | } |
1160 | 0 | pY+=4; |
1161 | 0 | } |
1162 | 0 | memset(rctx->uv_alpha, 0, surf->uv_alpha_alloc); |
1163 | 0 | } |
1164 | | |
1165 | | void evg_yuyv_fill_const_a(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf, EVGRasterCtx *rctx) |
1166 | 0 | { |
1167 | 0 | u8 *pY; |
1168 | 0 | s32 i; |
1169 | 0 | u8 cy, cu, cv, a; |
1170 | |
|
1171 | 0 | pY = surf->pixels + y * surf->pitch_y; |
1172 | 0 | cy = GF_COL_R(surf->fill_col); |
1173 | 0 | cu = GF_COL_G(surf->fill_col); |
1174 | 0 | cv = GF_COL_B(surf->fill_col); |
1175 | 0 | a = GF_COL_A(surf->fill_col); |
1176 | |
|
1177 | 0 | for (i=0; i<count; i++) { |
1178 | 0 | u8 *s_pY; |
1179 | 0 | u32 fin, len; |
1180 | 0 | len = spans[i].len; |
1181 | 0 | s_pY = pY + (spans[i].x/2) * 4; |
1182 | 0 | if (spans[i].x%2) s_pY += 2; |
1183 | |
|
1184 | 0 | fin = mul255(a, spans[i].coverage); |
1185 | |
|
1186 | 0 | memset(rctx->uv_alpha + spans[i].x, (u8)fin, len); |
1187 | 0 | while (len--) { |
1188 | 0 | overmask_yuvy(s_pY + surf->idx_y1, cy, fin); |
1189 | 0 | s_pY += 2; |
1190 | 0 | } |
1191 | 0 | } |
1192 | 0 | pY = surf->pixels + y * surf->pitch_y; |
1193 | 0 | for (i=0; i<(s32) surf->width; i+=2) { |
1194 | 0 | u32 p_a = rctx->uv_alpha[i]; |
1195 | 0 | p_a += rctx->uv_alpha[i + 1]; |
1196 | 0 | p_a /=2; |
1197 | 0 | if (p_a==0xFF) { |
1198 | 0 | pY[surf->idx_u] = cu; |
1199 | 0 | pY[surf->idx_v] = cv; |
1200 | 0 | } else if (p_a) { |
1201 | 0 | overmask_yuvy(pY + surf->idx_u, cu, p_a); |
1202 | 0 | overmask_yuvy(pY + surf->idx_v, cv, p_a); |
1203 | 0 | } |
1204 | 0 | pY+=4; |
1205 | 0 | } |
1206 | 0 | memset(rctx->uv_alpha, 0, surf->uv_alpha_alloc); |
1207 | |
|
1208 | 0 | } |
1209 | | |
1210 | | void evg_yuyv_fill_var(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf, EVGRasterCtx *rctx) |
1211 | 0 | { |
1212 | 0 | s32 i; |
1213 | 0 | u8 *pY; |
1214 | |
|
1215 | 0 | pY = surf->pixels + y * surf->pitch_y; |
1216 | |
|
1217 | 0 | for (i=0; i<count; i++) { |
1218 | 0 | u8 spanalpha, col_a; |
1219 | 0 | u32 *p_col; |
1220 | 0 | u8 *s_pY; |
1221 | 0 | u32 len, x; |
1222 | 0 | len = spans[i].len; |
1223 | 0 | s_pY = pY + (spans[i].x/2) * 4; |
1224 | 0 | if (spans[i].x%2) s_pY += 2; |
1225 | |
|
1226 | 0 | p_col = surf->fill_run(surf->sten, rctx, &spans[i], y); |
1227 | 0 | spanalpha = spans[i].coverage; |
1228 | |
|
1229 | 0 | x = spans[i].x; |
1230 | |
|
1231 | 0 | while (len--) { |
1232 | 0 | u32 col = *p_col; |
1233 | 0 | col_a = GF_COL_A(col); |
1234 | 0 | if (col_a) { |
1235 | 0 | u32 idx=3*x; |
1236 | 0 | u8 cy, cb, cr; |
1237 | 0 | cy = GF_COL_R(col); |
1238 | 0 | cb = GF_COL_G(col); |
1239 | 0 | cr = GF_COL_B(col); |
1240 | |
|
1241 | 0 | if ((spanalpha!=0xFF) || (col_a != 0xFF)) { |
1242 | 0 | overmask_yuv420p(col_a, cy, s_pY + surf->idx_y1, spanalpha); |
1243 | |
|
1244 | 0 | u8 a = mul255(col_a, spanalpha); |
1245 | 0 | rctx->uv_alpha[idx] = a; |
1246 | 0 | } else { |
1247 | 0 | s_pY[surf->idx_y1] = cy; |
1248 | 0 | rctx->uv_alpha[idx] = 0xFF; |
1249 | 0 | } |
1250 | 0 | rctx->uv_alpha[idx+1] = cb; |
1251 | 0 | rctx->uv_alpha[idx+2] = cr; |
1252 | 0 | } |
1253 | 0 | s_pY+=2; |
1254 | 0 | p_col++; |
1255 | 0 | x++; |
1256 | 0 | } |
1257 | 0 | } |
1258 | 0 | pY = surf->pixels + y * surf->pitch_y; |
1259 | 0 | for (i=0; i<(s32)surf->width; i+=2) { |
1260 | 0 | u32 a; |
1261 | 0 | u32 idx1=3*i; |
1262 | 0 | u32 idx2=3*i + 3; |
1263 | | //get alpha |
1264 | 0 | a = (u32)rctx->uv_alpha[idx1] + (u32)rctx->uv_alpha[idx2]; |
1265 | 0 | if (a) { |
1266 | 0 | u32 chroma; |
1267 | |
|
1268 | 0 | a /= 2; |
1269 | | |
1270 | | //get cb |
1271 | 0 | chroma = (u32)rctx->uv_alpha[idx1+1] + (u32)rctx->uv_alpha[idx2+1]; |
1272 | 0 | chroma /= 2; |
1273 | 0 | if (a==0xFF) { |
1274 | 0 | pY[surf->idx_u] = chroma; |
1275 | 0 | } else { |
1276 | 0 | overmask_yuvy(pY + surf->idx_u, chroma, a); |
1277 | 0 | } |
1278 | | //get cr |
1279 | 0 | chroma = (u32)rctx->uv_alpha[idx1+2] + (u32)rctx->uv_alpha[idx2+2]; |
1280 | 0 | chroma /= 2; |
1281 | 0 | if (a==0xFF) { |
1282 | 0 | pY[surf->idx_v] = chroma; |
1283 | 0 | } else { |
1284 | 0 | overmask_yuvy(pY + surf->idx_v, chroma, a); |
1285 | 0 | } |
1286 | 0 | } |
1287 | 0 | pY+=4; |
1288 | 0 | } |
1289 | |
|
1290 | 0 | memset(rctx->uv_alpha, 0, surf->uv_alpha_alloc); |
1291 | |
|
1292 | 0 | } |
1293 | | |
1294 | | GF_Err evg_surface_clear_yuyv(GF_EVGSurface *_surf, GF_IRect rc, GF_Color col) |
1295 | 0 | { |
1296 | 0 | u32 i; |
1297 | 0 | s32 j; |
1298 | 0 | u8 cy, cb, cr; |
1299 | 0 | GF_EVGSurface *surf = (GF_EVGSurface *)_surf; |
1300 | 0 | u8 *o_pY; |
1301 | 0 | u8 *pY = surf->pixels; |
1302 | 0 | pY += rc.y * surf->pitch_y; |
1303 | 0 | pY += (rc.x/2) * 4; |
1304 | |
|
1305 | 0 | gf_evg_rgb_to_yuv(surf, col, &cy, &cb, &cr); |
1306 | 0 | o_pY = pY; |
1307 | 0 | for (i = 0; i <(u32)rc.height; i++) { |
1308 | 0 | if (!i) { |
1309 | 0 | u8 *dst = pY; |
1310 | 0 | for (j = 0; j < rc.width/2; j++) { |
1311 | 0 | dst[surf->idx_y1] = cy; |
1312 | 0 | dst[surf->idx_u] = cb; |
1313 | 0 | dst[surf->idx_y1 + 2] = cy; |
1314 | 0 | dst[surf->idx_v] = cr; |
1315 | 0 | dst += 4; |
1316 | 0 | } |
1317 | 0 | } else { |
1318 | 0 | memcpy(pY, o_pY, rc.width*2); |
1319 | 0 | } |
1320 | 0 | pY += surf->pitch_y; |
1321 | 0 | } |
1322 | 0 | return GF_OK; |
1323 | 0 | } |
1324 | | |
1325 | | |
1326 | | #ifdef GPAC_BIG_ENDIAN |
1327 | | |
1328 | | #define set_u16_le(_ptr, val) { ((u8 *)_ptr)[0] = (val>>8)&0xFF; ((u8 *)_ptr)[1] = (val&0xFF); } |
1329 | | #define set_u16_be(_ptr, val) { *(u16 *) _ptr = (u16) val; } |
1330 | | |
1331 | | #define get_u16_le(val, _ptr) { val = ((u32) (*(u8 *) _ptr+1)<< 8) | *(u8 *) _ptr; } |
1332 | | #define get_u16_be(val, _ptr) { val = *(u16 *) (_ptr); } |
1333 | | |
1334 | | #else |
1335 | | |
1336 | 0 | #define set_u16_le(_ptr, val) { (*(u16 *) _ptr) = (u16) val; } |
1337 | | #define set_u16_be(_ptr, val) { ((u8 *)_ptr)[0] = (val>>8)&0xFF; ((u8 *)_ptr)[1] = (val&0xFF); } |
1338 | | |
1339 | 0 | #define get_u16_le(val, _ptr) { val = *(u16 *) (_ptr); } |
1340 | | #define get_u16_be(val, _ptr) { val = ((u32) (*(u8 *) _ptr)<< 8) | *(u8 *) _ptr+1; } |
1341 | | |
1342 | | #endif |
1343 | | |
1344 | | |
1345 | | /* |
1346 | | YUV420p-10 part |
1347 | | */ |
1348 | | static s32 |
1349 | | mul_10(s64 a, s64 b) |
1350 | 0 | { |
1351 | 0 | return (s32) ( ((a + 1) * b) >> 16); |
1352 | 0 | } |
1353 | | |
1354 | | static s32 |
1355 | | mul_10_zero(s64 a, s64 b) |
1356 | 0 | { |
1357 | 0 | if (!a) return 0; |
1358 | 0 | return (s32) ( ((a + 1) * b) >> 16); |
1359 | 0 | } |
1360 | | |
1361 | | static void overmask_yuv420p_10(u16 col_a, u16 cy, u16 *dst, u32 alpha) |
1362 | 0 | { |
1363 | 0 | s32 srca = col_a; |
1364 | 0 | u32 srcc = cy; |
1365 | 0 | s32 dstc; |
1366 | 0 | get_u16_le(dstc, dst); |
1367 | |
|
1368 | 0 | srca = mul_10(srca, alpha); |
1369 | 0 | set_u16_le(dst, (mul_10(srca, srcc - dstc) + dstc) ); |
1370 | 0 | } |
1371 | | |
1372 | | static void overmask_yuv420p_10_const_run(u16 a, u16 val, u16 *ptr, u32 count, short x) |
1373 | 0 | { |
1374 | 0 | while (count) { |
1375 | 0 | u16 dst; |
1376 | 0 | get_u16_le(dst, ptr); |
1377 | 0 | set_u16_le(ptr, (u16) (mul_10(a, val - dst) + dst)); |
1378 | 0 | ptr ++; |
1379 | 0 | count--; |
1380 | 0 | } |
1381 | 0 | } |
1382 | | |
1383 | | void evg_yuv420p_10_flush_uv_const(GF_EVGSurface *surf, EVGRasterCtx *rctx, u8 *_surf_uv_alpha, s32 cu, s32 cv, s32 y) |
1384 | 0 | { |
1385 | 0 | u32 i, a; |
1386 | 0 | u16 *surf_uv_alpha_even = (u16 *) rctx->uv_alpha; |
1387 | 0 | u16 *surf_uv_alpha_odd = (u16 *) _surf_uv_alpha; |
1388 | 0 | u8 *pU = surf->pixels + surf->height *surf->pitch_y; |
1389 | 0 | u8 *pV; |
1390 | 0 | pU += y/2 * surf->pitch_y/2; |
1391 | 0 | pV = pU + surf->height/2 * surf->pitch_y/2; |
1392 | | |
1393 | | //we are at an odd line, write uv |
1394 | 0 | for (i=0; i<surf->width; i+=2) { |
1395 | 0 | u16 dst; |
1396 | | |
1397 | | //even line |
1398 | 0 | a = surf_uv_alpha_even[i] + surf_uv_alpha_even[i+1]; |
1399 | | //odd line |
1400 | 0 | a += surf_uv_alpha_odd[i] + surf_uv_alpha_odd[i+1]; |
1401 | |
|
1402 | 0 | if (a) { |
1403 | 0 | u16 *s_ptr_u, *s_ptr_v; |
1404 | |
|
1405 | 0 | a /= 4; |
1406 | |
|
1407 | 0 | s_ptr_u = ((u16 *) pU) + i/2; |
1408 | 0 | s_ptr_v = ((u16 *) pV) + i/2; |
1409 | 0 | if (a==0xFFFF) { |
1410 | 0 | set_u16_le(s_ptr_u, cu); |
1411 | 0 | set_u16_le(s_ptr_v, cv); |
1412 | 0 | } else { |
1413 | 0 | get_u16_le(dst, s_ptr_u); |
1414 | 0 | set_u16_le(s_ptr_u, (u16) (mul_10(a, cu - dst) + dst) ); |
1415 | 0 | get_u16_le(dst, s_ptr_v); |
1416 | 0 | set_u16_le(s_ptr_v, (u16) (mul_10(a, cv - dst) + dst) ); |
1417 | 0 | } |
1418 | 0 | } |
1419 | 0 | } |
1420 | 0 | memset(rctx->uv_alpha, 0, surf->uv_alpha_alloc); |
1421 | 0 | } |
1422 | | |
1423 | | void evg_yuv420p_10_fill_const(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf, EVGRasterCtx *rctx) |
1424 | 0 | { |
1425 | 0 | u16 *pY; |
1426 | 0 | u16 *surf_uv_alpha; |
1427 | 0 | s32 i; |
1428 | 0 | u16 cy, cu, cv; |
1429 | 0 | Bool write_uv = (y%2) ? GF_TRUE : GF_FALSE; |
1430 | |
|
1431 | 0 | if (surf->is_422) { |
1432 | 0 | write_uv = GF_TRUE; |
1433 | 0 | surf_uv_alpha = (u16 *)rctx->uv_alpha; |
1434 | 0 | } |
1435 | 0 | else if (write_uv) { |
1436 | 0 | surf_uv_alpha = ((u16 *)rctx->uv_alpha) + surf->width; |
1437 | 0 | } else { |
1438 | 0 | surf_uv_alpha = (u16 *)rctx->uv_alpha; |
1439 | 0 | } |
1440 | |
|
1441 | 0 | pY = (u16 *) (surf->pixels + y * surf->pitch_y); |
1442 | |
|
1443 | 0 | cy = (surf->fill_col_wide>>32) & 0xFFFF; |
1444 | 0 | cy >>=6; |
1445 | 0 | cu = (surf->fill_col_wide>>16) & 0xFFFF; |
1446 | 0 | cu >>=6; |
1447 | 0 | cv = (surf->fill_col_wide) & 0xFFFF; |
1448 | 0 | cv >>=6; |
1449 | |
|
1450 | 0 | for (i=0; i<count; i++) { |
1451 | 0 | u32 a; |
1452 | 0 | u16 *s_pY; |
1453 | 0 | u32 j, len; |
1454 | 0 | len = spans[i].len; |
1455 | 0 | s_pY = pY + spans[i].x; |
1456 | |
|
1457 | 0 | a = 0xFF * spans[i].coverage; |
1458 | 0 | for (j=0; j<len; j++) { |
1459 | 0 | surf_uv_alpha[spans[i].x + j] = a; |
1460 | 0 | } |
1461 | |
|
1462 | 0 | if (spans[i].coverage != 0xFF) { |
1463 | 0 | overmask_yuv420p_10_const_run(a, cy, s_pY, len, 0); |
1464 | 0 | } else { |
1465 | 0 | while (len--) { |
1466 | 0 | set_u16_le(s_pY, cy); |
1467 | 0 | s_pY ++; |
1468 | 0 | } |
1469 | 0 | } |
1470 | 0 | } |
1471 | 0 | if (write_uv && !rctx->no_yuv_flush) { |
1472 | 0 | surf->yuv_flush_uv(surf, rctx, (u8 *)surf_uv_alpha, cu, cv, y); |
1473 | 0 | } |
1474 | |
|
1475 | 0 | } |
1476 | | |
1477 | | void evg_yuv420p_10_fill_const_a(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf, EVGRasterCtx *rctx) |
1478 | 0 | { |
1479 | 0 | u32 a; |
1480 | 0 | u16 *pY; |
1481 | 0 | u16 *surf_uv_alpha; |
1482 | 0 | s32 i; |
1483 | 0 | u16 cy, cu, cv; |
1484 | 0 | Bool write_uv = (y%2) ? GF_TRUE : GF_FALSE; |
1485 | |
|
1486 | 0 | if (surf->is_422) { |
1487 | 0 | write_uv = GF_TRUE; |
1488 | 0 | surf_uv_alpha = (u16 *)rctx->uv_alpha; |
1489 | 0 | } else if (write_uv) { |
1490 | 0 | surf_uv_alpha = (u16 *)rctx->uv_alpha + surf->width; |
1491 | 0 | } else { |
1492 | 0 | surf_uv_alpha = (u16 *)rctx->uv_alpha; |
1493 | 0 | } |
1494 | |
|
1495 | 0 | pY = (u16 *) (surf->pixels + y * surf->pitch_y); |
1496 | | |
1497 | |
|
1498 | 0 | a = (surf->fill_col_wide>>48) & 0xFFFF; |
1499 | 0 | cy = (surf->fill_col_wide>>32) & 0xFFFF; |
1500 | 0 | cy >>=6; |
1501 | 0 | cu = (surf->fill_col_wide>>16) & 0xFFFF; |
1502 | 0 | cu >>=6; |
1503 | 0 | cv = (surf->fill_col_wide) & 0xFFFF; |
1504 | 0 | cv >>=6; |
1505 | |
|
1506 | 0 | if (surf->get_alpha) { |
1507 | 0 | for (i=0; i<count; i++) { |
1508 | 0 | u32 j; |
1509 | 0 | for (j=0; j<spans[i].len; j++) { |
1510 | 0 | u16 *s_pY; |
1511 | 0 | u32 fin; |
1512 | 0 | s32 x = spans[i].x + j; |
1513 | 0 | s_pY = pY + x; |
1514 | 0 | fin = surf->get_alpha(surf->get_alpha_udta, a, x, y) * spans[i].coverage; |
1515 | 0 | fin /= 0xFF; |
1516 | |
|
1517 | 0 | overmask_yuv420p_10_const_run(fin, cy, s_pY, 1, 0); |
1518 | 0 | surf_uv_alpha[x] = fin; |
1519 | 0 | } |
1520 | 0 | } |
1521 | 0 | } else { |
1522 | 0 | for (i=0; i<count; i++) { |
1523 | 0 | u16 *s_pY; |
1524 | 0 | u32 fin, len, j; |
1525 | 0 | len = spans[i].len; |
1526 | 0 | s_pY = pY + spans[i].x; |
1527 | 0 | fin = a * spans[i].coverage; |
1528 | 0 | fin /= 0xFF; |
1529 | |
|
1530 | 0 | overmask_yuv420p_10_const_run(fin, cy, s_pY, len, 0); |
1531 | |
|
1532 | 0 | for (j=0; j<len; j++) { |
1533 | 0 | surf_uv_alpha[spans[i].x + j] = fin; |
1534 | 0 | } |
1535 | 0 | } |
1536 | 0 | } |
1537 | | //we are at an odd line, write uv |
1538 | 0 | if (write_uv && !rctx->no_yuv_flush) |
1539 | 0 | surf->yuv_flush_uv(surf, rctx, (u8*)surf_uv_alpha, cu, cv, y); |
1540 | 0 | } |
1541 | | |
1542 | | void evg_yuv420p_10_flush_uv_var(GF_EVGSurface *surf, EVGRasterCtx *rctx, u8 *_surf_uv_alpha, s32 _cu, s32 _cv, s32 y) |
1543 | 0 | { |
1544 | 0 | u32 i; |
1545 | 0 | u16 *surf_uv_alpha_even = (u16 *) rctx->uv_alpha; |
1546 | 0 | u16 *surf_uv_alpha_odd = (u16 *) _surf_uv_alpha; |
1547 | 0 | u16 *pU, *pV; |
1548 | 0 | pU = (u16 *) (surf->pixels + surf->height *surf->pitch_y + y/2 * surf->pitch_y/2); |
1549 | 0 | pV = (u16 *) (surf->pixels + 5*surf->height *surf->pitch_y/4 + y/2 * surf->pitch_y/2); |
1550 | |
|
1551 | 0 | for (i=0; i<surf->width; i+=2) { |
1552 | 0 | u32 a, a11, a12, a21, a22; |
1553 | 0 | u32 idx1=3*i; |
1554 | 0 | u32 idx2=3*i + 3; |
1555 | | |
1556 | | //get alpha |
1557 | 0 | a11 = (u32)surf_uv_alpha_even[idx1]; |
1558 | 0 | a12 = (u32)surf_uv_alpha_even[idx2]; |
1559 | 0 | a21 = (u32)surf_uv_alpha_odd[idx1]; |
1560 | 0 | a22 = (u32)surf_uv_alpha_odd[idx2]; |
1561 | |
|
1562 | 0 | a = a11+a12+a21+a22; |
1563 | 0 | if (a) { |
1564 | 0 | s32 cdst=0; |
1565 | 0 | s32 chroma_u, chroma_v, c11, c12, c21, c22; |
1566 | |
|
1567 | 0 | a /= 4; |
1568 | | |
1569 | | //get cb |
1570 | 0 | idx1 += 1; |
1571 | 0 | idx2 += 1; |
1572 | |
|
1573 | 0 | if (a!=0xFFFF) { |
1574 | 0 | get_u16_le(cdst, pU); |
1575 | 0 | } |
1576 | 0 | c11 = (u32)surf_uv_alpha_even[idx1]; |
1577 | 0 | if (a11!=0xFFFF) c11 = mul_10_zero(a11, c11 - cdst) + cdst; |
1578 | 0 | c12 = (u32)surf_uv_alpha_even[idx2]; |
1579 | 0 | if (a12!=0xFFFF) c12 = mul_10_zero(a12, c12 - cdst) + cdst; |
1580 | 0 | c21 = (u32)surf_uv_alpha_odd[idx1]; |
1581 | 0 | if (a21!=0xFFFF) c21 = mul_10_zero(a21, c21 - cdst) + cdst; |
1582 | 0 | c22 = (u32)surf_uv_alpha_odd[idx2]; |
1583 | 0 | if (a22!=0xFFFF) c22 = mul_10_zero(a22, c22 - cdst) + cdst; |
1584 | |
|
1585 | 0 | chroma_u = c11 + c12 + c21 + c22; |
1586 | 0 | chroma_u /= 4; |
1587 | 0 | set_u16_le(pU, (u16) chroma_u); |
1588 | | |
1589 | | //get cr |
1590 | 0 | idx1 += 1; |
1591 | 0 | idx2 += 1; |
1592 | |
|
1593 | 0 | if (a!=0xFFFF) { |
1594 | 0 | get_u16_le(cdst, pV); |
1595 | 0 | } |
1596 | 0 | c11 = (u32)surf_uv_alpha_even[idx1]; |
1597 | 0 | if (a11!=0xFFFF) c11 = mul_10_zero(a11, c11 - cdst) + cdst; |
1598 | 0 | c12 = (u32)surf_uv_alpha_even[idx2]; |
1599 | 0 | if (a12!=0xFFFF) c12 = mul_10_zero(a12, c12 - cdst) + cdst; |
1600 | 0 | c21 = (u32)surf_uv_alpha_odd[idx1]; |
1601 | 0 | if (a21!=0xFFFF) c21 = mul_10_zero(a21, c21 - cdst) + cdst; |
1602 | 0 | c22 = (u32)surf_uv_alpha_odd[idx2]; |
1603 | 0 | if (a22!=0xFFFF) c22 = mul_10_zero(a22, c22 - cdst) + cdst; |
1604 | |
|
1605 | 0 | chroma_v = c11 + c12 + c21 + c22; |
1606 | 0 | chroma_v /= 4; |
1607 | 0 | set_u16_le(pV, (u16) chroma_v); |
1608 | 0 | } |
1609 | 0 | pU++; |
1610 | 0 | pV++; |
1611 | 0 | } |
1612 | | //reset for next pass |
1613 | 0 | memset(rctx->uv_alpha, 0, surf->uv_alpha_alloc); |
1614 | |
|
1615 | 0 | } |
1616 | | |
1617 | | void evg_yuv420p_10_fill_var(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf, EVGRasterCtx *rctx) |
1618 | 0 | { |
1619 | 0 | s32 i; |
1620 | 0 | u16 *pY; |
1621 | 0 | u16 *surf_uv_alpha; |
1622 | 0 | Bool write_uv = (y%2) ? GF_TRUE : GF_FALSE; |
1623 | |
|
1624 | 0 | if (surf->is_422) { |
1625 | 0 | write_uv = GF_TRUE; |
1626 | 0 | surf_uv_alpha = (u16 *) rctx->uv_alpha; |
1627 | 0 | } else if (write_uv) { |
1628 | | //second line of storage (we store alpha, cr, cb for each pixel) |
1629 | 0 | surf_uv_alpha = ((u16 *) rctx->uv_alpha) + 3*surf->width; |
1630 | 0 | } else { |
1631 | | //first line of storage |
1632 | 0 | surf_uv_alpha = (u16 *) rctx->uv_alpha; |
1633 | 0 | } |
1634 | |
|
1635 | 0 | pY = (u16 *) (surf->pixels + y * surf->pitch_y); |
1636 | |
|
1637 | 0 | for (i=0; i<count; i++) { |
1638 | 0 | u8 spanalpha; |
1639 | 0 | u32 len; |
1640 | 0 | u64 *p_col; |
1641 | 0 | u16 *s_pY; |
1642 | 0 | short x; |
1643 | 0 | len = spans[i].len; |
1644 | 0 | p_col = surf->fill_run(surf->sten, rctx, &spans[i], y); |
1645 | 0 | spanalpha = spans[i].coverage; |
1646 | |
|
1647 | 0 | s_pY = pY + spans[i].x; |
1648 | 0 | x = spans[i].x; |
1649 | |
|
1650 | 0 | while (len--) { |
1651 | 0 | u64 col = *p_col; |
1652 | 0 | u32 col_a = (col>>48)&0xFFFF; |
1653 | 0 | if (col_a) { |
1654 | 0 | u16 cy, cb, cr; |
1655 | 0 | u32 idx=3*x; |
1656 | | //col is directly packed as AYCbCr |
1657 | 0 | cy = ((col>>32) & 0xFFFF) >> 6; |
1658 | 0 | cb = ((col>>16) & 0xFFFF) >> 6; |
1659 | 0 | cr = ((col) & 0xFFFF) >> 6; |
1660 | |
|
1661 | 0 | if ((spanalpha!=0xFF) || (col_a != 0xFFFF)) { |
1662 | 0 | u16 spana = spanalpha; |
1663 | 0 | spana <<= 8; |
1664 | 0 | overmask_yuv420p_10(col_a, cy, s_pY, spana); |
1665 | 0 | surf_uv_alpha[idx] = mul_10(col_a, spana); |
1666 | 0 | } else { |
1667 | 0 | set_u16_le(s_pY, cy); |
1668 | 0 | surf_uv_alpha[idx] = 0xFFFF; |
1669 | 0 | } |
1670 | 0 | surf_uv_alpha[idx+1] = cb; |
1671 | 0 | surf_uv_alpha[idx+2] = cr; |
1672 | 0 | } |
1673 | 0 | s_pY++; |
1674 | 0 | p_col++; |
1675 | 0 | x++; |
1676 | 0 | } |
1677 | 0 | } |
1678 | | //compute final u,v for both lines |
1679 | 0 | if (write_uv && !rctx->no_yuv_flush) { |
1680 | 0 | surf->yuv_flush_uv(surf, rctx, (u8 *)surf_uv_alpha, 0, 0, y); |
1681 | 0 | } |
1682 | 0 | } |
1683 | | |
1684 | | GF_Err evg_surface_clear_yuv420p_10(GF_EVGSurface *_surf, GF_IRect rc, GF_Color col) |
1685 | 0 | { |
1686 | 0 | s32 i, j; |
1687 | 0 | u8 _cy, _cb, _cr; |
1688 | 0 | u16 cy, cb, cr; |
1689 | 0 | GF_EVGSurface *surf = (GF_EVGSurface *)_surf; |
1690 | 0 | u16 *pY, *pU, *pV, *o_pY, *o_pU, *o_pV; |
1691 | |
|
1692 | 0 | pY = (u16 *) (surf->pixels + rc.y * surf->pitch_y + 2*rc.x); |
1693 | 0 | pU = (u16 *) (surf->pixels + surf->height * surf->pitch_y + rc.y/2 * surf->pitch_y/2 + rc.x); |
1694 | 0 | pV = (u16 *) (surf->pixels + 5*surf->height * surf->pitch_y/4 + rc.y/2 * surf->pitch_y/2 + rc.x); |
1695 | |
|
1696 | 0 | gf_evg_rgb_to_yuv(surf, col, &_cy, &_cb, &_cr); |
1697 | 0 | cy = ((u16)_cy) << 2; |
1698 | 0 | cb = ((u16)_cb) << 2; |
1699 | 0 | cr = ((u16)_cr) << 2; |
1700 | 0 | o_pY = pY; |
1701 | 0 | o_pU = pU; |
1702 | 0 | o_pV = pV; |
1703 | 0 | for (i = 0; i <rc.height; i++) { |
1704 | 0 | if (!i) { |
1705 | 0 | if (cy) { |
1706 | 0 | for (j=0; j<rc.width; j++) |
1707 | 0 | set_u16_le(&pY[j] , cy); |
1708 | 0 | } else { |
1709 | 0 | memset(pY, 0, rc.width*2); |
1710 | 0 | } |
1711 | 0 | } else { |
1712 | 0 | memcpy(pY, o_pY, rc.width*2); |
1713 | 0 | } |
1714 | | //pitch is in bytes, we are in short |
1715 | 0 | pY += surf->pitch_y/2; |
1716 | |
|
1717 | 0 | if (i%2) continue; |
1718 | | |
1719 | 0 | if (!i) { |
1720 | 0 | for (j=0; j<rc.width/2; j++) { |
1721 | 0 | set_u16_le(&pU[j], cb); |
1722 | 0 | set_u16_le(&pV[j], cr); |
1723 | 0 | } |
1724 | 0 | } else { |
1725 | 0 | memcpy(pU, o_pU, rc.width);//half width at 2 bytes per short |
1726 | 0 | memcpy(pV, o_pV, rc.width); |
1727 | 0 | } |
1728 | | //pitch is in bytes, we are in short |
1729 | 0 | pU += surf->pitch_y/4; |
1730 | 0 | pV += surf->pitch_y/4; |
1731 | 0 | } |
1732 | 0 | return GF_OK; |
1733 | 0 | } |
1734 | | |
1735 | | /* |
1736 | | NV12 / NV21 10 bit part |
1737 | | */ |
1738 | | |
1739 | | |
1740 | | void evg_nv12_10_flush_uv_const(GF_EVGSurface *surf, EVGRasterCtx *rctx, u8 *_surf_uv_alpha, s32 cu, s32 cv, s32 y) |
1741 | 0 | { |
1742 | 0 | u32 i, a; |
1743 | 0 | u16 *surf_uv_alpha_even = (u16 *) rctx->uv_alpha; |
1744 | 0 | u16 *surf_uv_alpha_odd = (u16 *)_surf_uv_alpha; |
1745 | 0 | u8 *pUV = surf->pixels + surf->height * surf->pitch_y + y/2 * surf->pitch_y; |
1746 | 0 | u8 *pU = pUV + 2*surf->idx_u; |
1747 | 0 | u8 *pV = pUV + 2*surf->idx_v; |
1748 | |
|
1749 | 0 | for (i=0; i<surf->width; i+=2) { |
1750 | | //even line |
1751 | 0 | a = surf_uv_alpha_even[i] + surf_uv_alpha_even[i+1]; |
1752 | | //odd line |
1753 | 0 | a += surf_uv_alpha_odd[i] + surf_uv_alpha_odd[i+1]; |
1754 | |
|
1755 | 0 | if (a) { |
1756 | 0 | s32 dst; |
1757 | 0 | a /= 4; |
1758 | |
|
1759 | 0 | if (a==0xFFFF) { |
1760 | 0 | set_u16_le(pU, cu); |
1761 | 0 | set_u16_le(pV, cv); |
1762 | 0 | } else { |
1763 | 0 | get_u16_le(dst, pU); |
1764 | 0 | set_u16_le(pU, (u16) (mul_10(a, cu - dst) + dst) ); |
1765 | 0 | get_u16_le(dst, pV); |
1766 | 0 | set_u16_le(pV, (u16) (mul_10(a, cv - dst) + dst) ); |
1767 | 0 | } |
1768 | 0 | } |
1769 | 0 | pU += 4; |
1770 | 0 | pV += 4; |
1771 | 0 | } |
1772 | 0 | memset(rctx->uv_alpha, 0, surf->uv_alpha_alloc); |
1773 | 0 | } |
1774 | | |
1775 | | |
1776 | | void evg_nv12_10_flush_uv_var(GF_EVGSurface *surf, EVGRasterCtx *rctx, u8 *_surf_uv_alpha, s32 cu, s32 cv, s32 y) |
1777 | 0 | { |
1778 | 0 | u32 i; |
1779 | 0 | u16 *surf_uv_alpha_even = (u16 *) rctx->uv_alpha; |
1780 | 0 | u16 *surf_uv_alpha_odd = (u16 *) _surf_uv_alpha; |
1781 | 0 | u8 *pUV = surf->pixels + surf->height *surf->pitch_y + y/2 * surf->pitch_y; |
1782 | 0 | u8 *pU = pUV + 2*surf->idx_u; |
1783 | 0 | u8 *pV = pUV + 2*surf->idx_v; |
1784 | |
|
1785 | 0 | for (i=0; i<surf->width; i+=2) { |
1786 | 0 | u32 a, a11, a12, a21, a22; |
1787 | 0 | u32 idx1=3*i; |
1788 | 0 | u32 idx2=3*i + 3; |
1789 | | //get alpha |
1790 | 0 | a11 = (u32)surf_uv_alpha_even[idx1]; |
1791 | 0 | a12 = (u32)surf_uv_alpha_even[idx2]; |
1792 | 0 | a21 = (u32)surf_uv_alpha_odd[idx1]; |
1793 | 0 | a22 = (u32)surf_uv_alpha_odd[idx2]; |
1794 | 0 | a = a11+a12+a21+a22; |
1795 | |
|
1796 | 0 | if (a) { |
1797 | 0 | s32 cdst=0, chroma_u, chroma_v, c11, c12, c21, c22; |
1798 | |
|
1799 | 0 | a /= 4; |
1800 | | |
1801 | | //get cb |
1802 | 0 | idx1 += 1; |
1803 | 0 | idx2 += 1; |
1804 | 0 | if (a!=0xFFFF) |
1805 | 0 | get_u16_le(cdst, pU); |
1806 | |
|
1807 | 0 | c11 = (u32)surf_uv_alpha_even[idx1]; |
1808 | 0 | if (a11!=0xFFFF) c11 = mul_10_zero(a11, c11 - cdst) + cdst; |
1809 | 0 | c12 = (u32)surf_uv_alpha_even[idx2]; |
1810 | 0 | if (a12!=0xFFFF) c12 = mul_10_zero(a12, c12 - cdst) + cdst; |
1811 | 0 | c21 = (u32)surf_uv_alpha_odd[idx1]; |
1812 | 0 | if (a21!=0xFFFF) c21 = mul_10_zero(a21, c21 - cdst) + cdst; |
1813 | 0 | c22 = (u32)surf_uv_alpha_odd[idx2]; |
1814 | 0 | if (a22!=0xFFFF) c22 = mul_10_zero(a22, c22 - cdst) + cdst; |
1815 | |
|
1816 | 0 | chroma_u = c11+c12+c21+c22; |
1817 | 0 | chroma_u /= 4; |
1818 | | |
1819 | | //get cr |
1820 | 0 | idx1 += 1; |
1821 | 0 | idx2 += 1; |
1822 | 0 | if (a!=0xFFFF) |
1823 | 0 | get_u16_le(cdst, pV); |
1824 | |
|
1825 | 0 | c11 = (u32)surf_uv_alpha_even[idx1]; |
1826 | 0 | if (a11!=0xFFFF) c11 = mul_10_zero(a11, c11 - cdst) + cdst; |
1827 | 0 | c12 = (u32)surf_uv_alpha_even[idx2]; |
1828 | 0 | if (a12!=0xFFFF) c12 = mul_10_zero(a12, c12 - cdst) + cdst; |
1829 | 0 | c21 = (u32)surf_uv_alpha_odd[idx1]; |
1830 | 0 | if (a21!=0xFFFF) c21 = mul_10_zero(a21, c21 - cdst) + cdst; |
1831 | 0 | c22 = (u32)surf_uv_alpha_odd[idx2]; |
1832 | 0 | if (a22!=0xFFFF) c22 = mul_10_zero(a22, c22 - cdst) + cdst; |
1833 | |
|
1834 | 0 | chroma_v = c11+c12+c21+c22; |
1835 | 0 | chroma_v /= 4; |
1836 | | |
1837 | |
|
1838 | 0 | set_u16_le(pU, chroma_u); |
1839 | 0 | set_u16_le(pV, chroma_v); |
1840 | 0 | } |
1841 | 0 | pU += 4; |
1842 | 0 | pV += 4; |
1843 | 0 | } |
1844 | | //reset for next pass |
1845 | 0 | memset(rctx->uv_alpha, 0, surf->uv_alpha_alloc); |
1846 | 0 | } |
1847 | | |
1848 | | |
1849 | | GF_Err evg_surface_clear_nv12_10(GF_EVGSurface *_surf, GF_IRect rc, GF_Color col, Bool swap_uv) |
1850 | 0 | { |
1851 | 0 | s32 i, j; |
1852 | 0 | u8 _cy, _cb, _cr; |
1853 | 0 | u16 cy, cb, cr; |
1854 | 0 | GF_EVGSurface *surf = (GF_EVGSurface *)_surf; |
1855 | 0 | u16 *s_pY, *s_pU; |
1856 | 0 | u8 *pY = surf->pixels; |
1857 | 0 | u8 *pU = surf->pixels + surf->height *surf->pitch_y; |
1858 | 0 | u8 *pU_first, *pY_first; |
1859 | |
|
1860 | 0 | pY += rc.y * surf->pitch_y; |
1861 | 0 | pU += rc.y/2 * surf->pitch_y; |
1862 | |
|
1863 | 0 | pY += 2*rc.x; |
1864 | 0 | pU += 2*rc.x; |
1865 | 0 | pU_first = pU; |
1866 | 0 | pY_first = pY; |
1867 | |
|
1868 | 0 | gf_evg_rgb_to_yuv(surf, col, &_cy, &_cb, &_cr); |
1869 | |
|
1870 | 0 | if (swap_uv) { |
1871 | 0 | u8 t = _cb; |
1872 | 0 | _cb = _cr; |
1873 | 0 | _cr = t; |
1874 | 0 | } |
1875 | 0 | cy = ((u16)_cy) << 2; |
1876 | 0 | cb = ((u16)_cb) << 2; |
1877 | 0 | cr = ((u16)_cr) << 2; |
1878 | |
|
1879 | 0 | s_pY = (u16 *) pY; |
1880 | 0 | s_pU = (u16 *) pU; |
1881 | | |
1882 | | //init first lines |
1883 | 0 | if (cy) { |
1884 | 0 | for (j=0; j<rc.width;j++) { |
1885 | 0 | set_u16_le(&s_pY[j], cy); |
1886 | 0 | } |
1887 | 0 | } else { |
1888 | 0 | memset(s_pY, 0, 2*rc.width); |
1889 | 0 | } |
1890 | 0 | s_pY += surf->pitch_y/2; |
1891 | |
|
1892 | 0 | for (j=0; j<rc.width/2; j++) { |
1893 | 0 | set_u16_le(&s_pU[2*j], cb); |
1894 | 0 | set_u16_le(&s_pU[2*j + 1], cr); |
1895 | 0 | } |
1896 | 0 | s_pU += surf->pitch_y/2; |
1897 | |
|
1898 | 0 | for (i = 1; i < rc.height; i++) { |
1899 | |
|
1900 | 0 | memcpy(s_pY, pY_first, 2*rc.width); |
1901 | 0 | s_pY += surf->pitch_y/2; |
1902 | |
|
1903 | 0 | if (i%2) continue; |
1904 | | |
1905 | | //non-first uv line recopy from first (half width, U and V mix, 2 bytes = width*2) |
1906 | 0 | memcpy(s_pU, pU_first, 2*rc.width); |
1907 | 0 | s_pU += surf->pitch_y/2; |
1908 | 0 | } |
1909 | 0 | return GF_OK; |
1910 | 0 | } |
1911 | | |
1912 | | |
1913 | | |
1914 | | /* |
1915 | | YUV422 10 part |
1916 | | */ |
1917 | | |
1918 | | void evg_yuv422p_10_flush_uv_const(GF_EVGSurface *surf, EVGRasterCtx *rctx, u8 *_surf_uv_alpha, s32 cu, s32 cv, s32 y) |
1919 | 0 | { |
1920 | 0 | u32 i, a; |
1921 | 0 | u8 *pU = surf->pixels + surf->height *surf->pitch_y; |
1922 | 0 | u8 *pV; |
1923 | 0 | u16 *surf_uv_alpha = (u16 *) rctx->uv_alpha; |
1924 | 0 | pU += y * surf->pitch_y/2; |
1925 | 0 | pV = pU + surf->height * surf->pitch_y/2; |
1926 | |
|
1927 | 0 | for (i=0; i<surf->width; i+=2) { |
1928 | 0 | a = surf_uv_alpha[i] + surf_uv_alpha[i+1]; |
1929 | |
|
1930 | 0 | if (a) { |
1931 | 0 | s32 dst; |
1932 | 0 | u16 *s_ptr_u, *s_ptr_v; |
1933 | |
|
1934 | 0 | a /= 2; |
1935 | |
|
1936 | 0 | s_ptr_u = (u16*)pU + i / 2; |
1937 | 0 | s_ptr_v = (u16*)pV + i / 2; |
1938 | 0 | if (a==0xFFFF) { |
1939 | 0 | set_u16_le(s_ptr_u, (u16) cu); |
1940 | 0 | set_u16_le(s_ptr_v, (u16) cv); |
1941 | |
|
1942 | 0 | } else { |
1943 | 0 | get_u16_le(dst, s_ptr_u); |
1944 | 0 | set_u16_le(s_ptr_u, (u16) (mul_10(a, cu - dst) + dst) ); |
1945 | |
|
1946 | 0 | get_u16_le(dst, s_ptr_v); |
1947 | 0 | set_u16_le(s_ptr_v, (u16) (mul_10(a, cv - dst) + dst)); |
1948 | 0 | } |
1949 | 0 | } |
1950 | 0 | } |
1951 | 0 | memset(rctx->uv_alpha, 0, surf->uv_alpha_alloc); |
1952 | 0 | } |
1953 | | |
1954 | | void evg_yuv422p_10_flush_uv_var(GF_EVGSurface *surf, EVGRasterCtx *rctx, u8 *_surf_uv_alpha, s32 _cu, s32 _cv, s32 y) |
1955 | 0 | { |
1956 | 0 | u32 i; |
1957 | 0 | u16 *surf_uv_alpha = (u16 *) rctx->uv_alpha; |
1958 | 0 | u16 *pU = (u16 *) (surf->pixels + surf->height *surf->pitch_y + y * surf->pitch_y/2); |
1959 | 0 | u16 *pV = (u16 *) (surf->pixels + surf->height *surf->pitch_y + surf->height * surf->pitch_y/2 + y * surf->pitch_y/2); |
1960 | |
|
1961 | 0 | for (i=0; i<surf->width; i+=2) { |
1962 | 0 | u32 a, a11, a12; |
1963 | 0 | u32 idx1=3*i; |
1964 | 0 | u32 idx2=3*i + 3; |
1965 | | //get alpha |
1966 | 0 | a11 = surf_uv_alpha[idx1]; |
1967 | 0 | a12 = surf_uv_alpha[idx2]; |
1968 | 0 | a=a11+a12; |
1969 | |
|
1970 | 0 | if (a) { |
1971 | 0 | s32 cdst=0, chroma_u, chroma_v, c11, c12; |
1972 | |
|
1973 | 0 | a /= 2; |
1974 | | |
1975 | | //get cb |
1976 | 0 | if (a!=0xFFFF) |
1977 | 0 | get_u16_le(cdst, pU); |
1978 | |
|
1979 | 0 | c11 = (u32)surf_uv_alpha[idx1+1]; |
1980 | 0 | if (a11!=0xFFFF) c11 = mul_10_zero(a11, c11 - cdst) + cdst; |
1981 | 0 | c12 = (u32)surf_uv_alpha[idx2+1]; |
1982 | 0 | if (a12!=0xFFFF) c12 = mul_10_zero(a12, c12 - cdst) + cdst; |
1983 | |
|
1984 | 0 | chroma_u = c11 + c12; |
1985 | 0 | chroma_u /= 2; |
1986 | 0 | set_u16_le(pU, (u16) chroma_u); |
1987 | | |
1988 | | //get cr |
1989 | 0 | if (a!=0xFFFF) |
1990 | 0 | get_u16_le(cdst, pV); |
1991 | |
|
1992 | 0 | c11 = (u32)surf_uv_alpha[idx1+2]; |
1993 | 0 | if (a11!=0xFFFF) c11 = mul_10_zero(a11, c11 - cdst) + cdst; |
1994 | 0 | c12 = (u32)surf_uv_alpha[idx2+2]; |
1995 | 0 | if (a12!=0xFFFF) c12 = mul_10_zero(a12, c12 - cdst) + cdst; |
1996 | |
|
1997 | 0 | chroma_v = c11 + c12; |
1998 | 0 | chroma_v /= 2; |
1999 | 0 | set_u16_le(pV, (u16) chroma_v); |
2000 | 0 | } |
2001 | 0 | pU++; |
2002 | 0 | pV++; |
2003 | 0 | } |
2004 | | //reset for next pass |
2005 | 0 | memset(rctx->uv_alpha, 0, surf->uv_alpha_alloc); |
2006 | 0 | } |
2007 | | |
2008 | | |
2009 | | GF_Err evg_surface_clear_yuv422p_10(GF_EVGSurface *_surf, GF_IRect rc, GF_Color col) |
2010 | 0 | { |
2011 | 0 | s32 i, j; |
2012 | 0 | u8 _cy, _cb, _cr; |
2013 | 0 | u16 cy, cb, cr; |
2014 | 0 | GF_EVGSurface *surf = (GF_EVGSurface *)_surf; |
2015 | 0 | u8 *pY = surf->pixels; |
2016 | 0 | u8 *pU = surf->pixels + surf->height *surf->pitch_y; |
2017 | 0 | u8 *pV; |
2018 | 0 | u8 *o_pY, *o_pU, *o_pV; |
2019 | |
|
2020 | 0 | pY += rc.y * surf->pitch_y; |
2021 | 0 | pU += rc.y/2 * surf->pitch_y/2; |
2022 | 0 | pV = pU + surf->height/2 * surf->pitch_y/2; |
2023 | |
|
2024 | 0 | pY += 2*rc.x; |
2025 | 0 | pU += rc.x; |
2026 | 0 | pV += rc.x; |
2027 | |
|
2028 | 0 | o_pY = pY; |
2029 | 0 | o_pU = pU; |
2030 | 0 | o_pV = pV; |
2031 | 0 | gf_evg_rgb_to_yuv(surf, col, &_cy, &_cb, &_cr); |
2032 | |
|
2033 | 0 | cy = ((u16)_cy) << 2; |
2034 | 0 | cb = ((u16)_cb) << 2; |
2035 | 0 | cr = ((u16)_cr) << 2; |
2036 | |
|
2037 | 0 | for (i = 0; i < rc.height; i++) { |
2038 | 0 | if (!i) { |
2039 | 0 | for (j=0; j<rc.width; j++) { |
2040 | 0 | set_u16_le(&((u16 *)pY)[j], cy); |
2041 | 0 | if (j%2) { |
2042 | 0 | set_u16_le(&((u16 *)pU)[j/2], cb); |
2043 | 0 | set_u16_le(& ((u16 *)pV)[j/2], cr); |
2044 | 0 | } |
2045 | 0 | } |
2046 | 0 | } else { |
2047 | 0 | memcpy(pY, o_pY, 2*rc.width); |
2048 | 0 | memcpy(pU, o_pU, rc.width); |
2049 | 0 | memcpy(pV, o_pV, rc.width); |
2050 | 0 | } |
2051 | 0 | pY += surf->pitch_y; |
2052 | 0 | pU += surf->pitch_y/2; |
2053 | 0 | pV += surf->pitch_y/2; |
2054 | 0 | } |
2055 | 0 | return GF_OK; |
2056 | 0 | } |
2057 | | |
2058 | | |
2059 | | /* |
2060 | | YUV444 10bits part |
2061 | | */ |
2062 | | |
2063 | | void evg_yuv444p_10_fill_const(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf, EVGRasterCtx *rctx) |
2064 | 0 | { |
2065 | 0 | u16 *pY, *pU, *pV; |
2066 | 0 | s32 i; |
2067 | 0 | u32 cy, cu, cv; |
2068 | |
|
2069 | 0 | pY = (u16 *) (surf->pixels + y * surf->pitch_y); |
2070 | 0 | pU = (u16 *) (surf->pixels + surf->height*surf->pitch_y + y * surf->pitch_y); |
2071 | 0 | pV = (u16 *) (surf->pixels + 2*surf->height*surf->pitch_y + y * surf->pitch_y); |
2072 | |
|
2073 | 0 | cy = (surf->fill_col_wide>>32) & 0xFFFF; |
2074 | 0 | cy >>=6; |
2075 | 0 | cu = (surf->fill_col_wide>>16) & 0xFFFF; |
2076 | 0 | cu >>=6; |
2077 | 0 | cv = (surf->fill_col_wide) & 0xFFFF; |
2078 | 0 | cv >>=6; |
2079 | |
|
2080 | 0 | for (i=0; i<count; i++) { |
2081 | 0 | u32 a; |
2082 | 0 | u16 *s_pY, *s_pU, *s_pV; |
2083 | 0 | u32 len; |
2084 | 0 | len = spans[i].len; |
2085 | 0 | s_pY = pY + spans[i].x; |
2086 | 0 | s_pU = pU + spans[i].x; |
2087 | 0 | s_pV = pV + spans[i].x; |
2088 | |
|
2089 | 0 | if (spans[i].coverage != 0xFF) { |
2090 | 0 | a = 0xFF * spans[i].coverage; |
2091 | |
|
2092 | 0 | overmask_yuv420p_10_const_run(a, cy, s_pY, len, 0); |
2093 | 0 | overmask_yuv420p_10_const_run(a, cu, s_pU, len, 0); |
2094 | 0 | overmask_yuv420p_10_const_run(a, cv, s_pV, len, 0); |
2095 | 0 | } else { |
2096 | 0 | while (len--) { |
2097 | 0 | set_u16_le(s_pY, cy); |
2098 | 0 | s_pY ++; |
2099 | 0 | set_u16_le(s_pU, cu); |
2100 | 0 | s_pU ++; |
2101 | 0 | set_u16_le(s_pV, cv); |
2102 | 0 | s_pV ++; |
2103 | 0 | } |
2104 | 0 | } |
2105 | 0 | } |
2106 | 0 | } |
2107 | | |
2108 | | void evg_yuv444p_10_fill_const_a(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf, EVGRasterCtx *rctx) |
2109 | 0 | { |
2110 | 0 | u32 a; |
2111 | 0 | u16 *pY, *pU, *pV; |
2112 | 0 | s32 i; |
2113 | 0 | u32 cy, cu, cv; |
2114 | |
|
2115 | 0 | pY = (u16 *) (surf->pixels + y * surf->pitch_y); |
2116 | 0 | pU = (u16 *) (surf->pixels + surf->height*surf->pitch_y + y * surf->pitch_y); |
2117 | 0 | pV = (u16 *) (surf->pixels + 2*surf->height*surf->pitch_y + y * surf->pitch_y); |
2118 | |
|
2119 | 0 | a = (surf->fill_col_wide>>48) & 0xFFFF; |
2120 | 0 | cy = (surf->fill_col_wide>>32) & 0xFFFF; |
2121 | 0 | cy >>=6; |
2122 | 0 | cu = (surf->fill_col_wide>>16) & 0xFFFF; |
2123 | 0 | cu >>=6; |
2124 | 0 | cv = (surf->fill_col_wide) & 0xFFFF; |
2125 | 0 | cv >>=6; |
2126 | |
|
2127 | 0 | if (surf->get_alpha) { |
2128 | 0 | for (i=0; i<count; i++) { |
2129 | 0 | u32 j; |
2130 | 0 | for (j=0; j<spans[i].len; j++) { |
2131 | 0 | u16 *s_pY, *s_pU, *s_pV; |
2132 | 0 | u32 fin; |
2133 | 0 | s32 x = spans[i].x + j; |
2134 | 0 | s_pY = pY + x; |
2135 | 0 | s_pU = pU + x; |
2136 | 0 | s_pV = pV + x; |
2137 | |
|
2138 | 0 | fin = surf->get_alpha(surf->get_alpha_udta, a, x, y) * spans[i].coverage; |
2139 | 0 | fin /= 0xFF; |
2140 | |
|
2141 | 0 | overmask_yuv420p_10_const_run(fin, cy, s_pY, 1, 0); |
2142 | 0 | overmask_yuv420p_10_const_run(fin, cu, s_pU, 1, 0); |
2143 | 0 | overmask_yuv420p_10_const_run(fin, cv, s_pV, 1, 0); |
2144 | 0 | } |
2145 | 0 | } |
2146 | 0 | } else { |
2147 | 0 | for (i=0; i<count; i++) { |
2148 | 0 | u16 *s_pY, *s_pU, *s_pV; |
2149 | 0 | u32 fin, len; |
2150 | 0 | len = spans[i].len; |
2151 | 0 | s_pY = pY + spans[i].x; |
2152 | 0 | s_pU = pU + spans[i].x; |
2153 | 0 | s_pV = pV + spans[i].x; |
2154 | |
|
2155 | 0 | fin = a * spans[i].coverage; |
2156 | 0 | fin /= 0xFF; |
2157 | |
|
2158 | 0 | overmask_yuv420p_10_const_run(fin, cy, s_pY, len, 0); |
2159 | 0 | overmask_yuv420p_10_const_run(fin, cu, s_pU, len, 0); |
2160 | 0 | overmask_yuv420p_10_const_run(fin, cv, s_pV, len, 0); |
2161 | 0 | } |
2162 | 0 | } |
2163 | 0 | } |
2164 | | |
2165 | | void evg_yuv444p_10_fill_var(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf, EVGRasterCtx *rctx) |
2166 | 0 | { |
2167 | 0 | s32 i; |
2168 | 0 | u16 *pY, *pU, *pV; |
2169 | |
|
2170 | 0 | pY = (u16 *) (surf->pixels + y * surf->pitch_y); |
2171 | 0 | pU = (u16 *) (surf->pixels + surf->height*surf->pitch_y + y * surf->pitch_y); |
2172 | 0 | pV = (u16 *) (surf->pixels + 2*surf->height*surf->pitch_y + y * surf->pitch_y); |
2173 | |
|
2174 | 0 | for (i=0; i<count; i++) { |
2175 | 0 | u8 spanalpha; |
2176 | 0 | u32 len; |
2177 | 0 | u64 *p_col; |
2178 | 0 | u16 *s_pY, *s_pU, *s_pV; |
2179 | 0 | len = spans[i].len; |
2180 | 0 | p_col = surf->fill_run(surf->sten, rctx, &spans[i], y); |
2181 | 0 | spanalpha = spans[i].coverage; |
2182 | |
|
2183 | 0 | s_pY = pY + spans[i].x; |
2184 | 0 | s_pU = pU + spans[i].x; |
2185 | 0 | s_pV = pV + spans[i].x; |
2186 | |
|
2187 | 0 | while (len--) { |
2188 | 0 | u64 col = *p_col; |
2189 | 0 | u32 col_a = (col>>48)&0xFFFF; |
2190 | 0 | if (col_a) { |
2191 | 0 | u16 cy, cb, cr; |
2192 | | //col is directly packed as AYCbCr |
2193 | 0 | cy = ((col>>32) & 0xFFFF) >> 6; |
2194 | 0 | cb = ((col>>16) & 0xFFFF) >> 6; |
2195 | 0 | cr = ((col) & 0xFFFF) >> 6; |
2196 | |
|
2197 | 0 | if ((spanalpha!=0xFF) || (col_a != 0xFFFF)) { |
2198 | 0 | u16 spana = spanalpha; |
2199 | 0 | spana <<= 8; |
2200 | 0 | overmask_yuv420p_10(col_a, cy, s_pY, spana); |
2201 | 0 | overmask_yuv420p_10(col_a, cb, s_pU, spana); |
2202 | 0 | overmask_yuv420p_10(col_a, cr, s_pV, spana); |
2203 | 0 | } else { |
2204 | 0 | set_u16_le(s_pY, cy); |
2205 | 0 | set_u16_le(s_pU, cb); |
2206 | 0 | set_u16_le(s_pV, cr); |
2207 | 0 | } |
2208 | 0 | } |
2209 | 0 | s_pY++; |
2210 | 0 | s_pU++; |
2211 | 0 | s_pV++; |
2212 | 0 | p_col++; |
2213 | 0 | } |
2214 | 0 | } |
2215 | 0 | } |
2216 | | |
2217 | | GF_Err evg_surface_clear_yuv444p_10(GF_EVGSurface *_surf, GF_IRect rc, GF_Color col) |
2218 | 0 | { |
2219 | 0 | s32 i; |
2220 | 0 | u8 _cy, _cb, _cr; |
2221 | 0 | u16 cy, cb, cr; |
2222 | 0 | GF_EVGSurface *surf = (GF_EVGSurface *)_surf; |
2223 | 0 | u8 *pY = surf->pixels; |
2224 | 0 | u8 *pU = surf->pixels + surf->height *surf->pitch_y; |
2225 | 0 | u8 *pV, *o_pY, *o_pU, *o_pV; |
2226 | |
|
2227 | 0 | pY += rc.y * surf->pitch_y; |
2228 | 0 | pU += rc.y * surf->pitch_y; |
2229 | 0 | pV = pU + surf->height * surf->pitch_y; |
2230 | |
|
2231 | 0 | pY += 2*rc.x; |
2232 | 0 | pU += 2*rc.x; |
2233 | 0 | pV += 2*rc.x; |
2234 | |
|
2235 | 0 | gf_evg_rgb_to_yuv(surf, col, &_cy, &_cb, &_cr); |
2236 | |
|
2237 | 0 | cy = ((u16)_cy) << 2; |
2238 | 0 | cb = ((u16)_cb) << 2; |
2239 | 0 | cr = ((u16)_cr) << 2; |
2240 | |
|
2241 | 0 | o_pY = pY; |
2242 | 0 | o_pU = pU; |
2243 | 0 | o_pV = pV; |
2244 | |
|
2245 | 0 | for (i = 0; i < rc.height; i++) { |
2246 | 0 | if (!i) { |
2247 | 0 | s32 j; |
2248 | 0 | for (j=0; j<rc.width; j++) { |
2249 | 0 | set_u16_le(& ((u16 *)pY)[j], cy); |
2250 | 0 | set_u16_le(& ((u16 *)pU)[j], cb); |
2251 | 0 | set_u16_le(& ((u16 *)pV)[j], cr); |
2252 | 0 | } |
2253 | 0 | } else { |
2254 | 0 | memcpy(pY, o_pY, 2*rc.width); |
2255 | 0 | memcpy(pU, o_pU, 2*rc.width); |
2256 | 0 | memcpy(pV, o_pV, 2*rc.width); |
2257 | 0 | } |
2258 | 0 | pY += surf->pitch_y; |
2259 | 0 | pU += surf->pitch_y; |
2260 | 0 | pV += surf->pitch_y; |
2261 | 0 | } |
2262 | 0 | return GF_OK; |
2263 | 0 | } |
2264 | | |
2265 | | #endif //GPAC_DISABLE_EVG |