Coverage Report

Created: 2025-12-05 07:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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