Coverage Report

Created: 2025-11-09 07:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gpac/src/evg/stencil.c
Line
Count
Source
1
/*
2
 *      GPAC - Multimedia Framework C SDK
3
 *
4
 *      Authors: Jean Le Feuvre
5
 *      Copyright (c) Telecom ParisTech 2000-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
#include "rast_soft.h"
27
28
#ifndef GPAC_DISABLE_EVG
29
30
static GF_EVGStencil *evg_solid_brush();
31
static GF_EVGStencil *evg_texture_brush();
32
static GF_EVGStencil *evg_linear_gradient_brush();
33
static GF_EVGStencil *evg_radial_gradient_brush();
34
35
36
37
GF_Color color_interpolate(u32 a, u32 b, u8 pos)
38
0
{
39
0
  u32 ca = ((a>>24)     )*(u32)(0xFF-pos)+((b>>24)     )*(u32)pos;
40
0
  u32 cr = ((a>>16)&0xFF)*(u32)(0xFF-pos)+((b>>16)&0xFF)*(u32)pos;
41
0
  u32 cg = ((a>> 8)&0xFF)*(u32)(0xFF-pos)+((b>> 8)&0xFF)*(u32)pos;
42
0
  u32 cb = ((a    )&0xFF)*(u32)(0xFF-pos)+((b    )&0xFF)*(u32)pos;
43
0
  return  (((ca+(ca>>8)+1)>>8)<<24)|
44
0
          (((cr+(cr>>8)+1)>>8)<<16)|
45
0
          (((cg+(cg>>8)+1)>>8)<< 8)|
46
0
          (((cb+(cb>>8)+1)>>8)    );
47
0
}
48
49
50
51
52
/*
53
  Generic gradient tools
54
*/
55
56
0
#define EVGGRADIENTBUFFERSIZE (1<<EVGGRADIENTBITS)
57
0
#define EVGGRADIENTMAXINTPOS    EVGGRADIENTBUFFERSIZE - 1
58
59
static void gradient_update(EVG_BaseGradient *_this)
60
0
{
61
0
  s32 i, c;
62
0
  s32 start, end, diff;
63
0
  Fixed maxPos = INT2FIX(EVGGRADIENTMAXINTPOS);
64
65
0
  _this->updated = 1;
66
67
0
  if (_this->pos[0]>=0) {
68
0
    if(_this->pos[0]>0) {
69
0
      end = FIX2INT(gf_mulfix(_this->pos[0], maxPos));
70
0
      end = MIN(end, EVGGRADIENTMAXINTPOS);
71
0
      for (i=0; i<= end; i++) {
72
0
        _this->precomputed_argb[i] = _this->col[0];
73
0
      }
74
0
    }
75
0
    for (c=0; c<EVGGRADIENTSLOTS; c++) {
76
0
      if (_this->pos[c]<0) break;
77
0
      if (_this->pos[c+1]>=0) {
78
0
        Fixed pos = MIN(_this->pos[c], FIX_ONE);
79
0
        start = FIX2INT(gf_mulfix(pos, maxPos));
80
0
        pos = MIN(_this->pos[c+1], FIX_ONE);
81
0
        end = FIX2INT(gf_mulfix(pos, maxPos));
82
0
        end = MIN(end, EVGGRADIENTMAXINTPOS);
83
0
        diff = end-start;
84
85
0
        if (diff) {
86
0
          for (i=start; i<=end; i++) {
87
0
            _this->precomputed_argb[i] = color_interpolate(_this->col[c], _this->col[c+1],
88
0
                                              (u8) ( ( (i-start) * 255) / diff) );
89
0
          }
90
0
        }
91
0
      } else {
92
0
        Fixed pos = MIN(_this->pos[c+0], FIX_ONE);
93
0
        start = FIX2INT(gf_mulfix(pos, maxPos));
94
0
        for(i=start; i<=EVGGRADIENTMAXINTPOS; i++) {
95
0
          _this->precomputed_argb[i] = _this->col[c];
96
0
        }
97
0
      }
98
0
    }
99
0
  }
100
0
}
101
102
static u32 gradient_get_color(EVG_BaseGradient *_this, s32 pos)
103
0
{
104
0
  s32 max_pos = 1 << EVGGRADIENTBITS;
105
106
0
  switch (_this->mod) {
107
0
  case GF_GRADIENT_MODE_SPREAD:
108
0
    if (pos<0) pos = -pos;
109
0
    return _this->precomputed_dest[(pos & max_pos) ?  EVGGRADIENTMAXINTPOS - (pos % max_pos) :  pos % max_pos];
110
111
0
  case GF_GRADIENT_MODE_REPEAT:
112
0
    while (pos < 0) pos += max_pos;
113
0
    return _this->precomputed_dest[pos % max_pos];
114
115
0
  case GF_GRADIENT_MODE_PAD:
116
0
  default:
117
0
    return _this->precomputed_dest[ MIN(EVGGRADIENTMAXINTPOS, MAX((s32) 0, pos))];
118
0
  }
119
0
}
120
121
GF_EXPORT
122
GF_Err gf_evg_stencil_set_gradient_interpolation(GF_EVGStencil * p, Fixed *pos, GF_Color *col, u32 count)
123
0
{
124
0
  EVG_BaseGradient *_this = (EVG_BaseGradient *) p;
125
0
  if ( (_this->type != GF_STENCIL_LINEAR_GRADIENT) && (_this->type != GF_STENCIL_RADIAL_GRADIENT) ) return GF_BAD_PARAM;
126
0
  if (count>=EVGGRADIENTSLOTS-1) return GF_OUT_OF_MEM;
127
0
  if (count) {
128
0
    memcpy(_this->col, col, sizeof(GF_Color) * count);
129
0
    memcpy(_this->pos, pos, sizeof(Fixed) * count);
130
0
  }
131
0
  _this->col[count] = 0;
132
0
  _this->pos[count] = -FIX_ONE;
133
0
  gradient_update(_this);
134
0
  return GF_OK;
135
0
}
136
137
138
GF_EXPORT
139
GF_Err gf_evg_stencil_push_gradient_interpolation(GF_EVGStencil * p, Fixed pos, GF_Color col)
140
0
{
141
0
  u32 count=0;
142
0
  EVG_BaseGradient *_this = (EVG_BaseGradient *) p;
143
0
  if ( (_this->type != GF_STENCIL_LINEAR_GRADIENT) && (_this->type != GF_STENCIL_RADIAL_GRADIENT) ) return GF_BAD_PARAM;
144
0
  while (count<EVGGRADIENTSLOTS-1) {
145
0
    if (_this->pos[count]==-FIX_ONE) break;
146
0
    count++;
147
0
  }
148
0
  if (count>=EVGGRADIENTSLOTS-1) return GF_OUT_OF_MEM;
149
0
  _this->col[count] = col;
150
0
  _this->pos[count] = pos;
151
0
  count++;
152
0
  _this->col[count] = 0;
153
0
  _this->pos[count] = -FIX_ONE;
154
0
  gradient_update(_this);
155
0
  return GF_OK;
156
0
}
157
158
GF_EXPORT
159
GF_Err gf_evg_stencil_set_gradient_mode(GF_EVGStencil * p, GF_GradientMode mode)
160
0
{
161
0
  EVG_BaseGradient *_this = (EVG_BaseGradient *) p;
162
0
  if ( (_this->type != GF_STENCIL_LINEAR_GRADIENT) && (_this->type != GF_STENCIL_RADIAL_GRADIENT) ) return GF_BAD_PARAM;
163
0
  _this->mod = mode;
164
0
  return GF_OK;
165
0
}
166
167
/*
168
  Generic stencil
169
*/
170
171
GF_EXPORT
172
GF_EVGStencil * gf_evg_stencil_new(GF_StencilType type)
173
0
{
174
0
  GF_EVGStencil *st;
175
0
  switch (type) {
176
0
  case GF_STENCIL_SOLID:
177
0
    st = evg_solid_brush();
178
0
    break;
179
0
  case GF_STENCIL_LINEAR_GRADIENT:
180
0
    st = evg_linear_gradient_brush();
181
0
    break;
182
0
  case GF_STENCIL_RADIAL_GRADIENT:
183
0
    st = evg_radial_gradient_brush();
184
0
    break;
185
0
  case GF_STENCIL_TEXTURE:
186
0
    st = evg_texture_brush();
187
0
    break;
188
0
  default:
189
0
    return NULL;
190
0
  }
191
0
  if (st) {
192
0
    gf_mx2d_init(st->pmat);
193
0
    gf_mx2d_init(st->smat);
194
0
    gf_cmx_init(&st->cmat);
195
0
    st->auto_mx = 1;
196
0
  }
197
0
  return st;
198
0
}
199
200
GF_EXPORT
201
void gf_evg_stencil_delete(GF_EVGStencil * st)
202
0
{
203
0
  switch(st->type) {
204
0
  case GF_STENCIL_SOLID:
205
0
  case GF_STENCIL_LINEAR_GRADIENT:
206
0
  case GF_STENCIL_RADIAL_GRADIENT:
207
0
    gf_free(st);
208
0
    return;
209
0
  case GF_STENCIL_TEXTURE:
210
0
  {
211
0
    EVG_Texture *tx = (EVG_Texture *)st;
212
    /*destroy local texture iof any*/
213
0
    if (tx->owns_texture && tx->pixels) gf_free(tx->pixels);
214
0
    gf_free(st);
215
0
  }
216
0
  return;
217
0
  }
218
0
}
219
220
GF_EXPORT
221
GF_Err gf_evg_stencil_set_auto_matrix(GF_EVGStencil * st, Bool auto_on)
222
0
{
223
0
       if (!st) return GF_BAD_PARAM;
224
0
       st->auto_mx = auto_on ? 1 : 0;
225
0
       return GF_OK;
226
0
}
227
228
GF_EXPORT
229
Bool gf_evg_stencil_get_auto_matrix(GF_EVGStencil * st)
230
0
{
231
0
       return st ? st->auto_mx : GF_FALSE;
232
0
}
233
234
GF_EXPORT
235
GF_Err gf_evg_stencil_set_matrix(GF_EVGStencil * st, GF_Matrix2D *mx)
236
0
{
237
0
  if (!st || (st->type>GF_STENCIL_TEXTURE)) return GF_BAD_PARAM;
238
0
  if (mx) {
239
0
    gf_mx2d_copy(st->smat, *mx);
240
0
  } else {
241
0
    gf_mx2d_init(st->smat);
242
0
  }
243
0
  return GF_OK;
244
0
}
245
246
GF_EXPORT
247
Bool gf_evg_stencil_get_matrix(GF_EVGStencil * st, GF_Matrix2D *mx)
248
0
{
249
0
  if (!st || !mx || (st->type>GF_STENCIL_TEXTURE)) return GF_FALSE;
250
0
  gf_mx2d_copy(*mx, st->smat);
251
0
  return GF_TRUE;
252
0
}
253
254
255
GF_EXPORT
256
GF_StencilType gf_evg_stencil_type(GF_EVGStencil *sten)
257
0
{
258
0
  return sten ? sten->type : 0;
259
0
}
260
261
/*
262
  Solid color stencil
263
*/
264
static void sc_fill_run(GF_EVGStencil *p, EVGRasterCtx *rctx, s32 x, s32 y, u32 count)
265
0
{
266
0
  EVG_Brush *sc = (EVG_Brush *)p;
267
0
  u32 *data = rctx->stencil_pix_run;
268
0
  u64 *data_wide = rctx->surf->not_8bits ? rctx->stencil_pix_run : NULL;
269
0
  while (count) {
270
0
    if (data) *data++ = sc->fill_col;
271
0
    else *data_wide++ = sc->fill_col_wide;
272
273
0
    count--;
274
0
  }
275
276
0
}
277
static GF_EVGStencil *evg_solid_brush()
278
0
{
279
0
  EVG_Brush *tmp;
280
0
  GF_SAFEALLOC(tmp, EVG_Brush);
281
0
  if (!tmp) return 0L;
282
0
  tmp->fill_run = sc_fill_run;
283
0
  tmp->color = 0xFF000000;
284
0
  tmp->alpha = 0xFF;
285
0
  tmp->type = GF_STENCIL_SOLID;
286
0
  return (GF_EVGStencil *) tmp;
287
0
}
288
289
GF_EXPORT
290
GF_Err gf_evg_stencil_set_brush_color(GF_EVGStencil * st, GF_Color c)
291
0
{
292
0
  EVG_Brush *_this = (EVG_Brush *) st;
293
0
  if (!_this  || (_this ->type != GF_STENCIL_SOLID) ) return GF_BAD_PARAM;
294
0
  _this->color = c;
295
0
  return GF_OK;
296
0
}
297
298
GF_EXPORT
299
GF_Color gf_evg_stencil_get_brush_color(GF_EVGStencil * st)
300
0
{
301
0
  EVG_Brush *_this = (EVG_Brush *) st;
302
0
  if (!_this  || (_this ->type != GF_STENCIL_SOLID) ) return 0;
303
0
  return _this->color;
304
0
}
305
306
#define edgeFunction_pre2(a, b_minus_a_x, b_minus_a_y) \
307
0
  ( (_x - a.x) * (b_minus_a_y) - (_y - a.y) * (b_minus_a_x) ) / surf->tri_area
308
309
#define PERSP_VARS_DECL \
310
0
  GF_EVGSurface *surf = rctx->surf; \
311
0
  Float bc1 = edgeFunction_pre2(surf->s_v2, surf->s3_m_s2_x, surf->s3_m_s2_y); \
312
0
  Float bc3 = edgeFunction_pre2(surf->s_v1, surf->s2_m_s1_x, surf->s2_m_s1_y); \
313
0
  Float bc1_inc = surf->s3_m_s2_y / surf->tri_area; \
314
0
  Float bc3_inc = surf->s2_m_s1_y / surf->tri_area; \
315
0
  Float pbc1 = bc1 * surf->s_v1.q; \
316
0
  Float pbc3 = bc3 * surf->s_v3.q; \
317
0
  Float pbc2 = (1.0f - bc1 - bc3) * surf->s_v2.q; \
318
0
  Float pbc1_inc = bc1_inc * surf->s_v1.q; \
319
0
  Float pbc3_inc = bc3_inc * surf->s_v3.q; \
320
0
  Float pbc2_inc = - (bc1_inc + bc3_inc) * surf->s_v2.q; \
321
0
  Float persp_denum = pbc1 + pbc2 + pbc3; \
322
0
  Float pers_denum_inc = pbc1_inc + pbc2_inc + pbc3_inc;
323
324
325
326
//we map texture coords, pt1 is {0,0} pt2 is {1,0} pt3 is {0,1}
327
//y flip is done by switching the points in evg_raster_render_path_3d
328
#define PERSP_APPLY \
329
0
  Fixed ix = FLT2FIX(pbc2 / persp_denum);\
330
0
  Fixed iy = FLT2FIX(pbc3 / persp_denum);\
331
0
  pbc2 += pbc2_inc;\
332
0
  pbc3 += pbc3_inc;\
333
0
  persp_denum += pers_denum_inc;
334
335
/*
336
  linear gradient stencil
337
*/
338
339
static void lg_fill_run(GF_EVGStencil *p, EVGRasterCtx *rctx, s32 _x, s32 _y, u32 count)
340
0
{
341
0
  Fixed _res;
342
0
  s32 val;
343
0
  u32 col;
344
0
  u32 *data = rctx->stencil_pix_run;
345
0
  u64 *data_wide = rctx->surf->not_8bits ? rctx->stencil_pix_run : NULL;
346
0
  EVG_LinearGradient *_this = (EVG_LinearGradient *) p;
347
348
0
  gf_assert(data);
349
350
0
  if (rctx->surf->is_3d_matrix) {
351
0
    PERSP_VARS_DECL
352
353
0
    while (count) {
354
355
0
      PERSP_APPLY
356
357
0
      gf_mx2d_apply_coords(&_this->smat, &ix, &iy);
358
0
      val = FIX2INT(ix);
359
360
0
      col = gradient_get_color((EVG_BaseGradient *)_this, val );
361
0
      if (data_wide) *data_wide++ = evg_col_to_wide(col);
362
0
      else *data++ = col;
363
364
0
      count--;
365
0
    }
366
0
  } else {
367
    /*no need to move x & y to fixed*/
368
0
    _res = (Fixed) (_x * _this->smat.m[0] + _y * _this->smat.m[1] + _this->smat.m[2]);
369
0
    while (count) {
370
0
      val = FIX2INT(_res);
371
0
      _res += _this->smat.m[0];
372
373
0
      col = gradient_get_color((EVG_BaseGradient *)_this, val );
374
0
      if (data_wide) *data_wide++ = evg_col_to_wide(col);
375
0
      else *data++ = col;
376
377
0
      count--;
378
0
    }
379
0
  }
380
0
}
381
382
GF_EXPORT
383
GF_Err gf_evg_stencil_set_linear_gradient(GF_EVGStencil * st, Fixed start_x, Fixed start_y, Fixed end_x, Fixed end_y)
384
0
{
385
0
  GF_Matrix2D mtx;
386
0
  GF_Point2D s;
387
0
  Fixed f;
388
0
  EVG_LinearGradient *_this = (EVG_LinearGradient *) st;
389
0
  if (_this->type != GF_STENCIL_LINEAR_GRADIENT) return GF_BAD_PARAM;
390
391
0
  _this->start.x = start_x;
392
0
  _this->start.y = start_y;
393
0
  _this->end.x = end_x;
394
0
  _this->end.y = end_y;
395
0
  s.x = end_x - start_x;
396
0
  s.y = end_y - start_y;
397
0
  f = gf_v2d_len(&s);
398
0
  if (f) f = gf_invfix(f);
399
400
0
  gf_mx2d_init(mtx);
401
0
  mtx.m[2] = - _this->start.x;
402
0
  mtx.m[5] = - _this->start.y;
403
0
  _this->vecmat = mtx;
404
405
0
  gf_mx2d_init(mtx);
406
0
  gf_mx2d_add_rotation(&mtx, 0, 0, - gf_atan2(s.y, s.x));
407
0
  gf_mx2d_add_matrix(&_this->vecmat, &mtx);
408
409
0
  gf_mx2d_init(mtx);
410
0
  gf_mx2d_add_scale(&mtx, f, f);
411
0
  gf_mx2d_add_matrix(&_this->vecmat, &mtx);
412
0
  return GF_OK;
413
0
}
414
415
static GF_EVGStencil *evg_linear_gradient_brush()
416
0
{
417
0
  s32 i;
418
0
  EVG_LinearGradient *tmp;
419
0
  GF_SAFEALLOC(tmp, EVG_LinearGradient);
420
0
  if (!tmp) return 0L;
421
0
  gf_mx2d_init(tmp->vecmat);
422
0
  tmp->fill_run = lg_fill_run;
423
0
  tmp->type = GF_STENCIL_LINEAR_GRADIENT;
424
0
  for(i=0; i<EVGGRADIENTSLOTS; i++) tmp->pos[i]=-1;
425
426
0
  tmp->alpha = 0xFF;
427
0
  gf_evg_stencil_set_linear_gradient((GF_EVGStencil *)tmp, 0, 0, FIX_ONE, 0);
428
0
  return (GF_EVGStencil *) tmp;
429
0
}
430
431
432
/*
433
  radial gradient stencil
434
*/
435
436
static void rg_fill_run(GF_EVGStencil *p, EVGRasterCtx *rctx, s32 _x, s32 _y, u32 count)
437
0
{
438
0
  Fixed x, y, dx, dy, b, val;
439
0
  s32 pos;
440
0
  u32 col;
441
0
  u32 *data = rctx->stencil_pix_run;
442
0
  u64 *data_wide = rctx->surf->not_8bits ? rctx->stencil_pix_run : NULL;
443
0
  EVG_RadialGradient *_this = (EVG_RadialGradient *) p;
444
445
0
  gf_assert(data);
446
447
0
  if (rctx->surf->is_3d_matrix) {
448
0
    PERSP_VARS_DECL
449
450
0
    while (count) {
451
452
0
      PERSP_APPLY
453
454
0
      gf_mx2d_apply_coords(&_this->smat, &ix, &iy);
455
456
0
      dx = ix - _this->d_f.x;
457
0
      dy = iy - _this->d_f.y;
458
0
      b = gf_mulfix(_this->rad, gf_mulfix(dx, _this->d_f.x) + gf_mulfix(dy,  _this->d_f.y));
459
0
      val = gf_mulfix(b, b) + gf_mulfix(_this->rad, gf_mulfix(dx, dx)+gf_mulfix(dy, dy));
460
0
      b += gf_sqrt(val);
461
0
      pos = FIX2INT(EVGGRADIENTBUFFERSIZE*b);
462
463
0
      col = gradient_get_color((EVG_BaseGradient *)_this, pos );
464
0
      if (data_wide) *data_wide++ = evg_col_to_wide(col);
465
0
      else *data++ = col;
466
467
0
      count--;
468
0
    }
469
0
  } else {
470
0
    x = INT2FIX(_x);
471
0
    y = INT2FIX(_y);
472
0
    gf_mx2d_apply_coords(&_this->smat, &x, &y);
473
474
0
    dx = x - _this->d_f.x;
475
0
    dy = y - _this->d_f.y;
476
0
    while (count) {
477
0
      b = gf_mulfix(_this->rad, gf_mulfix(dx, _this->d_f.x) + gf_mulfix(dy,  _this->d_f.y));
478
0
      val = gf_mulfix(b, b) + gf_mulfix(_this->rad, gf_mulfix(dx, dx)+gf_mulfix(dy, dy));
479
0
      b += gf_sqrt(val);
480
0
      pos = FIX2INT(EVGGRADIENTBUFFERSIZE*b);
481
482
0
      col = gradient_get_color((EVG_BaseGradient *)_this, pos);
483
0
      if (data_wide) *data_wide++ = evg_col_to_wide(col);
484
0
      else *data++ = col;
485
486
0
      dx += _this->d_i.x;
487
0
      dy += _this->d_i.y;
488
0
      count--;
489
0
    }
490
0
  }
491
0
}
492
493
void evg_radial_init(EVG_RadialGradient *_this)
494
0
{
495
0
  GF_Point2D p0, p1;
496
0
  p0.x = p0.y = p1.y = 0;
497
0
  p1.x = FIX_ONE;
498
499
0
  gf_mx2d_apply_point(&_this->smat, &p0);
500
0
  gf_mx2d_apply_point(&_this->smat, &p1);
501
0
  _this->d_i.x = p1.x - p0.x;
502
0
  _this->d_i.y = p1.y - p0.y;
503
504
0
  _this->rad = FIX_ONE - gf_mulfix(_this->d_f.x, _this->d_f.x) - gf_mulfix(_this->d_f.y, _this->d_f.y);
505
0
  if (_this->rad) {
506
0
    _this->rad = gf_invfix(_this->rad);
507
0
  } else {
508
0
    _this->rad = EVGGRADIENTBUFFERSIZE;
509
0
  }
510
0
}
511
512
static GF_EVGStencil *evg_radial_gradient_brush()
513
0
{
514
0
  s32 i;
515
0
  EVG_RadialGradient *tmp;
516
0
  GF_SAFEALLOC(tmp, EVG_RadialGradient);
517
0
  if (!tmp) return 0L;
518
519
0
  tmp->fill_run = rg_fill_run;
520
0
  tmp->type = GF_STENCIL_RADIAL_GRADIENT;
521
0
  for(i=0; i<EVGGRADIENTSLOTS; i++) tmp->pos[i]=-1;
522
523
0
  tmp->center.x = tmp->center.y = FIX_ONE/2;
524
0
  tmp->focus = tmp->center;
525
0
  tmp->radius = tmp->center;
526
0
  tmp->alpha = 0xFF;
527
0
  return (GF_EVGStencil *) tmp;
528
0
}
529
530
531
GF_EXPORT
532
GF_Err gf_evg_stencil_set_radial_gradient(GF_EVGStencil * st, Fixed cx, Fixed cy, Fixed fx, Fixed fy, Fixed x_radius, Fixed y_radius)
533
0
{
534
0
  EVG_RadialGradient *_this = (EVG_RadialGradient *) st;
535
0
  if (_this->type != GF_STENCIL_RADIAL_GRADIENT) return GF_BAD_PARAM;
536
537
0
  _this->center.x = cx;
538
0
  _this->center.y = cy;
539
0
  _this->focus.x = fx;
540
0
  _this->focus.y = fy;
541
0
  _this->radius.x = x_radius;
542
0
  _this->radius.y = y_radius;
543
0
  return GF_OK;
544
0
}
545
546
547
void evg_gradient_precompute(EVG_BaseGradient *grad, GF_EVGSurface *surf)
548
0
{
549
0
  Bool do_cmat, do_yuv, has_a, has_changed;
550
0
  u32 i, nb_col;
551
552
0
  has_changed = grad->updated;
553
554
0
  if (surf->yuv_type) {
555
0
    if (grad->yuv_prof != surf->yuv_prof) {
556
0
      grad->yuv_prof = surf->yuv_prof;
557
0
      has_changed = GF_TRUE;
558
0
    }
559
0
  } else {
560
0
    if (grad->yuv_prof) {
561
0
      grad->yuv_prof = 0;
562
0
      has_changed = GF_TRUE;
563
0
    }
564
0
  }
565
0
  if (!has_changed) {
566
0
    return;
567
0
  }
568
0
  grad->updated = 0;
569
570
0
  do_yuv = (surf->yuv_type==EVG_YUV_NONE) ? GF_FALSE : GF_TRUE;
571
572
0
  do_cmat = (grad->cmat.identity) ? GF_FALSE : GF_TRUE;
573
0
  has_a = (grad->alpha==0xFF) ? GF_FALSE : GF_TRUE;
574
0
  nb_col = (1<<EVGGRADIENTBITS);
575
576
0
  for (i=0; i<nb_col; i++) {
577
0
    u32 argb = grad->precomputed_argb[i];
578
0
    if (has_a) {
579
0
      u32 ca = ((u32) (GF_COL_A(argb) + 1) * grad->alpha) >> 8;
580
0
      argb = ( ((ca<<24) & 0xFF000000) ) | (argb & 0x00FFFFFF);
581
0
    }
582
0
    if (do_cmat)
583
0
      argb = gf_cmx_apply(&grad->cmat, argb);
584
585
0
    if (do_yuv)
586
0
      argb = gf_evg_argb_to_ayuv(surf, argb);
587
588
0
    grad->precomputed_dest[i] = argb;
589
0
  }
590
0
}
591
592
593
/*
594
  Texture stencil
595
    FIXME: add filtering , check bilinear
596
*/
597
598
static GFINLINE s32 mul255(s32 a, s32 b)
599
0
{
600
0
  return ((a+1) * b) >> 8;
601
0
}
602
static u32 EVG_LERP(u32 c0, u32 c1, u8 t)
603
0
{
604
0
  s32 a0, r0, g0, b0;
605
0
  s32 a1, r1, g1, b1;
606
0
  s32 a2, r2, g2, b2;
607
608
0
  if (!t) return c0;
609
610
0
  a0 = GF_COL_A(c0);
611
0
  r0 = GF_COL_R(c0);
612
0
  g0 = GF_COL_G(c0);
613
0
  b0 = GF_COL_B(c0);
614
0
  a1 = GF_COL_A(c1);
615
0
  r1 = GF_COL_R(c1);
616
0
  g1 = GF_COL_G(c1);
617
0
  b1 = GF_COL_B(c1);
618
619
0
  a2 = a0 + mul255(t, (a1 - a0));
620
0
  r2 = r0 + mul255(t, (r1 - r0));
621
0
  g2 = g0 + mul255(t, (g1 - g0));
622
0
  b2 = b0 + mul255(t, (b1 - b0));
623
0
  return GF_COL_ARGB(a2, r2, g2, b2);
624
0
}
625
626
static GFINLINE s64 mul_wide(s64 a, s64 b)
627
0
{
628
0
  return ((a+1) * b) >> 16;
629
0
}
630
static u64 EVG_LERP_WIDE(u64 c0, u64 c1, u8 t)
631
0
{
632
0
  s64 a0, r0, g0, b0;
633
0
  s64 a1, r1, g1, b1;
634
0
  s64 a2, r2, g2, b2;
635
636
0
  if (!t) return c0;
637
638
0
  a0 = (c0>>48) & 0xFFFF;
639
0
  r0 = (c0>>32) & 0xFFFF;
640
0
  g0 = (c0>>16) & 0xFFFF;
641
0
  b0 = (c0) & 0xFFFF;
642
643
0
  a1 = (c1>>48) & 0xFFFF;
644
0
  r1 = (c1>>32) & 0xFFFF;
645
0
  g1 = (c1>>16) & 0xFFFF;
646
0
  b1 = (c1) & 0xFFFF;
647
648
0
  a2 = a0 + mul_wide(t, (a1 - a0));
649
0
  r2 = r0 + mul_wide(t, (r1 - r0));
650
0
  g2 = g0 + mul_wide(t, (g1 - g0));
651
0
  b2 = b0 + mul_wide(t, (b1 - b0));
652
653
0
  return GF_COLW_ARGB(a2, r2, g2, b2);
654
0
}
655
656
//slightly more precise but way too expensive as it uses mx2d apply
657
//#define EXACT_TX_COORDS
658
659
static void tex_untransform_coord(EVG_Texture *_this, s32 _x, s32 _y, Fixed *outx, Fixed *outy)
660
0
{
661
0
  Fixed x, y;
662
663
  /* reverse to texture coords*/
664
0
  x = INT2FIX(_x);
665
0
  y = INT2FIX(_y);
666
0
  gf_mx2d_apply_coords(&_this->smat, &x, &y);
667
668
#ifdef EXACT_TX_COORDS
669
  u32 checkx = 0;
670
  u32 checky = 0;
671
  if (ABS(x)< FIX_ONE/20) checkx = 1;
672
  if (ABS(y)< FIX_ONE/20) checky = 1;
673
674
  /*we may have a numerical stability issues, try to figure out whether we are close from 0 or width/height*/
675
  if ( checkx || checky) {
676
    Fixed tx, ty;
677
    tx = INT2FIX(_x+1);
678
    ty = INT2FIX(_y+1);
679
    gf_mx2d_apply_coords(&_this->smat, &tx, &ty);
680
681
    if (checkx) {
682
      if (tx<0) x = INT2FIX(_this->width - 1);
683
      else x = 0;
684
    }
685
    if (checky) {
686
      if (ty<0) y = INT2FIX(_this->height - 1);
687
      else y = 0;
688
    }
689
  }
690
#endif
691
692
0
  *outx=x;
693
0
  *outy=y;
694
0
}
695
696
#ifdef EXACT_TX_COORDS
697
698
#define TEX_UNTRANSFORM_COORDS \
699
  _x++; \
700
  tex_untransform_coord(_this, _x, _y, &x, &y);
701
702
#else
703
704
#define TEX_UNTRANSFORM_COORDS \
705
0
    x += _this->inc_x; \
706
0
    y += _this->inc_y; \
707
708
#endif
709
710
static u32 evg_paramtx_get_pixel(struct __evg_texture *_this, u32 x, u32 y, EVGRasterCtx *rctx)
711
0
{
712
0
  Float a, r, g, b;
713
0
  _this->tx_callback(_this->tx_callback_udta, x, y, &r, &g, &b, &a);
714
0
  r*=255;
715
0
  g*=255;
716
0
  b*=255;
717
0
  a*=255;
718
0
  return GF_COL_ARGB(a, r, g, b);
719
0
}
720
u64 evg_paramtx_get_pixel_wide(struct __evg_texture *_this, u32 x, u32 y, EVGRasterCtx *rctx)
721
0
{
722
0
  Float a, r, g, b;
723
0
  _this->tx_callback(_this->tx_callback_udta, x, y, &r, &g, &b, &a);
724
0
  r*=0xFFFF;
725
0
  g*=0xFFFF;
726
0
  b*=0xFFFF;
727
0
  a*=0xFFFF;
728
0
  return GF_COLW_ARGB(a, r, g, b);
729
0
}
730
731
static void tex_fill_run_callback(GF_EVGStencil *_p, EVGRasterCtx *rctx, s32 _x, s32 _y, u32 count)
732
0
{
733
0
  EVG_Texture *p = (EVG_Texture *)_p;
734
0
  u32 *data = rctx->stencil_pix_run;
735
0
  while (count) {
736
0
    *data = evg_paramtx_get_pixel(p, _x, _y, NULL);
737
0
    data++;
738
0
    count--;
739
0
    _x++;
740
0
  }
741
0
}
742
743
static void tex_fill_run_callback_wide(GF_EVGStencil *_p, EVGRasterCtx *rctx, s32 _x, s32 _y, u32 count)
744
0
{
745
0
  EVG_Texture *p = (EVG_Texture *)_p;
746
0
  u64 *data = rctx->stencil_pix_run;
747
0
  while (count) {
748
0
    *data = evg_paramtx_get_pixel_wide(p, _x, _y, NULL);
749
0
    data++;
750
0
    count--;
751
0
  }
752
0
}
753
754
//bilinear used fo 2D graphics ?
755
#define USE_BILINEAR  1
756
757
static void tex_fill_run(GF_EVGStencil *p, EVGRasterCtx *rctx, s32 _x, s32 _y, u32 count)
758
0
{
759
0
  s32 cx, x0, y0, m_width, m_height;
760
0
  u32 pix;
761
0
  Bool has_alpha, has_cmat, repeat_s, repeat_t;
762
0
  Fixed x, y;
763
0
#if USE_BILINEAR
764
0
  s32 incx, incy;
765
0
#endif
766
0
  EVG_YUVType yuv_type = rctx->surf->yuv_type;
767
0
  u32 *data = rctx->stencil_pix_run;
768
0
  EVG_Texture *_this = (EVG_Texture *) p;
769
770
0
  tex_untransform_coord(_this, _x, _y, &x, &y);
771
772
0
#if USE_BILINEAR
773
0
  incx = (_this->inc_x>0) ? 1 : -1;
774
0
  incy = (_this->inc_y>0) ? 1 : -1;
775
0
#endif
776
777
0
  repeat_s = _this->mod & GF_TEXTURE_REPEAT_S;
778
0
  repeat_t = _this->mod & GF_TEXTURE_REPEAT_T;
779
780
0
  has_alpha = (_this->alpha != 255) ? GF_TRUE : GF_FALSE;
781
0
  has_cmat = _this->cmat.identity ? GF_FALSE : GF_TRUE;
782
783
0
  m_width = _this->width-1;
784
0
  m_height = _this->height-1;
785
786
0
  while (count) {
787
0
    x0 = FIX2INT(x);
788
789
0
    if (x0 > m_width) {
790
0
      if (repeat_s) {
791
0
        x0 = (x0) % _this->width;
792
0
      } else if (_this->fill_pad_color) {
793
0
        pix = _this->fill_pad_color;
794
0
        TEX_UNTRANSFORM_COORDS
795
0
        goto write_pix;
796
0
      } else {
797
0
        x0 = m_width;
798
0
      }
799
0
    }
800
0
    else if (x0 < 0) {
801
0
      if (repeat_s) {
802
0
        while (x0<0) x0 += _this->width;
803
0
      } else if (_this->fill_pad_color) {
804
0
        pix = _this->fill_pad_color;
805
0
        TEX_UNTRANSFORM_COORDS
806
0
        goto write_pix;
807
0
      } else {
808
0
        x0 = 0;
809
0
      }
810
0
    }
811
812
0
    y0 = FIX2INT(y);
813
0
    if (y0 > m_height) {
814
0
      if (repeat_t) {
815
0
        y0 = (y0) % _this->height;
816
0
      } else if (_this->fill_pad_color) {
817
0
        pix = _this->fill_pad_color;
818
0
        TEX_UNTRANSFORM_COORDS
819
0
        goto write_pix;
820
0
      } else {
821
0
        y0 = m_height;
822
0
      }
823
0
    }
824
0
    else if (y0 < 0) {
825
0
      if (repeat_t) {
826
0
        while (y0<0) y0 += _this->height;
827
0
      } else if (_this->fill_pad_color) {
828
0
        pix = _this->fill_pad_color;
829
0
        TEX_UNTRANSFORM_COORDS
830
0
        goto write_pix;
831
0
      } else {
832
0
        y0 = 0;
833
0
      }
834
0
    }
835
836
0
    pix = _this->tx_get_pixel(_this, x0, y0, rctx);
837
838
0
    TEX_UNTRANSFORM_COORDS
839
840
    /*bilinear filtering*/
841
0
#if USE_BILINEAR
842
0
    if (_this->filter==GF_TEXTURE_FILTER_HIGH_QUALITY) {
843
0
      Bool do_lerp=GF_TRUE;
844
0
      u32 p00, p01, p10, p11;
845
0
      s32 x1, y1;
846
0
      u8 tx, ty;
847
848
0
      tx = FIX2INT(gf_muldiv(x, 255, _this->width) );
849
0
      ty = FIX2INT(gf_muldiv(y, 255, _this->height) );
850
851
0
      x1 = (x0+incx);
852
0
      if (x1<0) {
853
0
        if (!repeat_s)
854
0
          do_lerp=GF_FALSE;
855
0
        else
856
0
          while (x1<0) x1 += _this->width;
857
0
      } else {
858
0
        if (!repeat_s && ((u32) x1 > _this->width))
859
0
          do_lerp=GF_FALSE;
860
0
        else
861
0
          x1 = x1 % _this->width;
862
0
      }
863
0
      y1 = (y0+incy);
864
0
      if (y1<0) {
865
0
        if (!repeat_t)
866
0
          do_lerp=GF_FALSE;
867
0
        else
868
0
          while (y1<0) y1+=_this->height;
869
0
      } else {
870
0
        if (!repeat_t && ((u32) y1 > _this->height))
871
0
          do_lerp=GF_FALSE;
872
0
        else
873
0
          y1 = y1 % _this->height;
874
0
      }
875
876
0
      if (!do_lerp) goto write_pix;
877
878
0
      if (incx>0) {
879
0
        if (x1<x0) tx = 255-tx;
880
0
      } else {
881
0
        if (x1>x0) tx = 255-tx;
882
0
      }
883
0
      if (incy>0) {
884
0
        if (y1<y0) ty = 255-ty;
885
0
      } else {
886
0
        if (y1>y0) ty = 255-ty;
887
0
      }
888
889
0
      p00 = pix;
890
0
      p01 = _this->tx_get_pixel(_this, x1, y0, rctx);
891
0
      p10 = _this->tx_get_pixel(_this, x0, y1, rctx);
892
0
      p11 = _this->tx_get_pixel(_this, x1, y1, rctx);
893
894
0
      p00 = EVG_LERP(p00, p01, tx);
895
0
      p10 = EVG_LERP(p10, p11, tx);
896
0
      pix = EVG_LERP(p00, p10, ty);
897
898
0
    }
899
0
#endif
900
901
0
write_pix:
902
0
    if (has_alpha) {
903
0
      cx = ((GF_COL_A(pix) + 1) * _this->alpha) >> 8;
904
0
      pix = ( (((u32)cx<<24) & 0xFF000000) ) | (pix & 0x00FFFFFF);
905
0
    }
906
    //move pixel to target pixel format, applying color transform matrix
907
0
    if (_this->is_yuv) {
908
      //if surf is rgb, transform
909
0
      if (!yuv_type) {
910
0
        pix = gf_evg_ayuv_to_argb(rctx->surf, pix);
911
        //apply cmat
912
0
        if (has_cmat)
913
0
          pix = gf_cmx_apply(&_this->cmat, pix);
914
0
      } else if (has_cmat) {
915
        //yuv->yuv , use color matrix in yuv domain
916
        //this is equivalent to  gf_evg_ayuv_to_argb, gf_cmx_apply(&_this->cmat, pix), gf_evg_argb_to_ayuv
917
0
        pix = gf_cmx_apply(&_this->yuv_cmat, pix);
918
0
      }
919
0
    }
920
    //texture is RGB
921
0
    else {
922
      //apply cmat
923
0
      if (has_cmat)
924
0
        pix = gf_cmx_apply(&_this->cmat, pix);
925
926
      //dest is yuv, transform
927
0
      if (yuv_type)
928
0
        pix = gf_evg_argb_to_ayuv(rctx->surf, pix);
929
0
    }
930
931
0
    *data++ = pix;
932
0
    count--;
933
0
  }
934
0
}
935
936
937
/*just a little faster...*/
938
static void tex_fill_run_straight(GF_EVGStencil *p, EVGRasterCtx *rctx, s32 _x, s32 _y, u32 count)
939
0
{
940
0
  s32 x0, y0, m_width;
941
0
  u32 pix;
942
0
  u32 conv_type=0;
943
0
  Bool repeat_s = GF_FALSE;
944
0
  u32 pad_y = 0;
945
0
  Fixed x, y;
946
0
  EVG_YUVType yuv_type = rctx->surf->yuv_type;
947
0
  u32 *data = rctx->stencil_pix_run;
948
0
  EVG_Texture *_this = (EVG_Texture *) p;
949
950
  /*get texture coords in FIXED - offset*/
951
0
  x = _this->smat.m[0]*_x + _this->smat.m[2];
952
0
  y = _this->smat.m[4]*_y + _this->smat.m[5];
953
954
  /*we may have a numerical stability issues, try to figure out whether we are close from 0 or width/height*/
955
0
  if (ABS(x)< FIX_ONE/10) {
956
0
    Fixed test = _this->smat.m[0]*(_x+1) + _this->smat.m[2];
957
0
    if (test<0)
958
0
      x = INT2FIX(_this->width - 1);
959
0
    else x = 0;
960
0
  }
961
0
  if (ABS(y)< FIX_ONE/10) {
962
0
    Fixed test = _this->smat.m[4]*(_y+1) + _this->smat.m[5];
963
0
    if (test<0)
964
0
      y = INT2FIX(_this->height - 1);
965
0
    else y = 0;
966
0
  }
967
968
0
  repeat_s = (_this->mod & GF_TEXTURE_REPEAT_S);
969
970
0
  y0 = FIX2INT(y);
971
0
  if (y0<0) {
972
0
    if (_this->mod & GF_TEXTURE_REPEAT_T) {
973
0
      while (y0<0) y0 += (s32) _this->height;
974
0
    } else if (_this->fill_pad_color)
975
0
      pad_y = _this->fill_pad_color;
976
0
    else
977
0
      y0 = 0;
978
0
  } else if (y0 >= (s32) _this->height) {
979
0
    if (_this->mod & GF_TEXTURE_REPEAT_T)
980
0
      while (y0 >= (s32) _this->height) y0 -= (s32) _this->height;
981
0
    else if (_this->fill_pad_color)
982
0
      pad_y = _this->fill_pad_color;
983
0
    else
984
0
      y0 = _this->height-1;
985
0
  }
986
0
  if (pad_y) {
987
0
    while (count) {
988
0
      *data++ = pad_y;
989
0
      count--;
990
0
    }
991
0
    return;
992
0
  }
993
994
0
  m_width = _this->width - 1;
995
996
0
  if (_this->is_yuv && !yuv_type) conv_type = 1;
997
0
  else if (!_this->is_yuv && yuv_type) conv_type = 2;
998
999
1000
0
  while (count) {
1001
0
    x0 = FIX2INT(x);
1002
0
    if (x0 > m_width) {
1003
0
      if (repeat_s) {
1004
0
        while ((u32) x0 > _this->width) x0 -= _this->width;
1005
0
      } else if (_this->fill_pad_color) {
1006
0
        pix = _this->fill_pad_color;
1007
0
        goto write_pix;
1008
0
      } else {
1009
0
        x0 = m_width;
1010
0
      }
1011
0
    }
1012
0
    else if (x0 < 0) {
1013
0
      if (repeat_s) {
1014
0
        while (x0<0) x0 += _this->width;
1015
0
      } else if (_this->fill_pad_color) {
1016
0
        pix = _this->fill_pad_color;
1017
0
        goto write_pix;
1018
0
      } else {
1019
0
        x0 = 0;
1020
0
      }
1021
0
    }
1022
1023
0
    pix = _this->tx_get_pixel(_this, x0, y0, rctx);
1024
1025
0
write_pix:
1026
0
    x += _this->inc_x;
1027
    //move pixel to target pixel format
1028
0
    switch (conv_type) {
1029
0
    case 1:
1030
0
      pix = gf_evg_ayuv_to_argb(rctx->surf, pix);
1031
0
      break;
1032
0
    case 2:
1033
0
      pix = gf_evg_argb_to_ayuv(rctx->surf, pix);
1034
0
      break;
1035
0
    }
1036
1037
0
    *data++ = pix;
1038
0
    count--;
1039
0
  }
1040
0
}
1041
1042
u64 evg_col_to_wide( u32 col)
1043
0
{
1044
0
  u32 a = GF_COL_A(col) << 8 | 0xFF;
1045
0
  u32 r = GF_COL_R(col) << 8 | 0xFF;
1046
0
  u32 g = GF_COL_G(col) << 8 | 0xFF;
1047
0
  u32 b = GF_COL_B(col) << 8 | 0xFF;
1048
0
  return GF_COLW_ARGB(a, r, g, b);
1049
0
}
1050
1051
static void tex_fill_run_wide(GF_EVGStencil *p, EVGRasterCtx *rctx, s32 _x, s32 _y, u32 count)
1052
0
{
1053
0
  s32 x0, y0, m_width, m_height;
1054
0
  u64 pix;
1055
0
  Bool has_alpha, has_cmat, repeat_s, repeat_t;
1056
0
  Fixed x, y;
1057
0
#if USE_BILINEAR
1058
0
  s32 incx, incy;
1059
0
#endif
1060
0
  EVG_YUVType yuv_type = rctx->surf->yuv_type;
1061
0
  u64 *data = rctx->stencil_pix_run;
1062
0
  EVG_Texture *_this = (EVG_Texture *) p;
1063
1064
0
  tex_untransform_coord(_this, _x, _y, &x, &y);
1065
1066
0
#if USE_BILINEAR
1067
0
  incx = (_this->inc_x>0) ? 1 : -1;
1068
0
  incy = (_this->inc_y>0) ? 1 : -1;
1069
0
#endif
1070
1071
0
  repeat_s = _this->mod & GF_TEXTURE_REPEAT_S;
1072
0
  repeat_t = _this->mod & GF_TEXTURE_REPEAT_T;
1073
1074
0
  has_alpha = (_this->alpha != 255) ? GF_TRUE : GF_FALSE;
1075
0
  has_cmat = _this->cmat.identity ? GF_FALSE : GF_TRUE;
1076
1077
0
  m_width = _this->width - 1;
1078
0
  m_height = _this->height - 1;
1079
1080
0
  while (count) {
1081
0
    x0 = FIX2INT(x);
1082
0
    if (x0 > m_width) {
1083
0
      if (repeat_s) {
1084
0
        x0 = (x0) % _this->width;
1085
0
      } else if (_this->fill_pad_color_wide) {
1086
0
        pix = _this->fill_pad_color_wide;
1087
0
        TEX_UNTRANSFORM_COORDS
1088
0
        goto write_pix;
1089
0
      } else {
1090
0
        x0 = m_width;
1091
0
      }
1092
0
    }
1093
0
    else if (x0 < 0) {
1094
0
      if (repeat_s) {
1095
0
        while (x0<0) x0 += _this->width;
1096
0
      } else if (_this->fill_pad_color_wide) {
1097
0
        pix = _this->fill_pad_color_wide;
1098
0
        TEX_UNTRANSFORM_COORDS
1099
0
        goto write_pix;
1100
0
      } else {
1101
0
        x0 = 0;
1102
0
      }
1103
0
    }
1104
1105
0
    y0 = FIX2INT(y);
1106
0
    if (y0 > m_height) {
1107
0
      if (repeat_t) {
1108
0
        y0 = (y0) % _this->height;
1109
0
      } else if (_this->fill_pad_color_wide) {
1110
0
        pix = _this->fill_pad_color_wide;
1111
0
        TEX_UNTRANSFORM_COORDS
1112
0
        goto write_pix;
1113
0
      } else {
1114
0
        y0 = m_height;
1115
0
      }
1116
0
    }
1117
0
    else if (y0 < 0) {
1118
0
      if (repeat_t) {
1119
0
        while (y0<0) y0 += _this->height;
1120
0
      } else if (_this->fill_pad_color_wide) {
1121
0
        pix = _this->fill_pad_color_wide;
1122
0
        TEX_UNTRANSFORM_COORDS
1123
0
        goto write_pix;
1124
0
      } else {
1125
0
        y0 = 0;
1126
0
      }
1127
0
    }
1128
1129
0
    pix = _this->tx_get_pixel_wide(_this, x0, y0, rctx);
1130
1131
0
    TEX_UNTRANSFORM_COORDS
1132
1133
    /*bilinear filtering*/
1134
0
#if USE_BILINEAR
1135
0
    if (_this->filter==GF_TEXTURE_FILTER_HIGH_QUALITY) {
1136
0
      u64 p00, p01, p10, p11;
1137
0
      s32 x1, y1;
1138
0
      u8 tx, ty;
1139
0
      Bool do_lerp=GF_TRUE;
1140
1141
0
      tx = FIX2INT(gf_muldiv(x, 255, _this->width) );
1142
0
      ty = FIX2INT(gf_muldiv(y, 255, _this->height) );
1143
1144
0
      x1 = (x0+incx);
1145
0
      if (x1<0) {
1146
0
        if (!repeat_s)
1147
0
          do_lerp=GF_FALSE;
1148
0
        else
1149
0
          while (x1<0) x1 += _this->width;
1150
0
      } else {
1151
0
        if (!repeat_s && ((u32) x1 > _this->width))
1152
0
          do_lerp=GF_FALSE;
1153
0
        else
1154
0
          x1 = x1 % _this->width;
1155
0
      }
1156
0
      y1 = (y0+incy);
1157
0
      if (y1<0) {
1158
0
        if (!repeat_t)
1159
0
          do_lerp=GF_FALSE;
1160
0
        else
1161
0
          while (y1<0) y1+=_this->height;
1162
0
      } else {
1163
0
        if (!repeat_t && ((u32) y1 > _this->height))
1164
0
          do_lerp=GF_FALSE;
1165
0
        else
1166
0
          y1 = y1 % _this->height;
1167
0
      }
1168
1169
0
      if (!do_lerp) goto write_pix;
1170
1171
1172
0
      if (incx>0) {
1173
0
        if (x1<x0) tx = 255-tx;
1174
0
      } else {
1175
0
        if (x1>x0) tx = 255-tx;
1176
0
      }
1177
0
      if (incy>0) {
1178
0
        if (y1<y0) ty = 255-ty;
1179
0
      } else {
1180
0
        if (y1>y0) ty = 255-ty;
1181
0
      }
1182
1183
0
      p00 = pix;
1184
1185
0
      p01 = _this->tx_get_pixel_wide(_this, x1, y0, rctx);
1186
0
      p10 = _this->tx_get_pixel_wide(_this, x0, y1, rctx);
1187
0
      p11 = _this->tx_get_pixel_wide(_this, x1, y1, rctx);
1188
1189
0
      p00 = EVG_LERP_WIDE(p00, p01, tx);
1190
0
      p10 = EVG_LERP_WIDE(p10, p11, tx);
1191
0
      pix = EVG_LERP_WIDE(p00, p10, ty);
1192
0
    }
1193
0
#endif
1194
1195
0
write_pix:
1196
1197
0
    if (has_alpha) {
1198
0
      u64 _a = (pix>>48)&0xFF;
1199
0
      _a = (_a * _this->alpha) >> 8;
1200
0
      _a<<=48;
1201
0
      pix = ( (_a & 0xFFFF000000000000UL) ) | (pix & 0x0000FFFFFFFFFFFFUL);
1202
0
    }
1203
1204
    //move pixel to target pixel format, applying color transform matrix
1205
0
    if (_this->is_yuv) {
1206
      //if surf is rgb, transform
1207
0
      if (!yuv_type) {
1208
0
        pix = gf_evg_ayuv_to_argb_wide(rctx->surf, pix);
1209
        //apply cmat
1210
0
        if (has_cmat)
1211
0
          pix = gf_cmx_apply_wide(&_this->cmat, pix);
1212
0
      } else if (has_cmat) {
1213
        //yuv->yuv , use color matrix in yuv domain
1214
        //this is equivalent to  gf_evg_ayuv_to_argb, gf_cmx_apply(&_this->cmat, pix), gf_evg_argb_to_ayuv
1215
0
        pix = gf_cmx_apply_wide(&_this->yuv_cmat, pix);
1216
0
      }
1217
0
    }
1218
    //texture is RGB
1219
0
    else {
1220
      //apply cmat
1221
0
      if (has_cmat)
1222
0
        pix = gf_cmx_apply_wide(&_this->cmat, pix);
1223
1224
      //dest is yuv, transform
1225
0
      if (yuv_type)
1226
0
        pix = gf_evg_argb_to_ayuv_wide(rctx->surf, pix);
1227
0
    }
1228
1229
0
    *data++ = pix;
1230
0
    count--;
1231
0
  }
1232
0
}
1233
1234
1235
/*just a little faster...*/
1236
static void tex_fill_run_straight_wide(GF_EVGStencil *p, EVGRasterCtx *rctx, s32 _x, s32 _y, u32 count)
1237
0
{
1238
0
  s32 x0, y0, m_width;
1239
0
  u64 pix, pad_y=0;
1240
0
  u32 conv_type=0;
1241
0
  Bool repeat_s = GF_FALSE;
1242
0
  Fixed x, y;
1243
0
  EVG_YUVType yuv_type = rctx->surf->yuv_type;
1244
0
  u64 *data = rctx->stencil_pix_run;
1245
0
  EVG_Texture *_this = (EVG_Texture *) p;
1246
1247
  /*get texture coords in FIXED - offset*/
1248
0
  x = _this->smat.m[0]*_x + _this->smat.m[2];
1249
0
  y = _this->smat.m[4]*_y + _this->smat.m[5];
1250
1251
  /*we may have a numerical stability issues, try to figure out whether we are close from 0 or width/height*/
1252
0
  if (ABS(x)< FIX_ONE/10) {
1253
0
    Fixed test = _this->smat.m[0]*(_x+1) + _this->smat.m[2];
1254
0
    if (test<0) x = INT2FIX(_this->width - 1);
1255
0
    else x = 0;
1256
0
  }
1257
0
  if (ABS(y)< FIX_ONE/10) {
1258
0
    Fixed test = _this->smat.m[4]*(_y+1) + _this->smat.m[5];
1259
0
    if (test<0) y = INT2FIX(_this->height - 1);
1260
0
    else y = 0;
1261
0
  }
1262
1263
  /* and move in absolute coords*/
1264
0
  repeat_s = (_this->mod & GF_TEXTURE_REPEAT_S);
1265
1266
0
  y0 = FIX2INT(y);
1267
1268
0
  if (y0<0) {
1269
0
    if (_this->mod & GF_TEXTURE_REPEAT_T)
1270
0
      while (y0<0) y0 += _this->height;
1271
0
    else if (_this->fill_pad_color_wide)
1272
0
      pad_y = _this->fill_pad_color_wide;
1273
0
    else
1274
0
      y0 = 0;
1275
0
  } else if (y0>=(s32) _this->height) {
1276
0
    if (_this->mod & GF_TEXTURE_REPEAT_T)
1277
0
      while ((u32) y0 > _this->height) y0 -= _this->height;
1278
0
    else if (_this->fill_pad_color_wide)
1279
0
      pad_y = _this->fill_pad_color_wide;
1280
0
    else
1281
0
      y0 = _this->height-1;
1282
0
  }
1283
0
  if (pad_y) {
1284
0
    while (count) {
1285
0
      *data++ = pad_y;
1286
0
      count--;
1287
0
    }
1288
0
    return;
1289
0
  }
1290
1291
0
  m_width = _this->width - 1;
1292
1293
0
  if (_this->is_yuv && !yuv_type) conv_type = 1;
1294
0
  else if (!_this->is_yuv && yuv_type) conv_type = 2;
1295
1296
0
  while (count) {
1297
0
    x0 = FIX2INT(x);
1298
0
    if (x0 > m_width) {
1299
0
      if (repeat_s) {
1300
0
        x0 = (x0) % _this->width;
1301
0
      } else if (_this->fill_pad_color_wide) {
1302
0
        pix = _this->fill_pad_color_wide;
1303
0
        goto write_pix;
1304
0
      } else {
1305
0
        x0 = m_width;
1306
0
      }
1307
0
    }
1308
0
    else if (x0 < 0) {
1309
0
      if (repeat_s) {
1310
0
        while (x0<0) x0 += _this->width;
1311
0
      } else if (_this->fill_pad_color_wide) {
1312
0
        pix = _this->fill_pad_color_wide;
1313
0
        goto write_pix;
1314
0
      } else {
1315
0
        x0 = 0;
1316
0
      }
1317
0
    }
1318
1319
0
    pix = _this->tx_get_pixel_wide(_this, x0, y0, rctx);
1320
1321
0
write_pix:
1322
0
    x += _this->inc_x;
1323
    //move pixel to target pixel format
1324
0
    switch (conv_type) {
1325
0
    case 1:
1326
0
      pix = gf_evg_ayuv_to_argb_wide(rctx->surf, pix);
1327
0
      break;
1328
0
    case 2:
1329
0
      pix = gf_evg_argb_to_ayuv_wide(rctx->surf, pix);
1330
0
      break;
1331
0
    }
1332
1333
0
    *data++ = pix;
1334
0
    count--;
1335
0
  }
1336
0
}
1337
1338
static void tex_fill_run_3d(GF_EVGStencil *p, EVGRasterCtx *rctx, s32 _x, s32 _y, u32 count)
1339
0
{
1340
0
  s32 cx, x0, y0, m_width, m_height;
1341
0
  u32 pix;
1342
0
  Bool has_alpha, has_cmat, repeat_s, repeat_t;
1343
0
  Fixed x, y;
1344
0
#if USE_BILINEAR
1345
0
  s32 incx, incy;
1346
0
#endif
1347
0
  EVG_YUVType yuv_type = rctx->surf->yuv_type;
1348
0
  u32 *data = rctx->stencil_pix_run;
1349
0
  EVG_Texture *_this = (EVG_Texture *) p;
1350
1351
1352
0
#if USE_BILINEAR
1353
0
  Bool use_bili = (_this->filter==GF_TEXTURE_FILTER_HIGH_QUALITY) ? 1 : 0;
1354
0
  incx = (_this->inc_x>0) ? 1 : -1;
1355
0
  incy = (_this->inc_y>0) ? 1 : -1;
1356
0
#endif
1357
1358
0
  Bool do_mx = gf_mx2d_is_identity(_this->smat_bck) ? GF_FALSE : GF_TRUE;
1359
1360
0
  repeat_s = _this->mod & GF_TEXTURE_REPEAT_S;
1361
0
  repeat_t = _this->mod & GF_TEXTURE_REPEAT_T;
1362
1363
0
  has_alpha = (_this->alpha != 255) ? GF_TRUE : GF_FALSE;
1364
0
  has_cmat = _this->cmat.identity ? GF_FALSE : GF_TRUE;
1365
1366
0
  m_width = _this->width-1;
1367
0
  m_height = _this->height-1;
1368
1369
0
  PERSP_VARS_DECL
1370
1371
0
  while (count) {
1372
0
    PERSP_APPLY
1373
1374
0
    if (do_mx)
1375
0
      gf_mx2d_apply_coords(&_this->smat_bck, &ix, &iy);
1376
1377
0
    x = m_width * ix;
1378
0
    y = m_height * iy;
1379
1380
0
    x0 = FIX2INT(x);
1381
1382
0
    if (x0 > m_width) {
1383
0
      if (repeat_s) {
1384
0
        while (x0>m_width) x0 -= m_width;
1385
0
      } else if (_this->fill_pad_color) {
1386
0
        pix = _this->fill_pad_color;
1387
0
        goto write_pix;
1388
0
      } else {
1389
0
        x0 = m_width;
1390
0
      }
1391
0
    }
1392
0
    else if (x0 < 0) {
1393
0
      if (repeat_s) {
1394
0
        while (x0<0) x0 += m_width;
1395
0
      } else if (_this->fill_pad_color) {
1396
0
        pix = _this->fill_pad_color;
1397
0
        goto write_pix;
1398
0
      } else {
1399
0
        x0 = 0;
1400
0
      }
1401
0
    }
1402
1403
0
    y0 = FIX2INT(y);
1404
0
    if (y0 > m_height) {
1405
0
      if (repeat_t) {
1406
0
        while (y0>m_height) y0 -= m_height;
1407
0
      } else if (_this->fill_pad_color) {
1408
0
        pix = _this->fill_pad_color;
1409
0
        goto write_pix;
1410
0
      } else {
1411
0
        y0 = m_height;
1412
0
      }
1413
0
    }
1414
0
    else if (y0 < 0) {
1415
0
      if (repeat_t) {
1416
0
        while (y0<0) y0 += m_height;
1417
0
      } else if (_this->fill_pad_color) {
1418
0
        pix = _this->fill_pad_color;
1419
0
        goto write_pix;
1420
0
      } else {
1421
0
        y0 = 0;
1422
0
      }
1423
0
    }
1424
1425
0
    pix = _this->tx_get_pixel(_this, x0, y0, rctx);
1426
1427
    /*bilinear filtering*/
1428
0
#if USE_BILINEAR
1429
0
    if (use_bili) {
1430
0
      Bool do_lerp=GF_TRUE;
1431
0
      u32 p00, p01, p10, p11;
1432
0
      s32 x1, y1;
1433
0
      u8 tx, ty;
1434
1435
0
      tx = FIX2INT(gf_muldiv(x, 255, m_width) );
1436
0
      ty = FIX2INT(gf_muldiv(y, 255, m_height) );
1437
1438
0
      x1 = (x0+incx);
1439
0
      if (x1<0) {
1440
0
        if (!repeat_s)
1441
0
          do_lerp=GF_FALSE;
1442
0
        else
1443
0
          while (x1<0) x1 += m_width;
1444
0
      } else {
1445
0
        if (!repeat_s && (x1 > m_width))
1446
0
          do_lerp=GF_FALSE;
1447
0
        else
1448
0
          x1 = x1 % m_width;
1449
0
      }
1450
0
      y1 = (y0+incy);
1451
0
      if (y1<0) {
1452
0
        if (!repeat_t)
1453
0
          do_lerp=GF_FALSE;
1454
0
        else
1455
0
          while (y1<0) y1 += m_height;
1456
0
      } else {
1457
0
        if (!repeat_t && (y1 > m_height))
1458
0
          do_lerp=GF_FALSE;
1459
0
        else
1460
0
          y1 = y1 % m_height;
1461
0
      }
1462
1463
0
      if (!do_lerp) goto write_pix;
1464
1465
0
      if (incx>0) {
1466
0
        if (x1<x0) tx = 255-tx;
1467
0
      } else {
1468
0
        if (x1>x0) tx = 255-tx;
1469
0
      }
1470
0
      if (incy>0) {
1471
0
        if (y1<y0) ty = 255-ty;
1472
0
      } else {
1473
0
        if (y1>y0) ty = 255-ty;
1474
0
      }
1475
1476
0
      p00 = pix;
1477
0
      p01 = _this->tx_get_pixel(_this, x1, y0, rctx);
1478
0
      p10 = _this->tx_get_pixel(_this, x0, y1, rctx);
1479
0
      p11 = _this->tx_get_pixel(_this, x1, y1, rctx);
1480
1481
0
      p00 = EVG_LERP(p00, p01, tx);
1482
0
      p10 = EVG_LERP(p10, p11, tx);
1483
0
      pix = EVG_LERP(p00, p10, ty);
1484
1485
0
    }
1486
0
#endif
1487
1488
0
write_pix:
1489
0
    if (has_alpha) {
1490
0
      cx = ((GF_COL_A(pix) + 1) * _this->alpha) >> 8;
1491
0
      pix = ( (((u32)cx<<24) & 0xFF000000) ) | (pix & 0x00FFFFFF);
1492
0
    }
1493
    //move pixel to target pixel format, applying color transform matrix
1494
0
    if (_this->is_yuv) {
1495
      //if surf is rgb, transform
1496
0
      if (!yuv_type) {
1497
0
        pix = gf_evg_ayuv_to_argb(rctx->surf, pix);
1498
        //apply cmat
1499
0
        if (has_cmat)
1500
0
          pix = gf_cmx_apply(&_this->cmat, pix);
1501
0
      } else if (has_cmat) {
1502
        //yuv->yuv , use color matrix in yuv domain
1503
        //this is equivalent to  gf_evg_ayuv_to_argb, gf_cmx_apply(&_this->cmat, pix), gf_evg_argb_to_ayuv
1504
0
        pix = gf_cmx_apply(&_this->yuv_cmat, pix);
1505
0
      }
1506
0
    }
1507
    //texture is RGB
1508
0
    else {
1509
      //apply cmat
1510
0
      if (has_cmat)
1511
0
        pix = gf_cmx_apply(&_this->cmat, pix);
1512
1513
      //dest is yuv, transform
1514
0
      if (yuv_type)
1515
0
        pix = gf_evg_argb_to_ayuv(rctx->surf, pix);
1516
0
    }
1517
1518
0
    *data++ = pix;
1519
0
    count--;
1520
0
  }
1521
0
}
1522
1523
static void tex_fill_run_3d_wide(GF_EVGStencil *p, EVGRasterCtx *rctx, s32 _x, s32 _y, u32 count)
1524
0
{
1525
0
  s32 x0, y0, m_width, m_height;
1526
0
  u64 pix;
1527
0
  Bool has_alpha, has_cmat, repeat_s, repeat_t;
1528
0
  Fixed x, y;
1529
0
#if USE_BILINEAR
1530
0
  s32 incx, incy;
1531
0
#endif
1532
0
  EVG_YUVType yuv_type = rctx->surf->yuv_type;
1533
0
  u64 *data = rctx->stencil_pix_run;
1534
0
  EVG_Texture *_this = (EVG_Texture *) p;
1535
1536
1537
0
#if USE_BILINEAR
1538
0
  Bool use_bili = (_this->filter==GF_TEXTURE_FILTER_HIGH_QUALITY) ? 1 : 0;
1539
0
  incx = (_this->inc_x>0) ? 1 : -1;
1540
0
  incy = (_this->inc_y>0) ? 1 : -1;
1541
0
#endif
1542
1543
0
  Bool do_mx = gf_mx2d_is_identity(_this->smat_bck) ? GF_FALSE : GF_TRUE;
1544
1545
0
  repeat_s = _this->mod & GF_TEXTURE_REPEAT_S;
1546
0
  repeat_t = _this->mod & GF_TEXTURE_REPEAT_T;
1547
1548
0
  has_alpha = (_this->alpha != 255) ? GF_TRUE : GF_FALSE;
1549
0
  has_cmat = _this->cmat.identity ? GF_FALSE : GF_TRUE;
1550
1551
0
  m_width = _this->width-1;
1552
0
  m_height = _this->height-1;
1553
1554
0
  PERSP_VARS_DECL
1555
1556
0
  while (count) {
1557
0
    PERSP_APPLY
1558
1559
0
    if (do_mx)
1560
0
      gf_mx2d_apply_coords(&_this->smat_bck, &ix, &iy);
1561
1562
0
    x = m_width * ix;
1563
0
    y = m_height * iy;
1564
1565
0
    x0 = FIX2INT(x);
1566
1567
0
    if (x0 > m_width) {
1568
0
      if (repeat_s) {
1569
0
        while (x0>m_width) x0 -= m_width;
1570
0
      } else if (_this->fill_pad_color_wide) {
1571
0
        pix = _this->fill_pad_color_wide;
1572
0
        goto write_pix;
1573
0
      } else {
1574
0
        x0 = m_width;
1575
0
      }
1576
0
    }
1577
0
    else if (x0 < 0) {
1578
0
      if (repeat_s) {
1579
0
        while (x0<0) x0 += m_width;
1580
0
      } else if (_this->fill_pad_color_wide) {
1581
0
        pix = _this->fill_pad_color_wide;
1582
0
        goto write_pix;
1583
0
      } else {
1584
0
        x0 = 0;
1585
0
      }
1586
0
    }
1587
1588
0
    y0 = FIX2INT(y);
1589
0
    if (y0 > m_height) {
1590
0
      if (repeat_t) {
1591
0
        while (y0>m_height) y0 -= m_height;
1592
0
      } else if (_this->fill_pad_color_wide) {
1593
0
        pix = _this->fill_pad_color_wide;
1594
0
        goto write_pix;
1595
0
      } else {
1596
0
        y0 = m_height;
1597
0
      }
1598
0
    }
1599
0
    else if (y0 < 0) {
1600
0
      if (repeat_t) {
1601
0
        while (y0<0) y0 += m_height;
1602
0
      } else if (_this->fill_pad_color_wide) {
1603
0
        pix = _this->fill_pad_color_wide;
1604
0
        goto write_pix;
1605
0
      } else {
1606
0
        y0 = 0;
1607
0
      }
1608
0
    }
1609
1610
0
    pix = _this->tx_get_pixel_wide(_this, x0, y0, rctx);
1611
1612
    /*bilinear filtering*/
1613
0
#if USE_BILINEAR
1614
0
    if (use_bili) {
1615
0
      Bool do_lerp=GF_TRUE;
1616
0
      u64 p00, p01, p10, p11;
1617
0
      s32 x1, y1;
1618
0
      u8 tx, ty;
1619
1620
0
      tx = FIX2INT(gf_muldiv(x, 255, m_width) );
1621
0
      ty = FIX2INT(gf_muldiv(y, 255, m_height) );
1622
1623
0
      x1 = (x0+incx);
1624
0
      if (x1<0) {
1625
0
        if (!repeat_s)
1626
0
          do_lerp=GF_FALSE;
1627
0
        else
1628
0
          while (x1<0) x1 += m_width;
1629
0
      } else {
1630
0
        if (!repeat_s && (x1 > m_width))
1631
0
          do_lerp=GF_FALSE;
1632
0
        else
1633
0
          x1 = x1 % m_width;
1634
0
      }
1635
0
      y1 = (y0+incy);
1636
0
      if (y1<0) {
1637
0
        if (!repeat_t)
1638
0
          do_lerp=GF_FALSE;
1639
0
        else
1640
0
          while (y1<0) y1 += m_height;
1641
0
      } else {
1642
0
        if (!repeat_t && (y1 > m_height))
1643
0
          do_lerp=GF_FALSE;
1644
0
        else
1645
0
          y1 = y1 % m_height;
1646
0
      }
1647
1648
0
      if (!do_lerp) goto write_pix;
1649
1650
0
      if (incx>0) {
1651
0
        if (x1<x0) tx = 255-tx;
1652
0
      } else {
1653
0
        if (x1>x0) tx = 255-tx;
1654
0
      }
1655
0
      if (incy>0) {
1656
0
        if (y1<y0) ty = 255-ty;
1657
0
      } else {
1658
0
        if (y1>y0) ty = 255-ty;
1659
0
      }
1660
1661
0
      p00 = pix;
1662
0
      p01 = _this->tx_get_pixel_wide(_this, x1, y0, rctx);
1663
0
      p10 = _this->tx_get_pixel_wide(_this, x0, y1, rctx);
1664
0
      p11 = _this->tx_get_pixel_wide(_this, x1, y1, rctx);
1665
1666
0
      p00 = EVG_LERP_WIDE(p00, p01, tx);
1667
0
      p10 = EVG_LERP_WIDE(p10, p11, tx);
1668
0
      pix = EVG_LERP_WIDE(p00, p10, ty);
1669
1670
0
    }
1671
0
#endif
1672
1673
0
write_pix:
1674
0
    if (has_alpha) {
1675
0
      u64 _a = (pix>>48)&0xFF;
1676
0
      _a = (_a * _this->alpha) >> 8;
1677
0
      _a<<=48;
1678
0
      pix = ( (_a & 0xFFFF000000000000UL) ) | (pix & 0x0000FFFFFFFFFFFFUL);
1679
0
    }
1680
    //move pixel to target pixel format, applying color transform matrix
1681
0
    if (_this->is_yuv) {
1682
      //if surf is rgb, transform
1683
0
      if (!yuv_type) {
1684
0
        pix = gf_evg_ayuv_to_argb_wide(rctx->surf, pix);
1685
        //apply cmat
1686
0
        if (has_cmat)
1687
0
          pix = gf_cmx_apply_wide(&_this->cmat, pix);
1688
0
      } else if (has_cmat) {
1689
        //yuv->yuv , use color matrix in yuv domain
1690
        //this is equivalent to  gf_evg_ayuv_to_argb, gf_cmx_apply(&_this->cmat, pix), gf_evg_argb_to_ayuv
1691
0
        pix = gf_cmx_apply_wide(&_this->yuv_cmat, pix);
1692
0
      }
1693
0
    }
1694
    //texture is RGB
1695
0
    else {
1696
      //apply cmat
1697
0
      if (has_cmat)
1698
0
        pix = gf_cmx_apply_wide(&_this->cmat, pix);
1699
1700
      //dest is yuv, transform
1701
0
      if (yuv_type)
1702
0
        pix = gf_evg_argb_to_ayuv_wide(rctx->surf, pix);
1703
0
    }
1704
1705
0
    *data++ = pix;
1706
0
    count--;
1707
0
  }
1708
0
}
1709
1710
GF_EVGStencil *evg_texture_brush()
1711
0
{
1712
0
  EVG_Texture *tmp;
1713
0
  GF_SAFEALLOC(tmp, EVG_Texture);
1714
0
  if (!tmp) return 0L;
1715
1716
0
  tmp->fill_run = tex_fill_run;
1717
0
  tmp->type = GF_STENCIL_TEXTURE;
1718
  /*default is using the surface settings*/
1719
0
  gf_evg_stencil_set_filter( (GF_EVGStencil *) tmp, GF_TEXTURE_FILTER_HIGH_SPEED);
1720
0
  tmp->mod = 0;
1721
0
  gf_cmx_init(&tmp->cmat);
1722
0
  tmp->alpha = 255;
1723
0
  return (GF_EVGStencil *) tmp;
1724
0
}
1725
1726
1727
u32 get_pix_argb(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
1728
0
{
1729
0
  u8 *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1730
0
  return GF_COL_ARGB(*(pix) & 0xFF, *(pix+1) & 0xFF, *(pix+2) & 0xFF, *(pix+3) & 0xFF);
1731
0
}
1732
u32 get_pix_rgba(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
1733
0
{
1734
0
  u8 *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1735
0
  return GF_COL_ARGB(*(pix+3) & 0xFF, *(pix) & 0xFF, *(pix+1) & 0xFF, *(pix+2) & 0xFF);
1736
0
}
1737
u32 get_pix_grba(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
1738
0
{
1739
0
  u8 *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1740
0
  return GF_COL_ARGB(*(pix+3) & 0xFF, *(pix+1) & 0xFF, *(pix) & 0xFF, *(pix+2) & 0xFF);
1741
0
}
1742
u32 get_pix_abgr(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
1743
0
{
1744
0
  u8 *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1745
0
  return GF_COL_ARGB(*(pix) & 0xFF, *(pix+3) & 0xFF, *(pix+2) & 0xFF, *(pix+1) & 0xFF);
1746
0
}
1747
u32 get_pix_bgra(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
1748
0
{
1749
0
  u8 *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1750
0
  return GF_COL_ARGB(*(pix+3) & 0xFF, *(pix+2) & 0xFF, *(pix+1) & 0xFF, *(pix) & 0xFF);
1751
0
}
1752
u32 get_pix_rgbx(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
1753
0
{
1754
0
  u8 *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1755
0
  return GF_COL_ARGB(0xFF, *(pix) & 0xFF, *(pix+1) & 0xFF, *(pix+2) & 0xFF);
1756
0
}
1757
u32 get_pix_xrgb(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
1758
0
{
1759
0
  u8 *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1760
0
  return GF_COL_ARGB(0xFF, *(pix+1) & 0xFF, *(pix+2) & 0xFF, *(pix+3) & 0xFF);
1761
0
}
1762
u32 get_pix_xbgr(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
1763
0
{
1764
0
  u8 *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1765
0
  return GF_COL_ARGB(0xFF, *(pix+3) & 0xFF, *(pix+2) & 0xFF, *(pix+1) & 0xFF);
1766
0
}
1767
u32 get_pix_bgrx(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
1768
0
{
1769
0
  u8 *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1770
0
  return GF_COL_ARGB(0xFF, *(pix+2) & 0xFF, *(pix+1) & 0xFF, *(pix) & 0xFF);
1771
0
}
1772
u32 get_pix_rgb_24(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
1773
0
{
1774
0
  u8 *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1775
0
  return GF_COL_ARGB(0xFF, *pix & 0xFF, *(pix+1) & 0xFF, *(pix+2) & 0xFF);
1776
0
}
1777
u32 get_pix_gbr_24(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
1778
0
{
1779
0
  u8 *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1780
0
  return GF_COL_ARGB(0xFF, *(pix+1) & 0xFF, *(pix+2) & 0xFF, *pix & 0xFF);
1781
0
}
1782
u32 get_pix_bgr_24(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
1783
0
{
1784
0
  u8 *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1785
0
  return GF_COL_ARGB(0xFF, *(pix+2) & 0xFF, * (pix+1) & 0xFF, *pix & 0xFF);
1786
0
}
1787
u32 get_pix_332(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
1788
0
{
1789
0
  u8 *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1790
0
  u32 r = pix[0]>>5;
1791
0
  u32 g = (pix[0]>>2)&0x7;
1792
0
  u32 b = pix[0]&0x3;
1793
0
  return GF_COL_ARGB(0xFF, (r << 5), (g << 5), (b << 6));
1794
0
}
1795
u32 get_pix_444(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
1796
0
{
1797
0
  u8 *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1798
0
  u32 r = pix[0]&0x0f;
1799
0
  u32 g = (pix[1]>>4)&0x0f;
1800
0
  u32 b = pix[1]&0x0f;
1801
0
  return GF_COL_ARGB(0xFF, (r << 4), (g << 4), (b << 4));
1802
0
}
1803
u32 get_pix_555(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
1804
0
{
1805
0
  u8 *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1806
0
  u32 r = (pix[0]>>2) & 0x1f;
1807
0
  u32 g = (pix[0])&0x3;
1808
0
  g<<=3;
1809
0
  g |= (pix[1]>>5) & 0x7;
1810
0
  u32 b = pix[1] & 0x1f;
1811
0
  return GF_COL_ARGB(0xFF, (r << 3), (g << 3), (b << 3));
1812
0
}
1813
u32 get_pix_565(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
1814
0
{
1815
0
  u8 *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1816
0
  u32 r = (pix[0]>>3) & 0x1f;
1817
0
  u32 g = (pix[0])&0x7;
1818
0
  g<<=3;
1819
0
  g |= (pix[1]>>5) & 0x7;
1820
0
  u32 b = pix[1] & 0x1f;
1821
0
  return GF_COL_ARGB(0xFF, (r << 3), (g << 2), (b << 3));
1822
0
}
1823
u32 get_pix_palette_alpha(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
1824
0
{
1825
0
  u8 *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1826
0
  u32 val = *pix;
1827
0
  if (val >= _this->palette_colors) return GF_COL_ARGB(0xFF, 0xFF, 0xFF, 0xFF);
1828
0
  pix = (u8*)_this->palette + val*4;
1829
0
  return GF_COL_ARGB(pix[_this->pidx_a], pix[_this->pidx_r], pix[_this->pidx_g], pix[_this->pidx_b]);
1830
0
}
1831
u32 get_pix_palette(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
1832
0
{
1833
0
  u8 *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1834
0
  u32 val = *pix;
1835
0
  if (val >= _this->palette_colors) return GF_COL_ARGB(0xFF, 0xFF, 0xFF, 0xFF);
1836
0
  pix = (u8*)_this->palette + val*3;
1837
0
  return GF_COL_ARGB(0xFF, pix[_this->pidx_r], pix[_this->pidx_g], pix[_this->pidx_b]);
1838
0
}
1839
u32 get_pix_grey(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
1840
0
{
1841
0
  u8 *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1842
0
  u8 val = *pix;
1843
0
  return GF_COL_ARGB(0xFF, val, val, val);
1844
0
}
1845
u32 get_pix_alphagrey(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
1846
0
{
1847
0
  u8 a, g;
1848
0
  u8 *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1849
0
  a = *pix;
1850
0
  g = *(pix+1);
1851
0
  return GF_COL_ARGB(a, g, g, g);
1852
0
}
1853
u32 get_pix_greyalpha(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
1854
0
{
1855
0
  u8 a, g;
1856
0
  u8 *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1857
0
  g = *pix;
1858
0
  a = *(pix+1);
1859
0
  return GF_COL_ARGB(a, g, g, g);
1860
0
}
1861
u32 get_pix_yuv420p(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
1862
0
{
1863
0
  u8 *pY = _this->pixels + y * _this->stride + x;
1864
0
  u8 *pU = _this->pix_u + y/2 * _this->stride/2 + x/2;
1865
0
  u8 *pV = _this->pix_v + y/2 * _this->stride/2 + x/2;
1866
0
  return GF_COL_ARGB(0xFF, *pY, *pU, *pV);
1867
0
}
1868
1869
#ifdef GPAC_BIG_ENDIAN
1870
1871
#define GET_LE_10BIT_AS_8(_ptr) ( (((u16)(_ptr)[1])<<8 | (u16)(_ptr)[0] ) >> 2 )
1872
#define GET_LE_10BIT_AS_16(_ptr) ( (((u16)(_ptr)[1])<<8 | (u16)(_ptr)[0] ) << 6 )
1873
1874
//#define GET_LE_10BIT_LEFT_AS_8(_ptr) ( (((u16)(_ptr)[1])<<8 | (u16)(_ptr)[0] ) >> 8 )
1875
#define GET_LE_10BIT_LEFT_AS_8(_ptr) ((_ptr)[1] )
1876
#define GET_LE_10BIT_LEFT_AS_16(_ptr) ( (((u16)(_ptr)[1])<<8 | (u16)(_ptr)[0] ) & 0xFFC0 )
1877
1878
#define GET_BE_10BIT_AS_8(_ptr) ( (*(u16 *)(_ptr)) >> 2 )
1879
#define GET_BE_10BIT_AS_16(_ptr) ( (*(u16 *)(_ptr)) << 6 )
1880
1881
#else
1882
1883
0
#define GET_LE_10BIT_AS_8(_ptr) ( (*(u16 *)(_ptr)) >> 2 )
1884
0
#define GET_LE_10BIT_AS_16(_ptr) ( (*(u16 *)(_ptr)) << 6 )
1885
1886
0
#define GET_LE_10BIT_LEFT_AS_8(_ptr) ( (*(u16 *)(_ptr)) >> 8 )
1887
0
#define GET_LE_10BIT_LEFT_AS_16(_ptr) ( (*(u16 *)(_ptr)) & 0xFFC0 )
1888
1889
1890
#define GET_BE_10BIT_AS_8(_ptr) ( (((u16)(_ptr)[0])<<8 | (u16)(_ptr)[1] ) >> 2 )
1891
#define GET_BE_10BIT_AS_16(_ptr) ( (((u16)(_ptr)[0])<<8 | (u16)(_ptr)[1] ) << 6 )
1892
1893
#endif
1894
1895
1896
u32 get_pix_yuv420p_10(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
1897
0
{
1898
0
  u8 vy, vu, vv;
1899
0
  u8 *pY = _this->pixels + y * _this->stride + x*2;
1900
0
  u8 *pU = _this->pix_u + y/2 * _this->stride/2 + (x/2)*2;
1901
0
  u8 *pV = _this->pix_v + y/2 * _this->stride/2 + (x/2)*2;
1902
1903
0
  vy = GET_LE_10BIT_AS_8(pY);
1904
0
  vu = GET_LE_10BIT_AS_8(pU);
1905
0
  vv = GET_LE_10BIT_AS_8(pV);
1906
1907
0
  return GF_COL_ARGB(0xFF, vy, vu, vv);
1908
0
}
1909
1910
u64 get_pix_yuv420p_10_wide(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
1911
0
{
1912
0
  u16 vy, vu, vv;
1913
0
  u8 *pY = _this->pixels + y * _this->stride + x*2;
1914
0
  u8 *pU = _this->pix_u + y/2 * _this->stride/2 + (x/2)*2;
1915
0
  u8 *pV = _this->pix_v + y/2 * _this->stride/2 + (x/2)*2;
1916
1917
0
  vy = GET_LE_10BIT_AS_16(pY);
1918
0
  vu = GET_LE_10BIT_AS_16(pU);
1919
0
  vv = GET_LE_10BIT_AS_16(pV);
1920
1921
0
  return GF_COLW_ARGB(0xFFFF, vy, vu, vv);
1922
0
}
1923
u32 get_pix_yuv420p_a(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
1924
0
{
1925
0
  u8 *pY = _this->pixels + y * _this->stride + x;
1926
0
  u8 *pU = _this->pix_u + y/2 * _this->stride/2 + x/2;
1927
0
  u8 *pV = _this->pix_v + y/2 * _this->stride/2 + x/2;
1928
0
  u8 *pA = _this->pix_a  + y * _this->stride + x;
1929
1930
0
  return GF_COL_ARGB(*pA, *pY, *pU, *pV);
1931
0
}
1932
u32 get_pix_yuv422p(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
1933
0
{
1934
0
  u8 *pY = _this->pixels + y * _this->stride + x;
1935
0
  u8 *pU = _this->pix_u + y * _this->stride/2 + x/2;
1936
0
  u8 *pV = _this->pix_v + y * _this->stride/2 + x/2;
1937
0
  return GF_COL_ARGB(0xFF, *pY, *pU, *pV);
1938
0
}
1939
u32 get_pix_yuv422p_10(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
1940
0
{
1941
0
  u8 vy, vu, vv;
1942
0
  u8 *pY = _this->pixels + y * _this->stride + x*2;
1943
0
  u8 *pU = _this->pix_u + y * _this->stride/2 + (x/2)*2;
1944
0
  u8 *pV = _this->pix_v + y * _this->stride/2 + (x/2)*2;
1945
1946
0
  vy = GET_LE_10BIT_AS_8(pY);
1947
0
  vu = GET_LE_10BIT_AS_8(pU);
1948
0
  vv = GET_LE_10BIT_AS_8(pV);
1949
0
  return GF_COL_ARGB(0xFF, vy, vu, vv);
1950
0
}
1951
1952
u64 get_pix_yuv422p_10_wide(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
1953
0
{
1954
0
  u16 vy, vu, vv;
1955
0
  u8 *pY = _this->pixels + y * _this->stride + x*2;
1956
0
  u8 *pU = _this->pix_u + y * _this->stride/2 + (x/2)*2;
1957
0
  u8 *pV = _this->pix_v + y * _this->stride/2 + (x/2)*2;
1958
1959
0
  vy = GET_LE_10BIT_AS_16(pY);
1960
0
  vu = GET_LE_10BIT_AS_16(pU);
1961
0
  vv = GET_LE_10BIT_AS_16(pV);
1962
0
  return GF_COLW_ARGB(0xFFFF, vy, vu, vv);
1963
0
}
1964
1965
u32 get_pix_yuv444p(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
1966
0
{
1967
0
  u8 *pY = _this->pixels + y * _this->stride + x;
1968
0
  u8 *pU = _this->pix_u + y * _this->stride + x;
1969
0
  u8 *pV = _this->pix_v + y * _this->stride + x;
1970
0
  return GF_COL_ARGB(0xFF, *pY, *pU, *pV);
1971
0
}
1972
u32 get_pix_yuv444p_10(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
1973
0
{
1974
0
  u8 vy, vu, vv;
1975
0
  u8 *pY = _this->pixels + y * _this->stride + x*2;
1976
0
  u8 *pU = _this->pix_u + y * _this->stride + x*2;
1977
0
  u8 *pV = _this->pix_v + y * _this->stride + x*2;
1978
1979
0
  vy = GET_LE_10BIT_AS_8(pY);
1980
0
  vu = GET_LE_10BIT_AS_8(pU);
1981
0
  vv = GET_LE_10BIT_AS_8(pV);
1982
0
  return GF_COL_ARGB(0xFF, vy, vu, vv);
1983
0
}
1984
u64 get_pix_yuv444p_10_wide(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
1985
0
{
1986
0
  u16 vy, vu, vv;
1987
0
  u8 *pY = _this->pixels + y * _this->stride + x*2;
1988
0
  u8 *pU = _this->pix_u + y * _this->stride + x*2;
1989
0
  u8 *pV = _this->pix_v + y * _this->stride + x*2;
1990
1991
0
  vy = GET_LE_10BIT_AS_16(pY);
1992
0
  vu = GET_LE_10BIT_AS_16(pU);
1993
0
  vv = GET_LE_10BIT_AS_16(pV);
1994
0
  return GF_COLW_ARGB(0xFFFF, vy, vu, vv);
1995
0
}
1996
u32 get_pix_yuv444p_a(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
1997
0
{
1998
0
  u8 *pY = _this->pixels + y * _this->stride + x;
1999
0
  u8 *pU = _this->pix_u + y * _this->stride + x;
2000
0
  u8 *pV = _this->pix_v + y * _this->stride + x;
2001
0
  u8 *pA = _this->pix_a + y * _this->stride + x;
2002
0
  return GF_COL_ARGB(*pA, *pY, *pU, *pV);
2003
0
}
2004
u32 get_pix_yuv_nv12(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
2005
0
{
2006
0
  u8 *pY = _this->pixels + y * _this->stride + x;
2007
0
  u8 *pU = _this->pix_u + y/2 * _this->stride + (x/2)*2;
2008
0
  return GF_COL_ARGB(0xFF, *pY, *pU, *(pU+1));
2009
0
}
2010
2011
u32 get_pix_yuv_nv12_10(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
2012
0
{
2013
0
  u16 vy, vu, vv;
2014
0
  u8 *pY = _this->pixels + y * _this->stride + x*2;
2015
0
  u8 *pU = _this->pix_u  + y/2 * _this->stride + (x/2)*4;
2016
0
  vy = GET_LE_10BIT_AS_8(pY);
2017
0
  vu = GET_LE_10BIT_AS_8(pU);
2018
0
  vv = GET_LE_10BIT_AS_8(pU+2);
2019
2020
0
  return GF_COL_ARGB(0xFF, vy, vu, vv);
2021
0
}
2022
u64 get_pix_yuv_nv12_10_wide(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
2023
0
{
2024
0
  u16 vy, vu, vv;
2025
0
  u8 *pY = _this->pixels + y * _this->stride + x*2;
2026
0
  u8 *pU = _this->pix_u + y/2 * _this->stride + (x/2)*4;
2027
2028
0
  vy = GET_LE_10BIT_AS_16(pY);
2029
0
  vu = GET_LE_10BIT_AS_16(pU);
2030
0
  vv = GET_LE_10BIT_AS_16(pU+2);
2031
2032
0
  return GF_COLW_ARGB(0xFFFF, vy, vu, vv);
2033
0
}
2034
u32 get_pix_yuv_nv21(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
2035
0
{
2036
0
  u8 *pY = _this->pixels + y * _this->stride + x;
2037
0
  u8 *pU = _this->pix_u + y/2 * _this->stride + (x/2)*2;
2038
0
  return GF_COL_ARGB(0xFF, *pY, *(pU+1), *pU);
2039
0
}
2040
u32 get_pix_yuv_nv21_10(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
2041
0
{
2042
0
  u8 vy, vu, vv;
2043
0
  u8 *pY = _this->pixels + y * _this->stride + x*2;
2044
0
  u8 *pU = _this->pix_u + y/2 * _this->stride + (x/2)*4;
2045
2046
0
  vy = GET_LE_10BIT_AS_8(pY);
2047
0
  vu = GET_LE_10BIT_AS_8(pU);
2048
0
  vv = GET_LE_10BIT_AS_8(pU+2);
2049
2050
0
  return GF_COL_ARGB(0xFF, vy, vv, vu);
2051
0
}
2052
u64 get_pix_yuv_nv21_10_wide(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
2053
0
{
2054
0
  u16 vy, vu, vv;
2055
0
  u8 *pY = _this->pixels + y * _this->stride + x*2;
2056
0
  u8 *pU = _this->pix_u + y/2 * _this->stride + (x/2)*4;
2057
2058
0
  vy = GET_LE_10BIT_AS_16(pY);
2059
0
  vu = GET_LE_10BIT_AS_16(pU);
2060
0
  vv = GET_LE_10BIT_AS_16(pU+2);
2061
0
  return GF_COLW_ARGB(0xFFFF, vy, vv, vu);
2062
0
}
2063
u32 get_pix_yuyv(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
2064
0
{
2065
0
  u8 *pY = _this->pixels + y * _this->stride + (x/2)*4;
2066
0
  u8 u = pY[1];
2067
0
  u8 v = pY[3];
2068
0
  u8 luma = (x%2) ? pY[2] : pY[0];
2069
0
  return GF_COL_ARGB(0xFF, luma, u, v);
2070
0
}
2071
u32 get_pix_yvyu(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
2072
0
{
2073
0
  u8 *pY = _this->pixels + y * _this->stride + (x/2)*4;
2074
0
  u8 u = pY[3];
2075
0
  u8 v = pY[1];
2076
0
  u8 luma = (x%2) ? pY[2] : pY[0];
2077
0
  return GF_COL_ARGB(0xFF, luma, u, v);
2078
0
}
2079
u32 get_pix_uyvy(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
2080
0
{
2081
0
  u8 *pY = _this->pixels + y * _this->stride + (x/2)*4;
2082
0
  u8 u = pY[0];
2083
0
  u8 v = pY[2];
2084
0
  u8 luma = (x%2) ? pY[3] : pY[1];
2085
0
  return GF_COL_ARGB(0xFF, luma, u, v);
2086
0
}
2087
u32 get_pix_vyuy(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
2088
0
{
2089
0
  u8 *pY = _this->pixels + y * _this->stride + (x/2)*4;
2090
0
  u8 u = pY[2];
2091
0
  u8 v = pY[0];
2092
0
  u8 luma = (x%2) ? pY[3] : pY[1];
2093
0
  return GF_COL_ARGB(0xFF, luma, u, v);
2094
0
}
2095
u32 get_pix_yuv444_10(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
2096
0
{
2097
0
  u8 vy, vu, vv;
2098
0
  u32 val;
2099
0
  u8 *p_src = _this->pixels + y * _this->stride + x*4;
2100
0
  val = p_src[3]; val<<=8;
2101
0
  val |= p_src[2]; val<<=8;
2102
0
  val |= p_src[1]; val<<=8;
2103
0
  val |= p_src[0];
2104
2105
0
  vu = (u8) ( ((val>>2) & 0x3FF) >> 2);
2106
0
  vy = (u8) ( ((val>>12) & 0x3FF) >> 2);
2107
0
  vv = (u8) ( ((val>>22)) >> 2);
2108
2109
0
  return GF_COL_ARGB(0xFF, vy, vu, vv);
2110
0
}
2111
u64 get_pix_yuv444_10_wide(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
2112
0
{
2113
0
  u16 vy, vu, vv;
2114
0
  u32 val;
2115
0
  u8 *p_src = _this->pixels + y * _this->stride + x*4;
2116
0
  val = p_src[3]; val<<=8;
2117
0
  val |= p_src[2]; val<<=8;
2118
0
  val |= p_src[1]; val<<=8;
2119
0
  val |= p_src[0];
2120
2121
0
  vu = (u16) ( ((val>>2) & 0x3FF) << 6);
2122
0
  vy = (u16) ( ((val>>12) & 0x3FF) << 6);
2123
0
  vv = (u16) ( ((val>>22)) << 6);
2124
0
  return GF_COLW_ARGB(0xFFFF, vy, vu, vv);
2125
0
}
2126
2127
u32 get_pix_v210(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
2128
0
{
2129
0
  u8 vy, vu, vv;
2130
0
  u32 val1, val2;
2131
0
  u32 x_offset = x%6;
2132
0
  x-=x_offset;
2133
0
  u8 *p_src = _this->pixels + y * _this->stride + (x * 16) / 6;
2134
0
  if (x_offset>=4) p_src += 8;
2135
0
  else if (x_offset>=2) p_src += 4;
2136
2137
0
  val1 = p_src[3]; val1<<=8;
2138
0
  val1 |= p_src[2]; val1<<=8;
2139
0
  val1 |= p_src[1]; val1<<=8;
2140
0
  val1 |= p_src[0];
2141
2142
0
  if (x_offset==0) {
2143
0
    vu = (u8) ( ((val1) & 0x3FF) >> 2);
2144
0
    vy = (u8) ( ((val1>>10) & 0x3FF) >> 2);
2145
0
    vv = (u8) ( ((val1>>20) & 0x3FF) >> 2);
2146
0
  } else {
2147
0
    val2 = p_src[7]; val2<<=8;
2148
0
    val2 |= p_src[6]; val2<<=8;
2149
0
    val2 |= p_src[5]; val2<<=8;
2150
0
    val2 |= p_src[4];
2151
2152
0
    if (x_offset==1) {
2153
0
      vu = (u8) ( ((val1) & 0x3FF) >> 2);
2154
0
      vv = (u8) ( ((val1>>20) & 0x3FF) >> 2);
2155
0
      vy = (u8) ( ((val2) & 0x3FF) >> 2);
2156
0
    } else if (x_offset==2) {
2157
0
      vu = (u8) ( ((val1>>10) & 0x3FF) >> 2);
2158
0
      vy = (u8) ( ((val1>>20) & 0x3FF) >> 2);
2159
0
      vv = (u8) ( ((val2) & 0x3FF) >> 2);
2160
0
    } else if (x_offset==3) {
2161
0
      vu = (u8) ( ((val1>>10) & 0x3FF) >> 2);
2162
0
      vv = (u8) ( ((val2) & 0x3FF) >> 2);
2163
0
      vy = (u8) ( ((val2>>10) & 0x3FF) >> 2);
2164
0
    } else if (x_offset==4) {
2165
0
      vu = (u8) ( ((val1>>20) & 0x3FF) >> 2);
2166
0
      vy = (u8) ( ((val2) & 0x3FF) >> 2);
2167
0
      vv = (u8) ( ((val2>>10) & 0x3FF) >> 2);
2168
0
    } else {
2169
0
      vu = (u8) ( ((val1>>20) & 0x3FF) >> 2);
2170
0
      vv = (u8) ( ((val2>>10) & 0x3FF) >> 2);
2171
0
      vy = (u8) ( ((val2>>20) & 0x3FF) >> 2);
2172
0
    }
2173
0
  }
2174
0
  return GF_COL_ARGB(0xFF, vy, vu, vv);
2175
0
}
2176
u64 get_pix_v210_wide(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
2177
0
{
2178
0
  u16 vy, vu, vv;
2179
0
  u32 val1, val2;
2180
0
  u32 x_offset = x%6;
2181
0
  x-=x_offset;
2182
0
  u8 *p_src = _this->pixels + y * _this->stride + (x * 16) / 6;
2183
0
  if (x_offset>=4) p_src += 8;
2184
0
  else if (x_offset>=2) p_src += 4;
2185
2186
0
  val1 = p_src[3]; val1<<=8;
2187
0
  val1 |= p_src[2]; val1<<=8;
2188
0
  val1 |= p_src[1]; val1<<=8;
2189
0
  val1 |= p_src[0];
2190
2191
0
  if (x_offset==0) {
2192
0
    vu = (u16) ( ((val1) & 0x3FF) << 6);
2193
0
    vy = (u16) ( ((val1>>10) & 0x3FF) << 6);
2194
0
    vv = (u16) ( ((val1>>20) & 0x3FF) << 6);
2195
0
  } else {
2196
0
    val2 = p_src[7]; val2<<=8;
2197
0
    val2 |= p_src[6]; val2<<=8;
2198
0
    val2 |= p_src[5]; val2<<=8;
2199
0
    val2 |= p_src[4];
2200
2201
0
    if (x_offset==1) {
2202
0
      vu = (u16) ( ((val1) & 0x3FF) << 6);
2203
0
      vv = (u16) ( ((val1>>20) & 0x3FF) << 6);
2204
0
      vy = (u16) ( ((val2) & 0x3FF) << 6);
2205
0
    } else if (x_offset==2) {
2206
0
      vu = (u16) ( ((val1>>10) & 0x3FF) << 6);
2207
0
      vy = (u16) ( ((val1>>20) & 0x3FF) << 6);
2208
0
      vv = (u16) ( ((val2) & 0x3FF) << 6);
2209
0
    } else if (x_offset==3) {
2210
0
      vu = (u16) ( ((val1>>10) & 0x3FF) << 6);
2211
0
      vv = (u16) ( ((val2) & 0x3FF) << 6);
2212
0
      vy = (u16) ( ((val2>>10) & 0x3FF) << 6);
2213
0
    } else if (x_offset==4) {
2214
0
      vu = (u16) ( ((val1>>20) & 0x3FF) << 6);
2215
0
      vy = (u16) ( ((val2) & 0x3FF) << 6);
2216
0
      vv = (u16) ( ((val2>>10) & 0x3FF) << 6);
2217
0
    } else {
2218
0
      vu = (u16) ( ((val1>>20) & 0x3FF) << 6);
2219
0
      vv = (u16) ( ((val2>>10) & 0x3FF) << 6);
2220
0
      vy = (u16) ( ((val2>>20) & 0x3FF) << 6);
2221
0
    }
2222
0
  }
2223
0
  return GF_COLW_ARGB(0xFFFF, vy, vu, vv);
2224
0
}
2225
2226
u32 get_pix_yuyv_10(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
2227
0
{
2228
0
  u8 vy, vu, vv;
2229
0
  Bool odd = x%2;
2230
0
  u8 *p_src = _this->pixels + y * _this->stride + (x/2)*8;
2231
2232
0
  vu = GET_LE_10BIT_LEFT_AS_8(p_src + _this->off_u);
2233
0
  if (odd)
2234
0
    vy = GET_LE_10BIT_LEFT_AS_8(p_src + _this->off_y+4);
2235
0
  else
2236
0
    vy = GET_LE_10BIT_LEFT_AS_8(p_src + _this->off_y);
2237
0
  vv = GET_LE_10BIT_LEFT_AS_8(p_src + _this->off_v);
2238
0
  return GF_COL_ARGB(0xFF, vy, vu, vv);
2239
0
}
2240
u64 get_pix_yuyv_10_wide(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *ctx)
2241
0
{
2242
0
  u16 vy, vu, vv;
2243
0
  u32 odd = x%2;
2244
0
  u8 *p_src = _this->pixels + y * _this->stride + (x/2)*8;
2245
2246
0
  vu = GET_LE_10BIT_LEFT_AS_16(p_src + _this->off_u);
2247
0
  if (odd)
2248
0
    vy = GET_LE_10BIT_LEFT_AS_16(p_src + _this->off_y+4);
2249
0
  else
2250
0
    vy = GET_LE_10BIT_LEFT_AS_16(p_src + _this->off_y);
2251
0
  vv = GET_LE_10BIT_LEFT_AS_16(p_src + _this->off_v);
2252
0
  return GF_COLW_ARGB(0xFFFF, vy, vu, vv);
2253
0
}
2254
u64 default_get_pixel_wide(struct __evg_texture *_this, u32 x, u32 y, EVGRasterCtx *rctx)
2255
0
{
2256
0
  return evg_col_to_wide( _this->tx_get_pixel(_this, x, y, rctx) );
2257
0
}
2258
2259
static void texture_set_callbacks(EVG_Texture *_this)
2260
0
{
2261
0
  Bool swap_uv = GF_FALSE;
2262
0
  if (_this->tx_callback)
2263
0
    return;
2264
2265
0
  _this->is_wide = 0;
2266
0
  _this->is_transparent = 0;
2267
0
  _this->tx_get_pixel = NULL;
2268
0
  _this->tx_get_pixel_wide = default_get_pixel_wide;
2269
2270
0
  switch (_this->pixel_format) {
2271
0
  case GF_PIXEL_RGBA:
2272
0
    _this->tx_get_pixel = get_pix_rgba;
2273
0
    _this->is_transparent = 1;
2274
0
    return;
2275
0
  case GF_PIXEL_ARGB:
2276
0
    _this->tx_get_pixel = get_pix_argb;
2277
0
    _this->is_transparent = 1;
2278
0
    return;
2279
0
  case GF_PIXEL_ABGR:
2280
0
    _this->tx_get_pixel = get_pix_abgr;
2281
0
    _this->is_transparent = 1;
2282
0
    return;
2283
0
  case GF_PIXEL_BGRA:
2284
0
    _this->tx_get_pixel = get_pix_bgra;
2285
0
    _this->is_transparent = 1;
2286
0
    return;
2287
0
  case GF_PIXEL_RGBX:
2288
0
    _this->tx_get_pixel = get_pix_rgbx;
2289
0
    return;
2290
0
  case GF_PIXEL_BGRX:
2291
0
    _this->tx_get_pixel = get_pix_bgrx;
2292
0
    return;
2293
0
  case GF_PIXEL_XRGB:
2294
0
    _this->tx_get_pixel = get_pix_xrgb;
2295
0
    return;
2296
0
  case GF_PIXEL_XBGR:
2297
0
    _this->tx_get_pixel = get_pix_xbgr;
2298
0
    return;
2299
0
  case GF_PIXEL_RGB:
2300
0
    _this->tx_get_pixel = get_pix_rgb_24;
2301
0
    return;
2302
0
  case GF_PIXEL_BGR:
2303
0
    _this->tx_get_pixel = get_pix_bgr_24;
2304
0
    return;
2305
0
  case GF_PIXEL_RGB_444:
2306
0
    _this->tx_get_pixel = get_pix_444;
2307
0
    return;
2308
0
  case GF_PIXEL_RGB_332:
2309
0
    _this->tx_get_pixel = get_pix_332;
2310
0
    return;
2311
0
  case GF_PIXEL_RGB_555:
2312
0
    _this->tx_get_pixel = get_pix_555;
2313
0
    return;
2314
0
  case GF_PIXEL_RGB_565:
2315
0
    _this->tx_get_pixel = get_pix_565;
2316
0
    return;
2317
0
  case GF_PIXEL_GREYSCALE:
2318
0
    if (_this->palette && _this->palette_colors) {
2319
0
      if (_this->palette_comp==4)
2320
0
        _this->tx_get_pixel = get_pix_palette_alpha;
2321
0
      else
2322
0
        _this->tx_get_pixel = get_pix_palette;
2323
0
    } else
2324
0
      _this->tx_get_pixel = get_pix_grey;
2325
0
    return;
2326
0
  case GF_PIXEL_ALPHAGREY:
2327
0
    _this->tx_get_pixel = get_pix_alphagrey;
2328
0
    _this->is_transparent = 1;
2329
0
    return;
2330
0
  case GF_PIXEL_GREYALPHA:
2331
0
    _this->tx_get_pixel = get_pix_greyalpha;
2332
0
    _this->is_transparent = 1;
2333
0
    return;
2334
0
  case GF_PIXEL_YUV:
2335
  //we swap pU and pV at setup, use the same function
2336
0
  case GF_PIXEL_YVU:
2337
0
    _this->tx_get_pixel = get_pix_yuv420p;
2338
0
    break;
2339
0
  case GF_PIXEL_YUVA:
2340
0
    _this->tx_get_pixel = get_pix_yuv420p_a;
2341
0
    _this->is_transparent = 1;
2342
0
    break;
2343
0
  case GF_PIXEL_YUV422:
2344
0
    _this->tx_get_pixel = get_pix_yuv422p;
2345
0
    break;
2346
0
  case GF_PIXEL_YUV444:
2347
0
    _this->tx_get_pixel = get_pix_yuv444p;
2348
0
    break;
2349
0
  case GF_PIXEL_YUVA444:
2350
0
    _this->tx_get_pixel = get_pix_yuv444p_a;
2351
0
    _this->is_transparent = 1;
2352
0
    break;
2353
0
  case GF_PIXEL_NV12:
2354
0
    _this->tx_get_pixel = get_pix_yuv_nv12;
2355
0
    break;
2356
0
  case GF_PIXEL_NV21:
2357
0
    _this->tx_get_pixel = get_pix_yuv_nv21;
2358
0
    break;
2359
0
  case GF_PIXEL_YUYV:
2360
0
    _this->tx_get_pixel = get_pix_yuyv;
2361
0
    return;
2362
0
  case GF_PIXEL_YVYU:
2363
0
    _this->tx_get_pixel = get_pix_yvyu;
2364
0
    return;
2365
0
  case GF_PIXEL_UYVY:
2366
0
    _this->tx_get_pixel = get_pix_uyvy;
2367
0
    return;
2368
0
  case GF_PIXEL_VYUY:
2369
0
    _this->tx_get_pixel = get_pix_vyuy;
2370
0
    return;
2371
0
  case GF_PIXEL_YUV_10:
2372
0
    _this->tx_get_pixel = get_pix_yuv420p_10;
2373
0
    _this->tx_get_pixel_wide = get_pix_yuv420p_10_wide;
2374
0
    _this->is_wide = 1;
2375
0
    break;
2376
0
  case GF_PIXEL_YUV422_10:
2377
0
    _this->tx_get_pixel = get_pix_yuv422p_10;
2378
0
    _this->tx_get_pixel_wide = get_pix_yuv422p_10_wide;
2379
0
    _this->is_wide = 1;
2380
0
    break;
2381
0
  case GF_PIXEL_YUV444_10:
2382
0
    _this->tx_get_pixel = get_pix_yuv444p_10;
2383
0
    _this->tx_get_pixel_wide = get_pix_yuv444p_10_wide;
2384
0
    _this->is_wide = 1;
2385
0
    break;
2386
0
  case GF_PIXEL_NV12_10:
2387
0
    _this->tx_get_pixel = get_pix_yuv_nv12_10;
2388
0
    _this->tx_get_pixel_wide = get_pix_yuv_nv12_10_wide;
2389
0
    _this->is_wide = 1;
2390
0
    break;
2391
0
  case GF_PIXEL_NV21_10:
2392
0
    _this->tx_get_pixel = get_pix_yuv_nv21_10;
2393
0
    _this->tx_get_pixel_wide = get_pix_yuv_nv21_10_wide;
2394
0
    _this->is_wide = 1;
2395
0
    break;
2396
0
  case GF_PIXEL_YUVA444_PACK:
2397
0
    _this->tx_get_pixel = get_pix_rgba;
2398
0
    _this->is_transparent = 1;
2399
0
    break;
2400
0
  case GF_PIXEL_UYVA444_PACK:
2401
0
    _this->tx_get_pixel = get_pix_grba;
2402
0
    _this->is_transparent = 1;
2403
0
    break;
2404
0
  case GF_PIXEL_YUV444_PACK:
2405
0
    _this->tx_get_pixel = get_pix_rgb_24;
2406
0
    break;
2407
0
  case GF_PIXEL_VYU444_PACK:
2408
0
    _this->tx_get_pixel = get_pix_gbr_24;
2409
0
    break;
2410
0
  case GF_PIXEL_YUV444_10_PACK:
2411
0
    _this->tx_get_pixel = get_pix_yuv444_10;
2412
0
    _this->tx_get_pixel_wide = get_pix_yuv444_10_wide;
2413
0
    _this->is_wide = 1;
2414
0
    break;
2415
0
  case GF_PIXEL_V210:
2416
0
    _this->tx_get_pixel = get_pix_v210;
2417
0
    _this->tx_get_pixel_wide = get_pix_v210_wide;
2418
0
    _this->is_wide = 1;
2419
0
    break;
2420
0
  case GF_PIXEL_YUYV_10:
2421
0
    _this->off_y=0;
2422
0
    _this->off_u=2;
2423
0
    _this->off_v=4;
2424
0
    _this->tx_get_pixel = get_pix_yuyv_10;
2425
0
    _this->tx_get_pixel_wide = get_pix_yuyv_10_wide;
2426
0
    _this->is_wide = 1;
2427
0
    break;
2428
0
  case GF_PIXEL_YVYU_10:
2429
0
    _this->off_y=0;
2430
0
    _this->off_u=4;
2431
0
    _this->off_v=2;
2432
0
    _this->tx_get_pixel = get_pix_yuyv_10;
2433
0
    _this->tx_get_pixel_wide = get_pix_yuyv_10_wide;
2434
0
    _this->is_wide = 1;
2435
0
    break;
2436
0
  case GF_PIXEL_UYVY_10:
2437
0
    _this->off_y=2;
2438
0
    _this->off_u=0;
2439
0
    _this->off_v=4;
2440
0
    _this->tx_get_pixel = get_pix_yuyv_10;
2441
0
    _this->tx_get_pixel_wide = get_pix_yuyv_10_wide;
2442
0
    _this->is_wide = 1;
2443
0
    break;
2444
0
  case GF_PIXEL_VYUY_10:
2445
0
    _this->off_y=2;
2446
0
    _this->off_u=4;
2447
0
    _this->off_v=2;
2448
0
    _this->tx_get_pixel = get_pix_yuyv_10;
2449
0
    _this->tx_get_pixel_wide = get_pix_yuyv_10_wide;
2450
0
    _this->is_wide = 1;
2451
0
    break;
2452
0
  default:
2453
0
    return;
2454
0
  }
2455
  //assign image planes
2456
0
  if (_this->pix_u) return;
2457
2458
0
  switch (_this->pixel_format) {
2459
0
  case GF_PIXEL_YVU:
2460
0
    swap_uv = GF_TRUE;
2461
0
  case GF_PIXEL_YUV_10:
2462
0
  case GF_PIXEL_YUV:
2463
0
    if (!_this->stride_uv) _this->stride_uv = _this->stride/2;
2464
0
    _this->pix_u = _this->pixels + _this->stride*_this->height;
2465
0
    _this->pix_v = _this->pix_u + _this->stride_uv * _this->height/2;
2466
0
    if (swap_uv) {
2467
0
      u8 *tmp = _this->pix_u;
2468
0
      _this->pix_u = _this->pix_v;
2469
0
      _this->pix_v = tmp;
2470
0
    }
2471
0
    return;
2472
0
  case GF_PIXEL_YUVA:
2473
0
    if (!_this->stride_uv) _this->stride_uv = _this->stride/2;
2474
0
    _this->pix_u = _this->pixels + _this->stride*_this->height;
2475
0
    _this->pix_v = _this->pix_u + _this->stride_uv * _this->height/2;
2476
0
    _this->pix_a = _this->pix_v + _this->stride_uv * _this->height/2;
2477
0
    return;
2478
0
  case GF_PIXEL_YUV422_10:
2479
0
  case GF_PIXEL_YUV422:
2480
0
    if (!_this->stride_uv) _this->stride_uv = _this->stride/2;
2481
0
    _this->pix_u = _this->pixels + _this->stride*_this->height;
2482
0
    _this->pix_v = _this->pix_u + _this->stride_uv * _this->height;
2483
0
    return;
2484
0
  case GF_PIXEL_YUV444_10:
2485
0
  case GF_PIXEL_YUV444:
2486
0
    if (!_this->stride_uv) _this->stride_uv = _this->stride;
2487
0
    _this->pix_u = _this->pixels + _this->stride*_this->height;
2488
0
    _this->pix_v = _this->pix_u + _this->stride_uv * _this->height;
2489
0
    return;
2490
0
  case GF_PIXEL_YUVA444:
2491
0
    if (!_this->stride_uv) _this->stride_uv = _this->stride;
2492
0
    _this->pix_u = _this->pixels + _this->stride*_this->height;
2493
0
    _this->pix_v = _this->pix_u + _this->stride_uv * _this->height;
2494
0
    _this->pix_a = _this->pix_v + _this->stride_uv * _this->height;
2495
0
    return;
2496
0
  case GF_PIXEL_NV12:
2497
0
  case GF_PIXEL_NV21:
2498
0
  case GF_PIXEL_NV12_10:
2499
0
  case GF_PIXEL_NV21_10:
2500
0
    if (!_this->stride_uv) _this->stride_uv = _this->stride;
2501
0
    _this->pix_u = _this->pixels + _this->stride*_this->height;
2502
0
    return;
2503
0
  }
2504
0
}
2505
2506
static GF_Err gf_evg_stencil_set_texture_internal(GF_EVGStencil * st, u32 width, u32 height, GF_PixelFormat pixelFormat, const char *pixels, u32 stride, const char *u_plane, const char *v_plane, u32 uv_stride, const char *alpha_plane, u32 alpha_stride)
2507
0
{
2508
0
  EVG_Texture *_this = (EVG_Texture *) st;
2509
0
  if (!_this || (_this->type != GF_STENCIL_TEXTURE) || !pixels || !width || !height || _this->owns_texture)
2510
0
    return GF_BAD_PARAM;
2511
2512
0
  _this->pixels = NULL;
2513
0
  _this->is_yuv = GF_FALSE;
2514
0
  _this->palette = NULL;
2515
0
  _this->palette_colors = 0;
2516
2517
0
  switch (pixelFormat) {
2518
0
  case GF_PIXEL_ARGB:
2519
0
  case GF_PIXEL_RGBA:
2520
0
  case GF_PIXEL_ABGR:
2521
0
  case GF_PIXEL_BGRA:
2522
0
  case GF_PIXEL_RGBX:
2523
0
  case GF_PIXEL_XRGB:
2524
0
  case GF_PIXEL_XBGR:
2525
0
  case GF_PIXEL_BGRX:
2526
0
    _this->Bpp = 4;
2527
0
    break;
2528
0
  case GF_PIXEL_RGB:
2529
0
  case GF_PIXEL_BGR:
2530
0
    _this->Bpp = 3;
2531
0
    break;
2532
0
  case GF_PIXEL_RGB_332:
2533
0
    _this->Bpp = 1;
2534
0
    break;
2535
0
  case GF_PIXEL_RGB_555:
2536
0
  case GF_PIXEL_RGB_565:
2537
0
  case GF_PIXEL_RGB_444:
2538
0
  case GF_PIXEL_ALPHAGREY:
2539
0
  case GF_PIXEL_GREYALPHA:
2540
0
    _this->Bpp = 2;
2541
0
    break;
2542
0
  case GF_PIXEL_GREYSCALE:
2543
0
    _this->Bpp = 1;
2544
0
    break;
2545
0
  case GF_PIXEL_YUV:
2546
0
  case GF_PIXEL_YVU:
2547
0
  case GF_PIXEL_NV12:
2548
0
  case GF_PIXEL_NV21:
2549
0
  case GF_PIXEL_YUV422:
2550
0
  case GF_PIXEL_YUV444:
2551
0
  case GF_PIXEL_YUVA:
2552
0
  case GF_PIXEL_YUVA444:
2553
0
    _this->is_yuv = GF_TRUE;
2554
0
    _this->Bpp = 1;
2555
0
    break;
2556
0
  case GF_PIXEL_YUV_10:
2557
0
  case GF_PIXEL_YUV422_10:
2558
0
  case GF_PIXEL_YUV444_10:
2559
0
  case GF_PIXEL_NV12_10:
2560
0
  case GF_PIXEL_NV21_10:
2561
0
    _this->is_yuv = GF_TRUE;
2562
0
    _this->Bpp = 2;
2563
0
    break;
2564
0
  case GF_PIXEL_YUYV:
2565
0
  case GF_PIXEL_YVYU:
2566
0
  case GF_PIXEL_UYVY:
2567
0
  case GF_PIXEL_VYUY:
2568
0
    _this->is_yuv = GF_TRUE;
2569
0
    _this->Bpp = 1;
2570
0
    if (!stride)
2571
0
      stride = 4 * width;
2572
0
    break;
2573
2574
0
  case GF_PIXEL_YUYV_10:
2575
0
  case GF_PIXEL_YVYU_10:
2576
0
  case GF_PIXEL_UYVY_10:
2577
0
  case GF_PIXEL_VYUY_10:
2578
0
    _this->is_yuv = GF_TRUE;
2579
0
    _this->Bpp = 2;
2580
0
    if (!stride)
2581
0
      stride = 4 * width;
2582
0
    break;
2583
0
  case GF_PIXEL_YUVA444_PACK:
2584
0
  case GF_PIXEL_UYVA444_PACK:
2585
0
    _this->Bpp = 4;
2586
0
    _this->is_yuv = GF_TRUE;
2587
0
    break;
2588
0
  case GF_PIXEL_YUV444_10_PACK:
2589
0
    _this->Bpp = 4;
2590
0
    _this->is_yuv = GF_TRUE;
2591
0
    break;
2592
0
  case GF_PIXEL_YUV444_PACK:
2593
0
  case GF_PIXEL_VYU444_PACK:
2594
0
    _this->Bpp = 3;
2595
0
    _this->is_yuv = GF_TRUE;
2596
0
    break;
2597
0
  case GF_PIXEL_V210:
2598
0
    _this->Bpp = 2;
2599
0
    _this->is_yuv = GF_TRUE;
2600
0
    if (!stride) {
2601
0
      stride = width;
2602
0
      while (stride % 48) stride++;
2603
0
      stride = stride * 16 / 6; //4 x 32 bits to represent 6 pixels
2604
0
    }
2605
0
    break;
2606
0
  default:
2607
0
    return GF_NOT_SUPPORTED;
2608
0
  }
2609
0
  if (!stride)
2610
0
    stride = _this->Bpp * width;
2611
2612
0
  _this->pixel_format = pixelFormat;
2613
0
  _this->width = width;
2614
0
  _this->height = height;
2615
0
  _this->stride = stride;
2616
0
  _this->stride_uv = uv_stride;
2617
0
  _this->stride_alpha = alpha_stride ? alpha_stride : stride;
2618
0
  _this->pixels = (char *) pixels;
2619
0
  _this->pix_u = (char *) u_plane;
2620
0
  _this->pix_v = (char *) v_plane;
2621
0
  texture_set_callbacks(_this);
2622
0
  return GF_OK;
2623
0
}
2624
2625
GF_EXPORT
2626
GF_Err gf_evg_stencil_set_texture_planes(GF_EVGStencil *stencil, u32 width, u32 height, GF_PixelFormat pixelFormat, const u8 *y_or_rgb, u32 stride, const u8 *u_plane, const u8 *v_plane, u32 uv_stride, const u8 *alpha_plane, u32 stride_alpha)
2627
0
{
2628
0
  return gf_evg_stencil_set_texture_internal(stencil, width, height, pixelFormat, y_or_rgb, stride, u_plane, v_plane, uv_stride, alpha_plane, stride_alpha);
2629
0
}
2630
GF_EXPORT
2631
GF_Err gf_evg_stencil_set_texture(GF_EVGStencil *stencil, u8 *pixels, u32 width, u32 height, u32 stride, GF_PixelFormat pixelFormat)
2632
0
{
2633
0
  return gf_evg_stencil_set_texture_internal(stencil, width, height, pixelFormat, pixels, stride, NULL, NULL, 0, NULL, 0);
2634
0
}
2635
2636
GF_EXPORT
2637
Bool gf_evg_texture_format_ok(GF_PixelFormat pixelFormat)
2638
0
{
2639
0
  EVG_Texture _tx;
2640
0
  memset(&_tx, 0, sizeof(EVG_Texture));
2641
0
  _tx.type = GF_STENCIL_TEXTURE;
2642
0
  GF_Err e = gf_evg_stencil_set_texture_internal((GF_EVGStencil *) &_tx, 2, 2, pixelFormat, (const u8 *) &_tx, 0, NULL, NULL, 0, NULL, 0);
2643
0
  if (e==GF_OK) return GF_TRUE;
2644
0
  return GF_FALSE;
2645
0
}
2646
2647
2648
GF_EXPORT
2649
GF_Err gf_evg_stencil_set_palette(GF_EVGStencil *stencil, const u8 *palette, u32 pix_fmt, u32 nb_cols)
2650
0
{
2651
0
  EVG_Texture *_this = (EVG_Texture *) stencil;
2652
0
  if (!_this || (_this->type != GF_STENCIL_TEXTURE) || !palette || !nb_cols)
2653
0
    return GF_BAD_PARAM;
2654
0
  if (_this->pixel_format != GF_PIXEL_GREYSCALE) return GF_BAD_PARAM;
2655
0
  _this->palette = palette;
2656
0
  _this->palette_colors = nb_cols;
2657
0
  _this->palette_pfmt = pix_fmt;
2658
0
  switch (pix_fmt) {
2659
0
  case GF_PIXEL_RGB:
2660
0
    _this->palette_comp = 3;
2661
0
    _this->pidx_r=0;
2662
0
    _this->pidx_g=1;
2663
0
    _this->pidx_b=2;
2664
0
    break;
2665
0
  case GF_PIXEL_BGR:
2666
0
    _this->palette_comp = 3;
2667
0
    _this->pidx_r=2;
2668
0
    _this->pidx_g=1;
2669
0
    _this->pidx_b=0;
2670
0
    break;
2671
0
  case GF_PIXEL_RGBA:
2672
0
    _this->palette_comp = 4;
2673
0
    _this->pidx_r=0;
2674
0
    _this->pidx_g=1;
2675
0
    _this->pidx_b=2;
2676
0
    _this->pidx_a=3;
2677
0
    break;
2678
0
  case GF_PIXEL_ARGB:
2679
0
    _this->palette_comp = 4;
2680
0
    _this->pidx_r=1;
2681
0
    _this->pidx_g=2;
2682
0
    _this->pidx_b=3;
2683
0
    _this->pidx_a=0;
2684
0
    break;
2685
0
  case GF_PIXEL_ABGR:
2686
0
    _this->palette_comp = 4;
2687
0
    _this->pidx_r=3;
2688
0
    _this->pidx_g=2;
2689
0
    _this->pidx_b=1;
2690
0
    _this->pidx_a=0;
2691
0
    break;
2692
0
  case GF_PIXEL_BGRA:
2693
0
    _this->palette_comp = 4;
2694
0
    _this->pidx_r=2;
2695
0
    _this->pidx_g=1;
2696
0
    _this->pidx_b=0;
2697
0
    _this->pidx_a=3;
2698
0
    break;
2699
0
  default:
2700
0
    _this->palette = NULL;
2701
0
    _this->palette_colors = 0;
2702
0
    return GF_NOT_SUPPORTED;
2703
0
  }
2704
0
  return GF_OK;
2705
0
}
2706
GF_EXPORT
2707
GF_Err gf_evg_stencil_get_texture_planes(GF_EVGStencil *stencil, u8 **pY_or_RGB, u8 **pU, u8 **pV, u8 **pA, u32 *stride, u32 *stride_uv)
2708
0
{
2709
0
  EVG_Texture *_this = (EVG_Texture *) stencil;
2710
0
  if (!_this || (_this->type != GF_STENCIL_TEXTURE) )
2711
0
    return GF_BAD_PARAM;
2712
2713
2714
0
  if (pY_or_RGB) *pY_or_RGB = _this->pixels;
2715
0
  if (pU) *pU = _this->pix_u;
2716
0
  if (pV) *pV = _this->pix_v;
2717
0
  if (pA) *pA = _this->pix_a;
2718
0
  if (stride) *stride = _this->stride;
2719
0
  if (stride_uv) *stride_uv = _this->stride_uv;
2720
2721
0
  return GF_OK;
2722
0
}
2723
2724
2725
GF_EXPORT
2726
GF_Err gf_evg_stencil_set_texture_parametric(GF_EVGStencil *stencil, u32 width, u32 height, GF_PixelFormat pixelFormat, gf_evg_texture_callback callback, void *cbk_data, Bool use_screen_coords)
2727
0
{
2728
0
  EVG_Texture *_this = (EVG_Texture *) stencil;
2729
0
  u8 data=0;
2730
0
  GF_Err e;
2731
0
  if (!callback) return GF_BAD_PARAM;
2732
0
  e = gf_evg_stencil_set_texture_internal(stencil, width, height, pixelFormat, &data, width, NULL, NULL, 0, NULL, 0);
2733
0
  if (e) return e;
2734
0
  _this->pixels = NULL;
2735
0
  _this->tx_get_pixel = evg_paramtx_get_pixel;
2736
0
  _this->tx_get_pixel_wide = evg_paramtx_get_pixel_wide;
2737
0
  _this->is_wide = 1;
2738
2739
0
  _this->tx_callback = callback;
2740
0
  _this->tx_callback_udta = cbk_data;
2741
0
  _this->tx_callback_screen_coords = use_screen_coords;
2742
0
  return GF_OK;
2743
0
}
2744
2745
void evg_texture_init(GF_EVGStencil *p, GF_EVGSurface *surf)
2746
0
{
2747
0
  GF_Point2D p0, p1;
2748
0
  EVG_Texture *_this = (EVG_Texture *) p;
2749
2750
0
  p0.x = p0.y = p1.y = 0;
2751
0
  p1.x = FIX_ONE;
2752
0
  gf_mx2d_apply_point(&_this->smat, &p0);
2753
0
  gf_mx2d_apply_point(&_this->smat, &p1);
2754
0
  _this->inc_x = p1.x - p0.x;
2755
0
  _this->inc_y = p1.y - p0.y;
2756
2757
0
  if (surf->is_3d_matrix) {
2758
0
    if (surf->not_8bits) {
2759
0
      _this->fill_run = tex_fill_run_3d_wide;
2760
0
    } else {
2761
0
      _this->fill_run = tex_fill_run_3d;
2762
0
    }
2763
0
  } else if (_this->tx_callback && _this->tx_callback_screen_coords) {
2764
0
    if (surf->not_8bits) {
2765
0
      _this->fill_run = tex_fill_run_callback_wide;
2766
0
    } else {
2767
0
      _this->fill_run = tex_fill_run_callback;
2768
0
    }
2769
0
  }
2770
0
  else if ((_this->filter != GF_TEXTURE_FILTER_HIGH_QUALITY) && (_this->alpha == 255)
2771
0
    && !_this->smat.m[1] && !_this->smat.m[3]
2772
0
    && _this->cmat.identity
2773
0
  ) {
2774
0
    if (surf->not_8bits) {
2775
0
      _this->fill_run = tex_fill_run_straight_wide;
2776
0
    } else {
2777
0
      _this->fill_run = tex_fill_run_straight;
2778
0
    }
2779
0
  } else {
2780
0
    if (!_this->cmat.identity && _this->is_yuv && surf->yuv_type) {
2781
//      evg_make_ayuv_color_mx(&_this->cmat, &_this->yuv_cmat);
2782
0
      _this->yuv_cmat = _this->cmat;
2783
0
    }
2784
0
    if (surf->not_8bits) {
2785
0
      _this->fill_run = tex_fill_run_wide;
2786
0
    } else {
2787
0
      _this->fill_run = tex_fill_run;
2788
0
    }
2789
0
  }
2790
2791
0
  if (!_this->pad_rbg) {
2792
0
    _this->fill_pad_color = 0;
2793
0
  } else if (_this->is_transparent) {
2794
0
    _this->fill_pad_color = GF_COL_ARGB(0, 0xFF, 0xFF, 0xFF);
2795
0
  } else if (_this->is_yuv) {
2796
0
    _this->fill_pad_color = gf_evg_argb_to_ayuv(surf, _this->pad_rbg);
2797
0
  } else {
2798
0
    _this->fill_pad_color = _this->pad_rbg;
2799
0
  }
2800
0
  _this->fill_pad_color_wide = evg_col_to_wide(_this->fill_pad_color);
2801
2802
0
  texture_set_callbacks(_this);
2803
0
}
2804
2805
GF_EXPORT
2806
GF_Err gf_evg_stencil_set_pad_color(GF_EVGStencil * st, GF_Color pad_color)
2807
0
{
2808
0
  EVG_Texture *_this = (EVG_Texture *) st;
2809
0
  if (!_this || (_this->type != GF_STENCIL_TEXTURE)) return GF_BAD_PARAM;
2810
0
  _this->pad_rbg = pad_color;
2811
0
  return GF_OK;
2812
0
}
2813
2814
GF_EXPORT
2815
u32 gf_evg_stencil_get_pad_color(GF_EVGStencil * st)
2816
0
{
2817
0
  EVG_Texture *_this = (EVG_Texture *) st;
2818
0
  if (!_this || (_this->type != GF_STENCIL_TEXTURE)) return 0;
2819
0
  return _this->pad_rbg;
2820
0
}
2821
2822
GF_EXPORT
2823
GF_Err gf_evg_stencil_set_mapping(GF_EVGStencil * st, GF_TextureMapFlags mode)
2824
0
{
2825
0
  EVG_Texture *_this = (EVG_Texture *) st;
2826
0
  if (!_this || (_this->type != GF_STENCIL_TEXTURE)) return GF_BAD_PARAM;
2827
0
  _this->mod = mode;
2828
0
  return GF_OK;
2829
0
}
2830
2831
GF_EXPORT
2832
GF_Err gf_evg_stencil_set_filter(GF_EVGStencil * st, GF_TextureFilter filter_mode)
2833
0
{
2834
0
  EVG_Texture *_this = (EVG_Texture *) st;
2835
0
  if (!_this || (_this->type != GF_STENCIL_TEXTURE)) return GF_BAD_PARAM;
2836
0
  _this->filter = filter_mode;
2837
0
  return GF_OK;
2838
0
}
2839
2840
GF_EXPORT
2841
GF_Err gf_evg_stencil_set_color_matrix(GF_EVGStencil * st, GF_ColorMatrix *cmat)
2842
0
{
2843
0
  Bool is_grad;
2844
0
  EVG_BaseGradient *_this = (EVG_BaseGradient *)st;
2845
0
  if (!_this) return GF_BAD_PARAM;
2846
0
  is_grad = ((_this->type==GF_STENCIL_LINEAR_GRADIENT) || (_this->type==GF_STENCIL_RADIAL_GRADIENT)) ? GF_TRUE : GF_FALSE;
2847
2848
2849
0
  if (!cmat) {
2850
0
    if (is_grad && !_this->cmat.identity)
2851
0
      _this->updated = 1;
2852
0
    gf_cmx_init(&_this->cmat);
2853
0
  } else {
2854
0
    if (is_grad && memcmp(&_this->cmat.m, &cmat->m, sizeof(Fixed)*20))
2855
0
      _this->updated = 1;
2856
0
    gf_cmx_copy(&_this->cmat, cmat);
2857
0
  }
2858
0
  return GF_OK;
2859
0
}
2860
2861
GF_EXPORT
2862
GF_Err gf_evg_stencil_get_color_matrix(GF_EVGStencil * st, GF_ColorMatrix *cmat)
2863
0
{
2864
0
  EVG_BaseGradient *_this = (EVG_BaseGradient *)st;
2865
0
  if (!_this || !cmat) return GF_BAD_PARAM;
2866
0
  gf_cmx_copy(cmat, &_this->cmat);
2867
0
  return GF_OK;
2868
0
}
2869
static u32 gf_evg_stencil_get_pixel_intern(EVG_Texture *_this, s32 x, s32 y, Bool want_yuv)
2870
0
{
2871
0
  u32 col;
2872
0
  if (!_this || (_this->type != GF_STENCIL_TEXTURE) || !_this->tx_get_pixel) return 0;
2873
0
  if (x<0) x=0;
2874
0
  else if ((u32) x>=_this->width) x = _this->width-1;
2875
2876
0
  if (y<0) y=0;
2877
0
  else if ((u32) y>=_this->height) y = _this->height-1;
2878
2879
0
  col = _this->tx_get_pixel(_this, x, y, NULL);
2880
0
  if (_this->is_yuv) {
2881
0
    if (!want_yuv) return gf_evg_ayuv_to_argb(NULL, col);
2882
0
  } else {
2883
0
    if (want_yuv) return gf_evg_argb_to_ayuv(NULL, col);
2884
0
  }
2885
0
  return col;
2886
0
}
2887
2888
GF_EXPORT
2889
u32 gf_evg_stencil_get_pixel(GF_EVGStencil *st, s32 x, s32 y)
2890
0
{
2891
0
  return gf_evg_stencil_get_pixel_intern((EVG_Texture *)st, x, y, GF_FALSE);
2892
0
}
2893
2894
GF_EXPORT
2895
u32 gf_evg_stencil_get_pixel_yuv(GF_EVGStencil *st, s32 x, s32 y)
2896
0
{
2897
0
  return gf_evg_stencil_get_pixel_intern((EVG_Texture *)st, x, y, GF_TRUE);
2898
0
}
2899
2900
u32 gf_evg_stencil_get_pixel_fast(GF_EVGStencil *st, s32 x, s32 y)
2901
0
{
2902
0
  return ((EVG_Texture *)st)->tx_get_pixel((EVG_Texture *)st, x, y, NULL);
2903
0
}
2904
u64 gf_evg_stencil_get_pixel_wide_fast(GF_EVGStencil *st, s32 x, s32 y)
2905
0
{
2906
0
  return ((EVG_Texture *)st)->tx_get_pixel_wide((EVG_Texture *)st, x, y, NULL);
2907
0
}
2908
2909
2910
2911
static u64 gf_evg_stencil_get_pixel_wide_intern(EVG_Texture *_this, s32 x, s32 y, Bool want_yuv)
2912
0
{
2913
0
  u64 col;
2914
0
  if (!_this || (_this->type != GF_STENCIL_TEXTURE) || !_this->tx_get_pixel_wide) return 0;
2915
0
  if (x<0) x=0;
2916
0
  else if ((u32) x>=_this->width) x = _this->width-1;
2917
2918
0
  if (y<0) y=0;
2919
0
  else if ((u32) y>=_this->height) y = _this->height-1;
2920
2921
0
  col = _this->tx_get_pixel_wide(_this, x, y, NULL);
2922
0
  if (_this->is_yuv) {
2923
0
    if (!want_yuv) return gf_evg_ayuv_to_argb_wide(NULL, col);
2924
0
  } else {
2925
0
    if (want_yuv) return gf_evg_argb_to_ayuv_wide(NULL, col);
2926
0
  }
2927
0
  return col;
2928
0
}
2929
2930
GF_EXPORT
2931
u64 gf_evg_stencil_get_pixel_wide(GF_EVGStencil *st, s32 x, s32 y)
2932
0
{
2933
0
  return gf_evg_stencil_get_pixel_wide_intern((EVG_Texture *)st, x, y, GF_FALSE);
2934
0
}
2935
2936
GF_EXPORT
2937
u64 gf_evg_stencil_get_pixel_yuv_wide(GF_EVGStencil *st, s32 x, s32 y)
2938
0
{
2939
0
  return gf_evg_stencil_get_pixel_intern((EVG_Texture *)st, x, y, GF_TRUE);
2940
0
}
2941
static GF_Vec4 gf_evg_stencil_get_pixel_f_intern(EVG_Texture *_this, Float x, Float y, Bool want_yuv)
2942
0
{
2943
0
  u32 col;
2944
0
  GF_Vec4 res;
2945
0
  if (!_this || (_this->type != GF_STENCIL_TEXTURE) || (!_this->tx_get_pixel && !_this->tx_get_pixel_wide) ) {
2946
0
    memset(&res, 0, sizeof(GF_Vec4));
2947
0
    return res;
2948
0
  }
2949
2950
0
  if (_this->mod & GF_TEXTURE_FLIP_X) x = -x;
2951
0
  if (_this->mod & GF_TEXTURE_FLIP_Y) y = -y;
2952
2953
0
  x*=_this->width;
2954
0
  y*=_this->height;
2955
0
  if (_this->mod & GF_TEXTURE_REPEAT_S) {
2956
0
    while (x<0) x += _this->width;
2957
0
    while (x>=_this->width) x -= _this->width;
2958
0
  } else {
2959
0
    if (x<0) x=0;
2960
0
    else if (x>=_this->width) x = (Float)_this->width-1;
2961
0
  }
2962
2963
0
  if (_this->mod & GF_TEXTURE_REPEAT_T) {
2964
0
    while (y<0) y += _this->height;
2965
0
    while (y>=_this->height) y -= _this->height;
2966
0
  } else {
2967
0
    if (y<0) y=0;
2968
0
    else if (y>=_this->height) y = (Float)_this->height-1;
2969
0
  }
2970
2971
  //10-bit or more texture, use wide and convert to float
2972
0
  if (_this->is_wide) {
2973
0
    u64 colw;
2974
0
    if (_this->filter==GF_TEXTURE_FILTER_HIGH_SPEED) {
2975
0
      colw = _this->tx_get_pixel_wide(_this, (s32) x, (s32) y, NULL);
2976
0
    } else {
2977
0
      u32 _x = (u32) floor(x);
2978
0
      u32 _y = (u32) floor(y);
2979
0
      if (_this->filter==GF_TEXTURE_FILTER_MID) {
2980
0
        if ((x - _x > 0.5) && _x+1<_this->width) _x++;
2981
0
        if ((y - _y > 0.5) && _y+1<_this->height) _y++;
2982
0
        colw = _this->tx_get_pixel_wide(_this, _x, _y, NULL);
2983
0
      } else {
2984
0
        u64 col01, col11, col10;
2985
0
        s32 _x1 = _x+1;
2986
0
        s32 _y1 = _y+1;
2987
0
        u8 diff_x = (u8) (255 * (x - _x));
2988
0
        u8 diff_y = (u8) (255 * (y - _y));
2989
2990
0
        if ((u32)_x1>=_this->width) _x1 = _this->width-1;
2991
0
        if ((u32)_y1>=_this->height) _y1 = _this->height-1;
2992
0
        colw = _this->tx_get_pixel_wide(_this, _x, _y, NULL);
2993
0
        col10 = _this->tx_get_pixel_wide(_this, _x1, _y, NULL);
2994
0
        col01 = _this->tx_get_pixel_wide(_this, _x, _y1, NULL);
2995
0
        col11 = _this->tx_get_pixel_wide(_this, _x1, _y1, NULL);
2996
0
        colw = EVG_LERP_WIDE(colw, col10, diff_x);
2997
0
        col11 = EVG_LERP_WIDE(col01, col11, diff_x);
2998
0
        colw = EVG_LERP_WIDE(colw, col11, diff_y);
2999
0
      }
3000
0
    }
3001
0
    if (_this->is_yuv) {
3002
0
      if (!want_yuv) colw = gf_evg_ayuv_to_argb_wide(NULL, colw);
3003
0
    } else {
3004
0
      if (want_yuv) colw = gf_evg_argb_to_ayuv_wide(NULL, colw);
3005
0
    }
3006
3007
0
    res.x = GF_COLW_R(colw); res.x /= 0xFFFF;
3008
0
    res.y = GF_COLW_G(colw); res.y /= 0xFFFF;
3009
0
    res.z = GF_COLW_B(colw); res.z /= 0xFFFF;
3010
0
    res.q = GF_COLW_A(colw); res.q /= 0xFFFF;
3011
0
    return res;
3012
0
  }
3013
3014
  //8-bit texture, use regular and convert to float
3015
0
  if (_this->filter==GF_TEXTURE_FILTER_HIGH_SPEED) {
3016
0
    col = _this->tx_get_pixel(_this, (s32) x, (s32) y, NULL);
3017
0
  } else {
3018
0
    u32 _x = (u32) floor(x);
3019
0
    u32 _y = (u32) floor(y);
3020
0
    if (_this->filter==GF_TEXTURE_FILTER_MID) {
3021
0
      if ((x - _x > 0.5) && _x+1<_this->width) _x++;
3022
0
      if ((y - _y > 0.5) && _y+1<_this->height) _y++;
3023
0
      col = _this->tx_get_pixel(_this, _x, _y, NULL);
3024
0
    } else {
3025
0
      u32 col01, col11, col10;
3026
0
      s32 _x1 = _x+1;
3027
0
      s32 _y1 = _y+1;
3028
0
      u8 diff_x = (u8) (255 * (x - _x));
3029
0
      u8 diff_y = (u8) (255 * (y - _y));
3030
3031
0
      if ((u32)_x1>=_this->width) _x1 = _this->width-1;
3032
0
      if ((u32)_y1>=_this->height) _y1 = _this->height-1;
3033
0
      col = _this->tx_get_pixel(_this, _x, _y, NULL);
3034
0
      col10 = _this->tx_get_pixel(_this, _x1, _y, NULL);
3035
0
      col01 = _this->tx_get_pixel(_this, _x, _y1, NULL);
3036
0
      col11 = _this->tx_get_pixel(_this, _x1, _y1, NULL);
3037
0
      col = EVG_LERP(col, col10, diff_x);
3038
0
      col11 = EVG_LERP(col01, col11, diff_x);
3039
0
      col = EVG_LERP(col, col11, diff_y);
3040
0
    }
3041
0
  }
3042
0
  if (_this->is_yuv) {
3043
0
    if (!want_yuv) col = gf_evg_ayuv_to_argb(NULL, col);
3044
0
  } else {
3045
0
    if (want_yuv) col = gf_evg_argb_to_ayuv(NULL, col);
3046
0
  }
3047
0
  res.x = (Float) ( GF_COL_R(col) / 255.0 );
3048
0
  res.y = (Float)( GF_COL_G(col) / 255.0 );
3049
0
  res.z = (Float)( GF_COL_B(col) / 255.0 );
3050
0
  res.q = (Float)( GF_COL_A(col) / 255.0 );
3051
0
  return res;
3052
0
}
3053
3054
GF_EXPORT
3055
GF_Vec4 gf_evg_stencil_get_pixel_f(GF_EVGStencil *st, Float x, Float y)
3056
0
{
3057
0
  return gf_evg_stencil_get_pixel_f_intern((EVG_Texture *)st, x, y, GF_FALSE);
3058
0
}
3059
3060
GF_EXPORT
3061
GF_Vec4 gf_evg_stencil_get_pixel_yuv_f(GF_EVGStencil *st, Float x, Float y)
3062
0
{
3063
0
  return gf_evg_stencil_get_pixel_f_intern((EVG_Texture *)st, x, y, GF_TRUE);
3064
0
}
3065
3066
GF_EXPORT
3067
GF_Err gf_evg_stencil_set_alpha(GF_EVGStencil * st, u8 alpha)
3068
0
{
3069
0
  EVG_Texture *_this = (EVG_Texture *)st;
3070
0
  if (!_this) return GF_BAD_PARAM;
3071
0
  if (_this->type==GF_STENCIL_SOLID) {
3072
0
    ((EVG_Brush *)st)->alpha = alpha;
3073
0
    return GF_OK;
3074
0
  }
3075
0
  if (_this->type==GF_STENCIL_TEXTURE)
3076
0
    _this->alpha = alpha;
3077
0
  else {
3078
0
    if ( ((EVG_BaseGradient*)st)->alpha != alpha) {
3079
0
      ((EVG_BaseGradient*)st)->updated = 1;
3080
0
    }
3081
0
    ((EVG_BaseGradient*)st)->alpha = alpha;
3082
0
  }
3083
0
  return GF_OK;
3084
0
}
3085
3086
GF_EXPORT
3087
u8 gf_evg_stencil_get_alpha(GF_EVGStencil * st)
3088
0
{
3089
0
  EVG_Texture *_this = (EVG_Texture *)st;
3090
0
  if (!_this) return 0;
3091
0
  if (_this->type==GF_STENCIL_SOLID) {
3092
0
    return ((EVG_Brush *)st)->alpha;
3093
0
  }
3094
0
  if (_this->type==GF_STENCIL_TEXTURE)
3095
0
    return _this->alpha;
3096
3097
0
  return ((EVG_BaseGradient*)st)->alpha;
3098
0
}
3099
3100
void *evg_fill_run(GF_EVGStencil *p, EVGRasterCtx *rctx, EVG_Span *span, s32 y)
3101
0
{
3102
3103
0
  if (rctx->surf->direct_yuv_3d) {
3104
0
    u32 *src = rctx->stencil_pix_run;
3105
0
    return src + span->x;
3106
0
  }
3107
0
  if (rctx->surf->is_shader) {
3108
0
    rctx->frag_param.coverage = span->coverage;
3109
0
    rctx->frag_param.odd_flag = span->odd_flag;
3110
0
    rctx->frag_param.screen_x = (Float) span->x;
3111
0
    rctx->frag_param.screen_y = (Float) y;
3112
0
  }
3113
0
  if (rctx->surf->odd_fill) {
3114
0
    if (!span->odd_flag && rctx->surf->sten2) {
3115
0
      rctx->surf->sten2->fill_run(rctx->surf->sten2, rctx, span->x, y, span->len);
3116
0
    } else {
3117
0
      p->fill_run(p, rctx, span->x, y, span->len);
3118
0
    }
3119
0
    return rctx->stencil_pix_run;
3120
0
  }
3121
3122
0
  if (p)
3123
0
    p->fill_run(p, rctx, span->x, y, span->len);
3124
0
  if (rctx->surf->update_run) {
3125
0
    void *bck = rctx->stencil_pix_run;
3126
0
    if (rctx->surf->sten2) {
3127
0
      rctx->stencil_pix_run = rctx->stencil_pix_run2;
3128
0
      rctx->surf->sten2->fill_run(rctx->surf->sten2, rctx, span->x, y, span->len);
3129
0
    }
3130
0
    if (rctx->surf->sten3) {
3131
0
      rctx->stencil_pix_run = rctx->stencil_pix_run3;
3132
0
      rctx->surf->sten3->fill_run(rctx->surf->sten3, rctx, span->x, y, span->len);
3133
0
    }
3134
0
    rctx->stencil_pix_run = bck;
3135
0
    rctx->surf->update_run(rctx, span->len);
3136
0
    return rctx->stencil_pix_run;
3137
0
  }
3138
3139
0
  if (rctx->surf->get_alpha) {
3140
0
    u32 i;
3141
0
    GF_EVGSurface *surf = rctx->surf;
3142
0
    EVG_Texture *_p = (EVG_Texture *)p;
3143
0
    if (_p->Bpp>8) {
3144
0
      u64 *coll = (u64 *)rctx->stencil_pix_run;
3145
0
      for (i=0; i<span->len; i++) {
3146
0
        u64 a = (*coll>>48)&0xFFFF;
3147
0
        a = 0xFF * surf->get_alpha(surf->get_alpha_udta, (u8) (a/0xFF), span->x+i, y);
3148
0
        *coll = (a<<48) | ((*coll) & 0x0000FFFFFFFFFFFFUL);
3149
0
        coll ++;
3150
0
      }
3151
0
    } else {
3152
0
      u32 *col = (u32 *)rctx->stencil_pix_run;
3153
0
      for (i=0; i<span->len; i++) {
3154
0
        u32 a = GF_COL_A(*col);
3155
0
        a = surf->get_alpha(surf->get_alpha_udta, a, span->len+i, y);
3156
0
        *col = (a<<24) | ((*col) & 0x00FFFFFF);
3157
0
        col ++;
3158
0
      }
3159
0
    }
3160
0
  }
3161
0
  return rctx->stencil_pix_run;
3162
0
}
3163
void *evg_fill_run_mask(GF_EVGStencil *p, EVGRasterCtx *rctx, EVG_Span *span, s32 y)
3164
0
{
3165
0
  void *res = evg_fill_run(p, rctx, span, y);
3166
0
  u8 *mask = rctx->surf->internal_mask + y*rctx->surf->width + span->x;
3167
0
  u32 i;
3168
0
  if (rctx->surf->not_8bits) {
3169
0
    u64 *wcols = res;
3170
0
    for (i=0; i<span->len; i++) {
3171
0
      *wcols = (*wcols & 0x0000FFFFFFFFFFFFUL) | (((u64) *mask)*256)<<48;
3172
0
      wcols++;
3173
0
      mask++;
3174
0
    }
3175
0
  } else {
3176
0
    u32 * cols = res;
3177
0
    for (i=0; i<span->len; i++) {
3178
0
      *cols = (*cols & 0x00FFFFFF) | ((u32)*mask)<<24;
3179
0
      cols++;
3180
0
      mask++;
3181
0
    }
3182
0
  }
3183
0
  return res;
3184
0
}
3185
void *evg_fill_run_mask_inv(GF_EVGStencil *p, EVGRasterCtx *rctx, EVG_Span *span, s32 y)
3186
0
{
3187
0
  void *res = evg_fill_run(p, rctx, span, y);
3188
0
  u8 *mask = rctx->surf->internal_mask + y*rctx->surf->width + span->x;
3189
0
  u32 i;
3190
0
  if (rctx->surf->not_8bits) {
3191
0
    u64 *wcols = res;
3192
0
    for (i=0; i<span->len; i++) {
3193
0
      *wcols = (*wcols & 0x0000FFFFFFFFFFFFUL) | (((u64) (0xFF- *mask))*256)<<48;
3194
0
      wcols++;
3195
0
      mask++;
3196
0
    }
3197
0
  } else {
3198
0
    u32 * cols = res;
3199
0
    for (i=0; i<span->len; i++) {
3200
0
      *cols = (*cols & 0x00FFFFFF) | ((u32) (0xFF- *mask) )<<24;
3201
0
      cols++;
3202
0
      mask++;
3203
0
    }
3204
0
  }
3205
0
  return res;
3206
0
}
3207
3208
void evg_fill_span_mask(int y, int count, EVG_Span *spans, GF_EVGSurface *surf, EVGRasterCtx *rctx)
3209
0
{
3210
0
  EVG_Span aspan, *ospan;
3211
0
  int i;
3212
0
  aspan.idx1 = aspan.idx2 = 0;
3213
3214
  //disable yuv flush for 420 and 422
3215
0
  rctx->no_yuv_flush = 1;
3216
0
  for (i=0; i<count; i++) {
3217
0
    u32 len, o_x;
3218
0
    ospan = &spans[i];
3219
3220
0
    o_x = ospan->x;
3221
0
    len = ospan->len;
3222
0
    aspan.len = 0;
3223
0
    u8 *mask = surf->internal_mask + surf->width * y + o_x;
3224
0
    while (len) {
3225
0
      u32 mv = *mask;
3226
3227
0
      if (mv) {
3228
0
        if (!aspan.len) {
3229
0
          aspan.x = o_x;
3230
0
          aspan.coverage = ospan->coverage;
3231
0
          aspan.odd_flag = ospan->odd_flag;
3232
0
        }
3233
0
        aspan.len++;
3234
0
        if (mv == 0xFF)
3235
0
          *mask = 0xFF - aspan.coverage;
3236
0
        else {
3237
0
          *mask = 0;
3238
0
          aspan.coverage = 0xFF;
3239
0
        }
3240
0
      } else if (aspan.len) {
3241
0
        surf->fill_spans(y, 1, &aspan, surf, rctx);
3242
0
        aspan.len = 0;
3243
0
      }
3244
0
      mask++;
3245
0
      o_x++;
3246
0
      len--;
3247
0
    }
3248
    //flush
3249
0
    if (aspan.len) {
3250
      //last span, enable yuv flush for 420 and 422
3251
      //we can do it now because we know we get called only once per y for YUV 420/422
3252
0
      if (i+1==count)
3253
0
        rctx->no_yuv_flush = 0;
3254
3255
0
      surf->fill_spans(y, 1, &aspan, surf, rctx);
3256
0
    }
3257
0
  }
3258
0
}
3259
3260
3261
#define mix_run_func(_type, _val, _shift, _R, _G, _B, _ARGB) \
3262
0
  u32 r1, g1, b1, r2, g2, b2; \
3263
0
  u32 mix = rctx->surf->mix_val; \
3264
0
  u32 imix = _val - mix; \
3265
0
  u32 i=0; \
3266
0
  _type col1, col2, *col1p = rctx->stencil_pix_run, *col2p = rctx->stencil_pix_run2; \
3267
0
  if (!mix) return; \
3268
0
  if (!imix) return;\
3269
0
  \
3270
0
  while (i<count) { \
3271
0
    col1 = col1p[i]; \
3272
0
    col2 = col2p[i]; \
3273
0
    r1 =  _R(col1); \
3274
0
    g1 =  _G(col1); \
3275
0
    b1 =  _B(col1); \
3276
0
    r2 =  _R(col2); \
3277
0
    g2 =  _G(col2); \
3278
0
    b2 =  _B(col2); \
3279
0
    r1 = (r1 * imix + r2 * mix) >> _shift; \
3280
0
    g1 = (g1 * imix + g2 * mix) >> _shift; \
3281
0
    b1 = (b1 * imix + b2 * mix) >> _shift; \
3282
0
    col1p[i] = _ARGB(_val, r1, g1, b1); \
3283
0
    i++; \
3284
0
  } \
3285
3286
static void mix_run(EVGRasterCtx *rctx, u32 count)
3287
0
{
3288
0
  mix_run_func(u32, 0xFF, 8, GF_COL_R, GF_COL_G, GF_COL_B, GF_COL_ARGB)
3289
0
}
3290
3291
static void mix_run_wide(EVGRasterCtx *rctx, u32 count)
3292
0
{
3293
0
  mix_run_func(u64, 0xFFFF, 16, GF_COLW_R, GF_COLW_G, GF_COLW_B, GF_COLW_ARGB)
3294
0
}
3295
3296
3297
#define mixa_run_func(_type, _val, _shift, _A, _R, _G, _B, _ARGB) \
3298
0
  u32 a1, r1, g1, b1, a2, r2, g2, b2; \
3299
0
  u32 mix = rctx->surf->mix_val; \
3300
0
  u32 imix = _val - mix; \
3301
0
  u32 i=0; \
3302
0
  _type col1, col2, *col1p = rctx->stencil_pix_run, *col2p = rctx->stencil_pix_run2; \
3303
0
  if (!mix) return; \
3304
0
  if (!imix) return; \
3305
0
 \
3306
0
  while (i<count) { \
3307
0
    col1 = col1p[i]; \
3308
0
    col2 = col2p[i]; \
3309
0
    a1 =  _A(col1); \
3310
0
    r1 =  _R(col1); \
3311
0
    g1 =  _G(col1); \
3312
0
    b1 =  _B(col1); \
3313
0
    a2 =  _A(col2); \
3314
0
    r2 =  _R(col2); \
3315
0
    g2 =  _G(col2); \
3316
0
    b2 =  _B(col2); \
3317
0
    a1 = (a1 * imix + a2 * mix) >> _shift; \
3318
0
    r1 = (r1 * imix + r2 * mix) >> _shift; \
3319
0
    g1 = (g1 * imix + g2 * mix) >> _shift; \
3320
0
    b1 = (b1 * imix + b2 * mix) >> _shift; \
3321
0
    col1p[i] = _ARGB(a1, r1, g1, b1); \
3322
0
    i++; \
3323
0
  } \
3324
3325
static void mixa_run(EVGRasterCtx *rctx, u32 count)
3326
0
{
3327
0
  mixa_run_func(u32, 0xFF, 8, GF_COL_A, GF_COL_R, GF_COL_G, GF_COL_B, GF_COL_ARGB)
3328
0
}
3329
3330
static void mixa_run_wide(EVGRasterCtx *rctx, u32 count)
3331
0
{
3332
0
  mixa_run_func(u64, 0xFFFF, 16, GF_COLW_A, GF_COLW_R, GF_COLW_G, GF_COLW_B, GF_COLW_ARGB)
3333
0
}
3334
3335
3336
#define repa_run_func(_type, _shift, _mask, _A) \
3337
0
  u32 i=0; \
3338
0
  _type a2, col1, col2, *col1p = rctx->stencil_pix_run, *col2p = rctx->stencil_pix_run2; \
3339
0
 \
3340
0
  while (i<count) { \
3341
0
    col1 = col1p[i]; \
3342
0
    col2 = col2p[i]; \
3343
0
    a2 = _A(col2);\
3344
0
    col1p[i] = (a2<<_shift) | (col1 & _mask);\
3345
0
    i++; \
3346
0
  } \
3347
3348
static void replace_alpha_run_a(EVGRasterCtx *rctx, u32 count)
3349
0
{
3350
0
  repa_run_func(u32, 24, 0x00FFFFFF, GF_COL_A)
3351
0
}
3352
static void replace_alpha_run_a_wide(EVGRasterCtx *rctx, u32 count)
3353
0
{
3354
0
  repa_run_func(u64, 56, 0x0000FFFFFFFFFFFFUL, GF_COLW_A)
3355
0
}
3356
static void replace_alpha_run_r(EVGRasterCtx *rctx, u32 count)
3357
0
{
3358
0
  repa_run_func(u32, 24, 0x00FFFFFF, GF_COL_R)
3359
0
}
3360
static void replace_alpha_run_r_wide(EVGRasterCtx *rctx, u32 count)
3361
0
{
3362
0
  repa_run_func(u64, 56, 0x0000FFFFFFFFFFFFUL, GF_COLW_R)
3363
0
}
3364
static void replace_alpha_run_g(EVGRasterCtx *rctx, u32 count)
3365
0
{
3366
0
  repa_run_func(u32, 24, 0x00FFFFFF, GF_COL_G)
3367
0
}
3368
static void replace_alpha_run_g_wide(EVGRasterCtx *rctx, u32 count)
3369
0
{
3370
0
  repa_run_func(u64, 56, 0x0000FFFFFFFFFFFFUL, GF_COLW_G)
3371
0
}
3372
static void replace_alpha_run_b(EVGRasterCtx *rctx, u32 count)
3373
0
{
3374
0
  repa_run_func(u32, 24, 0x00FFFFFF, GF_COL_B)
3375
0
}
3376
static void replace_alpha_run_b_wide(EVGRasterCtx *rctx, u32 count)
3377
0
{
3378
0
  repa_run_func(u64, 56, 0x0000FFFFFFFFFFFFUL, GF_COLW_B)
3379
0
}
3380
3381
3382
#define repa_m1_run_func(_type, _val, _shift, _mask, _A) \
3383
0
  u32 i=0; \
3384
0
  _type a2, col1, col2, *col1p = rctx->stencil_pix_run, *col2p = rctx->stencil_pix_run2; \
3385
0
 \
3386
0
  while (i<count) { \
3387
0
    col1 = col1p[i]; \
3388
0
    col2 = col2p[i]; \
3389
0
    a2 = _val - _A(col2);\
3390
0
    col1p[i] = (a2<<_shift) | (col1 & _mask);\
3391
0
    i++; \
3392
0
  } \
3393
3394
static void replace_alpha_m1_run_a(EVGRasterCtx *rctx, u32 count)
3395
0
{
3396
0
  repa_m1_run_func(u32, 0xFF, 24, 0x00FFFFFF, GF_COL_A)
3397
0
}
3398
static void replace_alpha_m1_run_a_wide(EVGRasterCtx *rctx, u32 count)
3399
0
{
3400
0
  repa_m1_run_func(u64, 0xFFFF, 56, 0x0000FFFFFFFFFFFFUL, GF_COLW_A)
3401
0
}
3402
static void replace_alpha_m1_run_r(EVGRasterCtx *rctx, u32 count)
3403
0
{
3404
0
  repa_m1_run_func(u32, 0xFF, 24, 0x00FFFFFF, GF_COL_R)
3405
0
}
3406
static void replace_alpha_m1_run_r_wide(EVGRasterCtx *rctx, u32 count)
3407
0
{
3408
0
  repa_m1_run_func(u64, 0xFFFF, 56, 0x0000FFFFFFFFFFFFUL, GF_COLW_R)
3409
0
}
3410
static void replace_alpha_m1_run_g(EVGRasterCtx *rctx, u32 count)
3411
0
{
3412
0
  repa_m1_run_func(u32, 0xFF, 24, 0x00FFFFFF, GF_COL_G)
3413
0
}
3414
static void replace_alpha_m1_run_g_wide(EVGRasterCtx *rctx, u32 count)
3415
0
{
3416
0
  repa_m1_run_func(u64, 0xFFFF, 56, 0x0000FFFFFFFFFFFFUL, GF_COLW_G)
3417
0
}
3418
static void replace_alpha_m1_run_b(EVGRasterCtx *rctx, u32 count)
3419
0
{
3420
0
  repa_m1_run_func(u32, 0xFF, 24, 0x00FFFFFF, GF_COL_B)
3421
0
}
3422
static void replace_alpha_m1_run_b_wide(EVGRasterCtx *rctx, u32 count)
3423
0
{
3424
0
  repa_m1_run_func(u64, 0xFFFF, 56, 0x0000FFFFFFFFFFFFUL, GF_COLW_B)
3425
0
}
3426
3427
3428
#define mix_dyn_run_func(_type, _val, _shift, _A, _R, _G, _B, _ARGB) \
3429
0
  u32 r1, g1, b1, r2, g2, b2; \
3430
0
  u32 i=0; \
3431
0
  _type col1, col2, *col1p = rctx->stencil_pix_run, *col2p = rctx->stencil_pix_run2, *col3p = rctx->stencil_pix_run3; \
3432
0
 \
3433
0
  while (i<count) { \
3434
0
    u32 mix = _A(col3p[i]); \
3435
0
    u32 imix = _val - mix; \
3436
0
    col1 = col1p[i]; \
3437
0
    col2 = col2p[i]; \
3438
0
    r1 =  _R(col1); \
3439
0
    g1 =  _G(col1); \
3440
0
    b1 =  _B(col1); \
3441
0
    r2 =  _R(col2); \
3442
0
    g2 =  _G(col2); \
3443
0
    b2 =  _B(col2); \
3444
0
    r1 = (r1 * imix + r2 * mix) >> _shift; \
3445
0
    g1 = (g1 * imix + g2 * mix) >> _shift; \
3446
0
    b1 = (b1 * imix + b2 * mix) >> _shift; \
3447
0
    col1p[i] = _ARGB(_val, r1, g1, b1); \
3448
0
    i++; \
3449
0
  } \
3450
3451
static void mix_dyn_run_a(EVGRasterCtx *rctx, u32 count)
3452
0
{
3453
0
  mix_dyn_run_func(u32, 0xFF, 8, GF_COL_A, GF_COL_R, GF_COL_G, GF_COL_B, GF_COL_ARGB)
3454
0
}
3455
3456
static void mix_dyn_run_a_wide(EVGRasterCtx *rctx, u32 count)
3457
0
{
3458
0
  mix_dyn_run_func(u64, 0xFFFF, 16, GF_COLW_A, GF_COLW_R, GF_COLW_G, GF_COLW_B, GF_COLW_ARGB)
3459
0
}
3460
3461
static void mix_dyn_run_r(EVGRasterCtx *rctx, u32 count)
3462
0
{
3463
0
  mix_dyn_run_func(u32, 0xFF, 8, GF_COL_R, GF_COL_R, GF_COL_G, GF_COL_B, GF_COL_ARGB)
3464
0
}
3465
3466
static void mix_dyn_run_r_wide(EVGRasterCtx *rctx, u32 count)
3467
0
{
3468
0
  mix_dyn_run_func(u64, 0xFFFF, 16, GF_COLW_R, GF_COLW_R, GF_COLW_G, GF_COLW_B, GF_COLW_ARGB)
3469
0
}
3470
3471
static void mix_dyn_run_g(EVGRasterCtx *rctx, u32 count)
3472
0
{
3473
0
  mix_dyn_run_func(u32, 0xFF, 8, GF_COL_G, GF_COL_R, GF_COL_G, GF_COL_B, GF_COL_ARGB)
3474
0
}
3475
3476
static void mix_dyn_run_g_wide(EVGRasterCtx *rctx, u32 count)
3477
0
{
3478
0
  mix_dyn_run_func(u64, 0xFFFF, 16, GF_COLW_G, GF_COLW_R, GF_COLW_G, GF_COLW_B, GF_COLW_ARGB)
3479
0
}
3480
static void mix_dyn_run_b(EVGRasterCtx *rctx, u32 count)
3481
0
{
3482
0
  mix_dyn_run_func(u32, 0xFF, 8, GF_COL_B, GF_COL_R, GF_COL_G, GF_COL_B, GF_COL_ARGB)
3483
0
}
3484
3485
static void mix_dyn_run_b_wide(EVGRasterCtx *rctx, u32 count)
3486
0
{
3487
0
  mix_dyn_run_func(u64, 0xFFFF, 16, GF_COLW_B, GF_COLW_R, GF_COLW_G, GF_COLW_B, GF_COLW_ARGB)
3488
0
}
3489
3490
3491
#define mix_dyna_run_func(_type, _val, _shift, _A, _R, _G, _B, _ARGB) \
3492
0
  u32 a1, r1, g1, b1, a2, r2, g2, b2; \
3493
0
  u32 i=0; \
3494
0
  _type col1, col2, *col1p = rctx->stencil_pix_run, *col2p = rctx->stencil_pix_run2, *col3p = rctx->stencil_pix_run3; \
3495
0
 \
3496
0
  while (i<count) { \
3497
0
    u32 mix = _A(col3p[i]); \
3498
0
    u32 imix = _val - mix; \
3499
0
    col1 = col1p[i]; \
3500
0
    col2 = col2p[i]; \
3501
0
    a1 =  _A(col1); \
3502
0
    r1 =  _R(col1); \
3503
0
    g1 =  _G(col1); \
3504
0
    b1 =  _B(col1); \
3505
0
    a2 =  _A(col2); \
3506
0
    r2 =  _R(col2); \
3507
0
    g2 =  _G(col2); \
3508
0
    b2 =  _B(col2); \
3509
0
    a1 = (a1 * imix + a2 * mix) >> _shift; \
3510
0
    r1 = (r1 * imix + r2 * mix) >> _shift; \
3511
0
    g1 = (g1 * imix + g2 * mix) >> _shift; \
3512
0
    b1 = (b1 * imix + b2 * mix) >> _shift; \
3513
0
    col1p[i] = _ARGB(a1, r1, g1, b1); \
3514
0
    i++; \
3515
0
  } \
3516
3517
static void mix_dyna_run_a(EVGRasterCtx *rctx, u32 count)
3518
0
{
3519
0
  mix_dyna_run_func(u32, 0xFF, 8, GF_COL_A, GF_COL_R, GF_COL_G, GF_COL_B, GF_COL_ARGB)
3520
0
}
3521
static void mix_dyna_run_a_wide(EVGRasterCtx *rctx, u32 count)
3522
0
{
3523
0
  mix_dyna_run_func(u64, 0xFFFF, 16, GF_COLW_A, GF_COLW_R, GF_COLW_G, GF_COLW_B, GF_COLW_ARGB)
3524
0
}
3525
static void mix_dyna_run_r(EVGRasterCtx *rctx, u32 count)
3526
0
{
3527
0
  mix_dyna_run_func(u32, 0xFF, 8, GF_COL_R, GF_COL_R, GF_COL_G, GF_COL_B, GF_COL_ARGB)
3528
0
}
3529
static void mix_dyna_run_r_wide(EVGRasterCtx *rctx, u32 count)
3530
0
{
3531
0
  mix_dyna_run_func(u64, 0xFFFF, 16, GF_COLW_R, GF_COLW_R, GF_COLW_G, GF_COLW_B, GF_COLW_ARGB)
3532
0
}
3533
static void mix_dyna_run_g(EVGRasterCtx *rctx, u32 count)
3534
0
{
3535
0
  mix_dyna_run_func(u32, 0xFF, 8, GF_COL_G, GF_COL_R, GF_COL_G, GF_COL_B, GF_COL_ARGB)
3536
0
}
3537
static void mix_dyna_run_g_wide(EVGRasterCtx *rctx, u32 count)
3538
0
{
3539
0
  mix_dyna_run_func(u64, 0xFFFF, 16, GF_COLW_G, GF_COLW_R, GF_COLW_G, GF_COLW_B, GF_COLW_ARGB)
3540
0
}
3541
static void mix_dyna_run_b(EVGRasterCtx *rctx, u32 count)
3542
0
{
3543
0
  mix_dyna_run_func(u32, 0xFF, 8, GF_COL_B, GF_COL_R, GF_COL_G, GF_COL_B, GF_COL_ARGB)
3544
0
}
3545
static void mix_dyna_run_b_wide(EVGRasterCtx *rctx, u32 count)
3546
0
{
3547
0
  mix_dyna_run_func(u64, 0xFFFF, 16, GF_COLW_B, GF_COLW_R, GF_COLW_G, GF_COLW_B, GF_COLW_ARGB)
3548
0
}
3549
3550
3551
GF_Err gf_evg_setup_multi_texture(GF_EVGSurface *surf, GF_EVGMultiTextureMode operand, GF_EVGStencil *sten2, GF_EVGStencil *sten3, Float *params)
3552
0
{
3553
0
  Float param1 = params ? params[0] : 0;
3554
0
  surf->sten2 = surf->sten3 = NULL;
3555
0
  surf->odd_fill = 0;
3556
3557
0
  switch (operand) {
3558
0
  case GF_EVG_OPERAND_MIX:
3559
0
    if (!sten2 || !params) return GF_BAD_PARAM;
3560
0
    surf->sten2 = sten2;
3561
0
    if (surf->not_8bits) {
3562
0
      surf->mix_val = (u32) (params[0] * 0xFFFF);
3563
0
      surf->update_run = mix_run_wide;
3564
0
      if (!surf->mix_val) surf->sten2 = NULL;
3565
0
      else if (surf->mix_val==0xFFFF) {
3566
0
        surf->sten2 = NULL;
3567
0
        surf->sten = sten2;
3568
0
      }
3569
0
    } else {
3570
0
      surf->mix_val = (u32) (params[0] * 255);
3571
0
      surf->update_run = mix_run;
3572
0
      if (!surf->mix_val) surf->sten2 = NULL;
3573
0
      else if (surf->mix_val==0xFF) {
3574
0
        surf->sten2 = NULL;
3575
0
        surf->sten = sten2;
3576
0
      }
3577
0
    }
3578
0
    break;
3579
0
  case GF_EVG_OPERAND_MIX_ALPHA:
3580
0
    if (!sten2 || !params) return GF_BAD_PARAM;
3581
0
    surf->sten2 = sten2;
3582
0
    if (surf->not_8bits) {
3583
0
      surf->mix_val = (u32) (params[0] * 0xFFFF);
3584
0
      surf->update_run = mixa_run_wide;
3585
0
      if (!surf->mix_val) surf->sten2 = NULL;
3586
0
      else if (surf->mix_val==0xFFFF) {
3587
0
        surf->sten2 = NULL;
3588
0
        surf->sten = sten2;
3589
0
      }
3590
0
    } else {
3591
0
      surf->mix_val = (u32) (params[0] * 255);
3592
0
      surf->update_run = mixa_run;
3593
0
      if (!surf->mix_val) surf->sten2 = NULL;
3594
0
      else if (surf->mix_val==0xFF) {
3595
0
        surf->sten2 = NULL;
3596
0
        surf->sten = sten2;
3597
0
      }
3598
0
    }
3599
0
    break;
3600
0
  case GF_EVG_OPERAND_REPLACE_ALPHA:
3601
0
    if (!sten2) return GF_BAD_PARAM;
3602
0
    if (param1>=3)
3603
0
      surf->update_run = surf->not_8bits ? replace_alpha_run_b_wide : replace_alpha_run_b;
3604
0
    else if (param1>=2)
3605
0
      surf->update_run = surf->not_8bits ? replace_alpha_run_g_wide : replace_alpha_run_g;
3606
0
    else if (param1>=1)
3607
0
      surf->update_run = surf->not_8bits ? replace_alpha_run_r_wide : replace_alpha_run_r;
3608
0
    else
3609
0
      surf->update_run = surf->not_8bits ? replace_alpha_run_a_wide : replace_alpha_run_a;
3610
0
    surf->sten2 = sten2;
3611
0
    break;
3612
0
  case GF_EVG_OPERAND_REPLACE_ONE_MINUS_ALPHA:
3613
0
    if (!sten2) return GF_BAD_PARAM;
3614
0
    if (param1>=3)
3615
0
      surf->update_run = surf->not_8bits ? replace_alpha_m1_run_b_wide : replace_alpha_m1_run_b;
3616
0
    else if (param1>=2)
3617
0
      surf->update_run = surf->not_8bits ? replace_alpha_m1_run_g_wide : replace_alpha_m1_run_g;
3618
0
    else if (param1>=1)
3619
0
      surf->update_run = surf->not_8bits ? replace_alpha_m1_run_r_wide : replace_alpha_m1_run_r;
3620
0
    else
3621
0
      surf->update_run = surf->not_8bits ? replace_alpha_m1_run_a_wide : replace_alpha_m1_run_a;
3622
0
    surf->sten2 = sten2;
3623
0
    break;
3624
0
  case GF_EVG_OPERAND_MIX_DYN:
3625
0
    if (!sten2 || !sten3) return GF_BAD_PARAM;
3626
0
    if (param1>=3)
3627
0
      surf->update_run = surf->not_8bits ? mix_dyn_run_b_wide : mix_dyn_run_b;
3628
0
    else if (param1>=2)
3629
0
      surf->update_run = surf->not_8bits ? mix_dyn_run_g_wide : mix_dyn_run_g;
3630
0
    else if (param1>=1)
3631
0
      surf->update_run = surf->not_8bits ? mix_dyn_run_r_wide : mix_dyn_run_r;
3632
0
    else
3633
0
      surf->update_run = surf->not_8bits ? mix_dyn_run_a_wide : mix_dyn_run_a;
3634
0
    surf->sten2 = sten2;
3635
0
    surf->sten3 = sten3;
3636
0
    break;
3637
0
  case GF_EVG_OPERAND_MIX_DYN_ALPHA:
3638
0
    if (!sten2 || !sten3 || !params) return GF_BAD_PARAM;
3639
0
    if (param1>=3)
3640
0
      surf->update_run = surf->not_8bits ? mix_dyna_run_b_wide : mix_dyna_run_b;
3641
0
    else if (param1>=2)
3642
0
      surf->update_run = surf->not_8bits ? mix_dyna_run_g_wide : mix_dyna_run_g;
3643
0
    else if (param1>=1)
3644
0
      surf->update_run = surf->not_8bits ? mix_dyna_run_r_wide : mix_dyna_run_r;
3645
0
    else
3646
0
      surf->update_run = surf->not_8bits ? mix_dyna_run_a_wide : mix_dyna_run_a;
3647
3648
0
    surf->sten2 = sten2;
3649
0
    surf->sten3 = sten3;
3650
0
    break;
3651
0
  case GF_EVG_OPERAND_ODD_FILL:
3652
0
    if (!sten2) return GF_BAD_PARAM;
3653
0
    surf->sten2 = sten2;
3654
0
    surf->odd_fill = 1;
3655
0
    break;
3656
3657
0
  default:
3658
0
    return GF_BAD_PARAM;
3659
0
  }
3660
3661
3662
0
  surf->run_size = sizeof(u32) * (surf->width+2);
3663
0
  if (surf->not_8bits) surf->run_size *= 2;
3664
3665
0
  if (surf->sten2 && !surf->raster_ctx.stencil_pix_run2) {
3666
0
    surf->raster_ctx.stencil_pix_run2 = gf_malloc(sizeof(u8) * surf->run_size);
3667
0
    if (!surf->raster_ctx.stencil_pix_run2) return GF_OUT_OF_MEM;
3668
0
  }
3669
0
  if (surf->sten3 && !surf->raster_ctx.stencil_pix_run3) {
3670
0
    surf->raster_ctx.stencil_pix_run3 = gf_malloc(sizeof(u8) * surf->run_size);
3671
0
    if (!surf->raster_ctx.stencil_pix_run3) return GF_OUT_OF_MEM;
3672
0
  }
3673
3674
0
#ifndef GPAC_DISABLE_THREADS
3675
0
  u32 i;
3676
0
  for (i=0; i<surf->nb_threads; i++) {
3677
0
    EVGRasterCtx *rctx = &surf->th_raster_ctx[i];
3678
0
    if (surf->sten2 && !rctx->stencil_pix_run2) {
3679
0
      rctx->stencil_pix_run2 = gf_malloc(sizeof(u8) * surf->run_size);
3680
0
      if (!rctx->stencil_pix_run2) return GF_OUT_OF_MEM;
3681
0
    }
3682
0
    if (surf->sten3 && !rctx->stencil_pix_run3) {
3683
0
      rctx->stencil_pix_run3 = gf_malloc(sizeof(u8) * surf->run_size);
3684
0
      if (!rctx->stencil_pix_run3) return GF_OUT_OF_MEM;
3685
0
    }
3686
0
  }
3687
0
#endif
3688
0
  return GF_OK;
3689
0
}
3690
3691
#endif //GPAC_DISABLE_EVG