1 /*
2 * GPAC - Multimedia Framework C SDK
3 *
4 * Authors: Jean Le Feuvre
5 * Copyright (c) Telecom ParisTech 2000-2019
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 static GF_EVGStencil *evg_solid_brush();
29 static GF_EVGStencil *evg_texture_brush();
30 static GF_EVGStencil *evg_linear_gradient_brush();
31 static GF_EVGStencil *evg_radial_gradient_brush();
32
33
34
color_interpolate(u32 a,u32 b,u8 pos)35 GF_Color color_interpolate(u32 a, u32 b, u8 pos)
36 {
37 u32 ca = ((a>>24) )*(u32)(0xFF-pos)+((b>>24) )*(u32)pos;
38 u32 cr = ((a>>16)&0xFF)*(u32)(0xFF-pos)+((b>>16)&0xFF)*(u32)pos;
39 u32 cg = ((a>> 8)&0xFF)*(u32)(0xFF-pos)+((b>> 8)&0xFF)*(u32)pos;
40 u32 cb = ((a )&0xFF)*(u32)(0xFF-pos)+((b )&0xFF)*(u32)pos;
41 return (((ca+(ca>>8)+1)>>8)<<24)|
42 (((cr+(cr>>8)+1)>>8)<<16)|
43 (((cg+(cg>>8)+1)>>8)<< 8)|
44 (((cb+(cb>>8)+1)>>8) );
45 }
46
47
48
49
50 /*
51 Generic gradient tools
52 */
53
54 #define EVGGRADIENTBUFFERSIZE (1<<EVGGRADIENTBITS)
55 #define EVGGRADIENTMAXINTPOS EVGGRADIENTBUFFERSIZE - 1
56
gradient_update(EVG_BaseGradient * _this)57 static void gradient_update(EVG_BaseGradient *_this)
58 {
59 s32 i, c;
60 s32 start, end, diff;
61 Fixed maxPos = INT2FIX(EVGGRADIENTMAXINTPOS);
62
63 _this->updated = 1;
64
65 if (_this->pos[0]>=0) {
66 if(_this->pos[0]>0) {
67 end = FIX2INT(gf_mulfix(_this->pos[0], maxPos));
68 for (i=0; i<= end; i++) {
69 _this->precomputed_argb[i] = _this->col[0];
70 }
71 }
72 for (c=0; c<EVGGRADIENTSLOTS; c++) {
73 if (_this->pos[c]<0) break;
74 if (_this->pos[c+1]>=0) {
75 start = FIX2INT(gf_mulfix(_this->pos[c], maxPos));
76 end = FIX2INT(gf_mulfix(_this->pos[c+1], maxPos));
77 diff = end-start;
78
79 if (diff) {
80 for (i=start; i<=end; i++) {
81 _this->precomputed_argb[i] = color_interpolate(_this->col[c], _this->col[c+1],
82 (u8) ( ( (i-start) * 255) / diff) );
83 }
84 }
85 } else {
86 start = FIX2INT(gf_mulfix(_this->pos[c+0], maxPos));
87 for(i=start; i<=EVGGRADIENTMAXINTPOS; i++) {
88 _this->precomputed_argb[i] = _this->col[c];
89 }
90 }
91 }
92 }
93 }
94
gradient_get_color(EVG_BaseGradient * _this,s32 pos)95 static u32 gradient_get_color(EVG_BaseGradient *_this, s32 pos)
96 {
97 s32 max_pos = 1 << EVGGRADIENTBITS;
98
99 switch (_this->mod) {
100 case GF_GRADIENT_MODE_SPREAD:
101 if (pos<0) pos = -pos;
102 return _this->precomputed_dest[(pos & max_pos) ? EVGGRADIENTMAXINTPOS - (pos % max_pos) : pos % max_pos];
103
104 case GF_GRADIENT_MODE_REPEAT:
105 while (pos < 0) pos += max_pos;
106 return _this->precomputed_dest[pos % max_pos];
107
108 case GF_GRADIENT_MODE_PAD:
109 default:
110 return _this->precomputed_dest[ MIN(EVGGRADIENTMAXINTPOS, MAX((s32) 0, pos))];
111 }
112 }
113
114 GF_EXPORT
gf_evg_stencil_set_gradient_interpolation(GF_EVGStencil * p,Fixed * pos,GF_Color * col,u32 count)115 GF_Err gf_evg_stencil_set_gradient_interpolation(GF_EVGStencil * p, Fixed *pos, GF_Color *col, u32 count)
116 {
117 EVG_BaseGradient *_this = (EVG_BaseGradient *) p;
118 if ( (_this->type != GF_STENCIL_LINEAR_GRADIENT) && (_this->type != GF_STENCIL_RADIAL_GRADIENT) ) return GF_BAD_PARAM;
119 if (count>=EVGGRADIENTSLOTS-1) return GF_OUT_OF_MEM;
120 if (count) {
121 memcpy(_this->col, col, sizeof(GF_Color) * count);
122 memcpy(_this->pos, pos, sizeof(Fixed) * count);
123 }
124 _this->col[count] = 0;
125 _this->pos[count] = -FIX_ONE;
126 gradient_update(_this);
127 return GF_OK;
128 }
129
130
131 GF_EXPORT
gf_evg_stencil_push_gradient_interpolation(GF_EVGStencil * p,Fixed pos,GF_Color col)132 GF_Err gf_evg_stencil_push_gradient_interpolation(GF_EVGStencil * p, Fixed pos, GF_Color col)
133 {
134 u32 count=0;
135 EVG_BaseGradient *_this = (EVG_BaseGradient *) p;
136 if ( (_this->type != GF_STENCIL_LINEAR_GRADIENT) && (_this->type != GF_STENCIL_RADIAL_GRADIENT) ) return GF_BAD_PARAM;
137 while (count<EVGGRADIENTSLOTS-1) {
138 if (_this->pos[count]==-FIX_ONE) break;
139 count++;
140 }
141 if (count>=EVGGRADIENTSLOTS-1) return GF_OUT_OF_MEM;
142 _this->col[count] = col;
143 _this->pos[count] = pos;
144 count++;
145 _this->col[count] = 0;
146 _this->pos[count] = -FIX_ONE;
147 gradient_update(_this);
148 return GF_OK;
149 }
150
151 GF_EXPORT
gf_evg_stencil_set_gradient_mode(GF_EVGStencil * p,GF_GradientMode mode)152 GF_Err gf_evg_stencil_set_gradient_mode(GF_EVGStencil * p, GF_GradientMode mode)
153 {
154 EVG_BaseGradient *_this = (EVG_BaseGradient *) p;
155 if ( (_this->type != GF_STENCIL_LINEAR_GRADIENT) && (_this->type != GF_STENCIL_RADIAL_GRADIENT) ) return GF_BAD_PARAM;
156 _this->mod = mode;
157 return GF_OK;
158 }
159
160 /*
161 Generic stencil
162 */
163
164 GF_EXPORT
gf_evg_stencil_new(GF_StencilType type)165 GF_EVGStencil * gf_evg_stencil_new(GF_StencilType type)
166 {
167 GF_EVGStencil *st;
168 switch (type) {
169 case GF_STENCIL_SOLID:
170 st = evg_solid_brush();
171 break;
172 case GF_STENCIL_LINEAR_GRADIENT:
173 st = evg_linear_gradient_brush();
174 break;
175 case GF_STENCIL_RADIAL_GRADIENT:
176 st = evg_radial_gradient_brush();
177 break;
178 case GF_STENCIL_TEXTURE:
179 st = evg_texture_brush();
180 break;
181 default:
182 return 0L;
183 }
184 if (st) {
185 gf_mx2d_init(st->pmat);
186 gf_mx2d_init(st->smat);
187 gf_cmx_init(&st->cmat);
188 }
189 return st;
190 }
191
192 GF_EXPORT
gf_evg_stencil_delete(GF_EVGStencil * st)193 void gf_evg_stencil_delete(GF_EVGStencil * st)
194 {
195 GF_EVGStencil *_this = (GF_EVGStencil *) st;
196 switch(_this->type) {
197 case GF_STENCIL_SOLID:
198 case GF_STENCIL_LINEAR_GRADIENT:
199 case GF_STENCIL_RADIAL_GRADIENT:
200 gf_free(_this);
201 return;
202 case GF_STENCIL_TEXTURE:
203 {
204 EVG_Texture *tx = (EVG_Texture *)_this;
205 /*destroy local texture iof any*/
206 if (tx->owns_texture && tx->pixels) gf_free(tx->pixels);
207 gf_free(_this);
208 }
209 return;
210 }
211 }
212
213 GF_EXPORT
gf_evg_stencil_set_matrix(GF_EVGStencil * st,GF_Matrix2D * mx)214 GF_Err gf_evg_stencil_set_matrix(GF_EVGStencil * st, GF_Matrix2D *mx)
215 {
216 GF_EVGStencil *_this = (GF_EVGStencil *)st;
217 if (!_this || _this->type>GF_STENCIL_TEXTURE) return GF_BAD_PARAM;
218 if (mx) {
219 gf_mx2d_copy(_this->smat, *mx);
220 } else {
221 gf_mx2d_init(_this->smat);
222 }
223 return GF_OK;
224 }
225
226
227 GF_EXPORT
gf_evg_stencil_type(GF_EVGStencil * sten)228 GF_StencilType gf_evg_stencil_type(GF_EVGStencil *sten)
229 {
230 return sten ? sten->type : 0;
231 }
232
233 /*
234 Solid color stencil
235 */
236
evg_solid_brush()237 static GF_EVGStencil *evg_solid_brush()
238 {
239 EVG_Brush *tmp;
240 GF_SAFEALLOC(tmp, EVG_Brush);
241 if (!tmp) return 0L;
242 tmp->fill_run = NULL;
243 tmp->color = 0xFF000000;
244 tmp->type = GF_STENCIL_SOLID;
245 return (GF_EVGStencil *) tmp;
246 }
247
248 GF_EXPORT
gf_evg_stencil_set_brush_color(GF_EVGStencil * st,GF_Color c)249 GF_Err gf_evg_stencil_set_brush_color(GF_EVGStencil * st, GF_Color c)
250 {
251 EVG_Brush *_this = (EVG_Brush *) st;
252 if (!_this || (_this ->type != GF_STENCIL_SOLID) ) return GF_BAD_PARAM;
253 _this->color = c;
254 return GF_OK;
255 }
256
257
258 /*
259 linear gradient stencil
260 */
261
lg_fill_run(GF_EVGStencil * p,GF_EVGSurface * surf,s32 x,s32 y,u32 count)262 static void lg_fill_run(GF_EVGStencil *p, GF_EVGSurface *surf, s32 x, s32 y, u32 count)
263 {
264 Fixed _res;
265 s32 val;
266 u32 col;
267 u32 *data = surf->stencil_pix_run;
268 u64 *data_wide = surf->not_8bits ? surf->stencil_pix_run : NULL;
269 EVG_LinearGradient *_this = (EVG_LinearGradient *) p;
270
271 assert(data);
272
273 /*no need to move x & y to fixed*/
274 _res = (Fixed) (x * _this->smat.m[0] + y * _this->smat.m[1] + _this->smat.m[2]);
275 while (count) {
276 val = FIX2INT(_res);
277 _res += _this->smat.m[0];
278
279 col = gradient_get_color((EVG_BaseGradient *)_this, val );
280 if (data_wide) *data_wide++ = evg_col_to_wide(col);
281 else *data++ = col;
282
283 count--;
284 }
285 }
286
287 GF_EXPORT
gf_evg_stencil_set_linear_gradient(GF_EVGStencil * st,Fixed start_x,Fixed start_y,Fixed end_x,Fixed end_y)288 GF_Err gf_evg_stencil_set_linear_gradient(GF_EVGStencil * st, Fixed start_x, Fixed start_y, Fixed end_x, Fixed end_y)
289 {
290 GF_Matrix2D mtx;
291 GF_Point2D s;
292 Fixed f;
293 EVG_LinearGradient *_this = (EVG_LinearGradient *) st;
294 if (_this->type != GF_STENCIL_LINEAR_GRADIENT) return GF_BAD_PARAM;
295
296 _this->start.x = start_x;
297 _this->start.y = start_y;
298 _this->end.x = end_x;
299 _this->end.y = end_y;
300 s.x = end_x - start_x;
301 s.y = end_y - start_y;
302 f = gf_v2d_len(&s);
303 if (f) f = gf_invfix(f);
304
305 gf_mx2d_init(mtx);
306 mtx.m[2] = - _this->start.x;
307 mtx.m[5] = - _this->start.y;
308 _this->vecmat = mtx;
309
310 gf_mx2d_init(mtx);
311 gf_mx2d_add_rotation(&mtx, 0, 0, - gf_atan2(s.y, s.x));
312 gf_mx2d_add_matrix(&_this->vecmat, &mtx);
313
314 gf_mx2d_init(mtx);
315 gf_mx2d_add_scale(&mtx, f, f);
316 gf_mx2d_add_matrix(&_this->vecmat, &mtx);
317 return GF_OK;
318 }
319
evg_linear_gradient_brush()320 static GF_EVGStencil *evg_linear_gradient_brush()
321 {
322 s32 i;
323 EVG_LinearGradient *tmp;
324 GF_SAFEALLOC(tmp, EVG_LinearGradient);
325 if (!tmp) return 0L;
326 gf_mx2d_init(tmp->vecmat);
327 tmp->fill_run = lg_fill_run;
328 tmp->type = GF_STENCIL_LINEAR_GRADIENT;
329 for(i=0; i<EVGGRADIENTSLOTS; i++) tmp->pos[i]=-1;
330
331 tmp->alpha = 0xFF;
332 gf_evg_stencil_set_linear_gradient((GF_EVGStencil *)tmp, 0, 0, FIX_ONE, 0);
333 return (GF_EVGStencil *) tmp;
334 }
335
336
337 /*
338 radial gradient stencil
339 */
340
rg_fill_run(GF_EVGStencil * p,GF_EVGSurface * surf,s32 _x,s32 _y,u32 count)341 static void rg_fill_run(GF_EVGStencil *p, GF_EVGSurface *surf, s32 _x, s32 _y, u32 count)
342 {
343 Fixed x, y, dx, dy, b, val;
344 s32 pos;
345 u32 col;
346 u32 *data = surf->stencil_pix_run;
347 u64 *data_wide = surf->not_8bits ? surf->stencil_pix_run : NULL;
348 EVG_RadialGradient *_this = (EVG_RadialGradient *) p;
349
350 assert(data);
351
352 x = INT2FIX(_x);
353 y = INT2FIX(_y);
354 gf_mx2d_apply_coords(&_this->smat, &x, &y);
355
356 dx = x - _this->d_f.x;
357 dy = y - _this->d_f.y;
358 while (count) {
359 b = gf_mulfix(_this->rad, gf_mulfix(dx, _this->d_f.x) + gf_mulfix(dy, _this->d_f.y));
360 val = gf_mulfix(b, b) + gf_mulfix(_this->rad, gf_mulfix(dx, dx)+gf_mulfix(dy, dy));
361 b += gf_sqrt(val);
362 pos = FIX2INT(EVGGRADIENTBUFFERSIZE*b);
363
364 col = gradient_get_color((EVG_BaseGradient *)_this, pos);
365 if (data_wide) *data_wide++ = evg_col_to_wide(col);
366 else *data++ = col;
367
368 dx += _this->d_i.x;
369 dy += _this->d_i.y;
370 count--;
371 }
372 }
373
evg_radial_init(EVG_RadialGradient * _this)374 void evg_radial_init(EVG_RadialGradient *_this)
375 {
376 GF_Point2D p0, p1;
377 p0.x = p0.y = p1.y = 0;
378 p1.x = FIX_ONE;
379
380 gf_mx2d_apply_point(&_this->smat, &p0);
381 gf_mx2d_apply_point(&_this->smat, &p1);
382 _this->d_i.x = p1.x - p0.x;
383 _this->d_i.y = p1.y - p0.y;
384
385 _this->rad = FIX_ONE - gf_mulfix(_this->d_f.x, _this->d_f.x) - gf_mulfix(_this->d_f.y, _this->d_f.y);
386 if (_this->rad) {
387 _this->rad = gf_invfix(_this->rad);
388 } else {
389 _this->rad = EVGGRADIENTBUFFERSIZE;
390 }
391 }
392
evg_radial_gradient_brush()393 static GF_EVGStencil *evg_radial_gradient_brush()
394 {
395 s32 i;
396 EVG_RadialGradient *tmp;
397 GF_SAFEALLOC(tmp, EVG_RadialGradient);
398 if (!tmp) return 0L;
399
400 tmp->fill_run = rg_fill_run;
401 tmp->type = GF_STENCIL_RADIAL_GRADIENT;
402 for(i=0; i<EVGGRADIENTSLOTS; i++) tmp->pos[i]=-1;
403
404 tmp->center.x = tmp->center.y = FIX_ONE/2;
405 tmp->focus = tmp->center;
406 tmp->radius = tmp->center;
407 tmp->alpha = 0xFF;
408 return (GF_EVGStencil *) tmp;
409 }
410
411
412 GF_EXPORT
gf_evg_stencil_set_radial_gradient(GF_EVGStencil * st,Fixed cx,Fixed cy,Fixed fx,Fixed fy,Fixed x_radius,Fixed y_radius)413 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)
414 {
415 EVG_RadialGradient *_this = (EVG_RadialGradient *) st;
416 if (_this->type != GF_STENCIL_RADIAL_GRADIENT) return GF_BAD_PARAM;
417
418 _this->center.x = cx;
419 _this->center.y = cy;
420 _this->focus.x = fx;
421 _this->focus.y = fy;
422 _this->radius.x = x_radius;
423 _this->radius.y = y_radius;
424 return GF_OK;
425 }
426
427
evg_gradient_precompute(EVG_BaseGradient * grad,GF_EVGSurface * surf)428 void evg_gradient_precompute(EVG_BaseGradient *grad, GF_EVGSurface *surf)
429 {
430 Bool do_cmat, do_yuv, has_a, has_changed;
431 u32 i, nb_col;
432
433 has_changed = grad->updated;
434
435 if (surf->yuv_type) {
436 if (grad->yuv_prof != surf->yuv_prof) {
437 grad->yuv_prof = surf->yuv_prof;
438 has_changed = GF_TRUE;
439 }
440 } else {
441 if (grad->yuv_prof) {
442 grad->yuv_prof = 0;
443 has_changed = GF_TRUE;
444 }
445 }
446 if (!has_changed) {
447 return;
448 }
449 grad->updated = 0;
450
451 do_yuv = (surf->yuv_type==EVG_YUV_NONE) ? GF_FALSE : GF_TRUE;
452
453 do_cmat = (grad->cmat.identity) ? GF_FALSE : GF_TRUE;
454 has_a = (grad->alpha==0xFF) ? GF_FALSE : GF_TRUE;
455 nb_col = (1<<EVGGRADIENTBITS);
456
457 for (i=0; i<nb_col; i++) {
458 u32 argb = grad->precomputed_argb[i];
459 if (has_a) {
460 u32 ca = ((u32) (GF_COL_A(argb) + 1) * grad->alpha) >> 8;
461 argb = ( ((ca<<24) & 0xFF000000) ) | (argb & 0x00FFFFFF);
462 }
463 if (do_cmat)
464 argb = gf_cmx_apply(&grad->cmat, argb);
465
466 if (do_yuv)
467 argb = gf_evg_argb_to_ayuv(surf, argb);
468
469 grad->precomputed_dest[i] = argb;
470 }
471 }
472
473
474 /*
475 Texture stencil
476 FIXME: add filtering , check bilinear
477 */
478
mul255(s32 a,s32 b)479 static GFINLINE s32 mul255(s32 a, s32 b)
480 {
481 return ((a+1) * b) >> 8;
482 }
EVG_LERP(u32 c0,u32 c1,u8 t)483 static u32 EVG_LERP(u32 c0, u32 c1, u8 t)
484 {
485 s32 a0, r0, g0, b0;
486 s32 a1, r1, g1, b1;
487 s32 a2, r2, g2, b2;
488
489 if (!t) return c0;
490
491 a0 = GF_COL_A(c0);
492 r0 = GF_COL_R(c0);
493 g0 = GF_COL_G(c0);
494 b0 = GF_COL_B(c0);
495 a1 = GF_COL_A(c1);
496 r1 = GF_COL_R(c1);
497 g1 = GF_COL_G(c1);
498 b1 = GF_COL_B(c1);
499
500 a2 = a0 + mul255(t, (a1 - a0));
501 r2 = r0 + mul255(t, (r1 - r0));
502 g2 = g0 + mul255(t, (g1 - g0));
503 b2 = b0 + mul255(t, (b1 - b0));
504 return GF_COL_ARGB(a2, r2, g2, b2);
505 }
506
mul_wide(s64 a,s64 b)507 static GFINLINE s64 mul_wide(s64 a, s64 b)
508 {
509 return ((a+1) * b) >> 16;
510 }
EVG_LERP_WIDE(u64 c0,u64 c1,u8 t)511 static u64 EVG_LERP_WIDE(u64 c0, u64 c1, u8 t)
512 {
513 s64 a0, r0, g0, b0;
514 s64 a1, r1, g1, b1;
515 s64 a2, r2, g2, b2;
516
517 if (!t) return c0;
518
519 a0 = (c0>>48) & 0xFFFF;
520 r0 = (c0>>32) & 0xFFFF;
521 g0 = (c0>>16) & 0xFFFF;
522 b0 = (c0) & 0xFFFF;
523
524 a1 = (c1>>48) & 0xFFFF;
525 r1 = (c1>>32) & 0xFFFF;
526 g1 = (c1>>16) & 0xFFFF;
527 b1 = (c1) & 0xFFFF;
528
529 a2 = a0 + mul_wide(t, (a1 - a0));
530 r2 = r0 + mul_wide(t, (r1 - r0));
531 g2 = g0 + mul_wide(t, (g1 - g0));
532 b2 = b0 + mul_wide(t, (b1 - b0));
533
534 return evg_make_col_wide(a2, r2, g2, b2);
535 }
536
tex_untransform_coord(EVG_Texture * _this,s32 _x,s32 _y,Fixed * outx,Fixed * outy)537 static void tex_untransform_coord(EVG_Texture *_this, s32 _x, s32 _y, Fixed *outx, Fixed *outy)
538 {
539 u32 checkx, checky;
540 Fixed x, y, dim;
541
542 /* reverse to texture coords*/
543 x = INT2FIX(_x);
544 y = INT2FIX(_y);
545 gf_mx2d_apply_coords(&_this->smat, &x, &y);
546
547 checkx = checky = 0;
548 if (ABS(x)< FIX_ONE/20) checkx = 1;
549 if (ABS(y)< FIX_ONE/20) checky = 1;
550
551 /*we may have a numerical stability issues, try to figure out whether we are close from 0 or width/height*/
552 if ( checkx || checky) {
553 Fixed tx, ty;
554 tx = INT2FIX(_x+1);
555 ty = INT2FIX(_y+1);
556 gf_mx2d_apply_coords(&_this->smat, &tx, &ty);
557
558 if (checkx) {
559 if (tx<0) x = INT2FIX(_this->width - 1);
560 else x = 0;
561 }
562 if (checky) {
563 if (ty<0) y = INT2FIX(_this->height - 1);
564 else y = 0;
565 }
566 }
567
568 dim = INT2FIX(_this->width);
569 if (_this->mod & GF_TEXTURE_REPEAT_S) {
570 if (x<0) {
571 while (x<0) x += dim;
572 } else {
573 while (x>dim) x -= dim;
574 }
575 } else {
576 if (x<-dim) {
577 x = 0;
578 } else if (x>dim) {
579 x = dim;
580 }
581 while (x<0) x+=dim;
582 }
583
584 dim = INT2FIX(_this->height);
585 if (_this->mod & GF_TEXTURE_REPEAT_T) {
586 if (y<0) {
587 while (y<0) y += dim;
588 } else {
589 while (y>dim) y -= dim;
590 }
591 } else {
592 if (y<-dim) {
593 y = 0;
594 } else if (y>dim) {
595 y = dim;
596 }
597 while (y<0) y+=dim;
598 }
599
600 *outx=x;
601 *outy=y;
602 }
603
604
evg_paramtx_get_pixel(struct __evg_texture * _this,u32 x,u32 y)605 static u32 evg_paramtx_get_pixel(struct __evg_texture *_this, u32 x, u32 y)
606 {
607 Float a, r, g, b;
608 _this->tx_callback(_this->tx_callback_udta, x, y, &r, &g, &b, &a);
609 r*=255;
610 g*=255;
611 b*=255;
612 a*=255;
613 return GF_COL_ARGB(a, r, g, b);
614 }
evg_paramtx_get_pixel_wide(struct __evg_texture * _this,u32 x,u32 y)615 u64 evg_paramtx_get_pixel_wide(struct __evg_texture *_this, u32 x, u32 y)
616 {
617 Float a, r, g, b;
618 _this->tx_callback(_this->tx_callback_udta, x, y, &r, &g, &b, &a);
619 r*=0xFFFF;
620 g*=0xFFFF;
621 b*=0xFFFF;
622 a*=0xFFFF;
623 return evg_make_col_wide(a, r, g, b);
624 }
625
tex_fill_run_callback(EVG_Texture * p,GF_EVGSurface * surf,s32 _x,s32 _y,u32 count)626 static void tex_fill_run_callback(EVG_Texture *p, GF_EVGSurface *surf, s32 _x, s32 _y, u32 count)
627 {
628 u32 *data = surf->stencil_pix_run;
629 while (count) {
630 *data = evg_paramtx_get_pixel(p, _x, _y);
631 data++;
632 count--;
633 _x++;
634 }
635 }
636
tex_fill_run_callback_wide(EVG_Texture * p,GF_EVGSurface * surf,s32 _x,s32 _y,u32 count)637 static void tex_fill_run_callback_wide(EVG_Texture *p, GF_EVGSurface *surf, s32 _x, s32 _y, u32 count)
638 {
639 u64 *data = surf->stencil_pix_run;
640 while (count) {
641 *data = evg_paramtx_get_pixel_wide(p, _x, _y);
642 data++;
643 count--;
644 }
645 }
646
647 //bilinear used fo 2D graphics ?
648 #define USE_BILINEAR 0
649
tex_fill_run(GF_EVGStencil * p,GF_EVGSurface * surf,s32 _x,s32 _y,u32 count)650 static void tex_fill_run(GF_EVGStencil *p, GF_EVGSurface *surf, s32 _x, s32 _y, u32 count)
651 {
652 s32 cx, x0, y0;
653 u32 pix, replace_col;
654 Bool has_alpha, has_replace_cmat, has_cmat, repeat_s, repeat_t;
655 Fixed x, y, _fd;
656 #if USE_BILINEAR
657 s32 incx, incy;
658 #endif
659 u32 *data = surf->stencil_pix_run;
660 EVG_Texture *_this = (EVG_Texture *) p;
661
662 if (_this->tx_callback && _this->tx_callback_screen_coords) {
663 tex_fill_run_callback(_this, surf, _x, _y, count);
664 return;
665 }
666
667 tex_untransform_coord(_this, _x, _y, &x, &y);
668
669 #if USE_BILINEAR
670 incx = (_this->inc_x>0) ? 1 : -1;
671 incy = (_this->inc_y>0) ? 1 : -1;
672 #endif
673
674 _fd = INT2FIX(_this->width);
675 repeat_s = _this->mod & GF_TEXTURE_REPEAT_S;
676 if (!repeat_s && (x < - _fd)) x = 0;
677 while (x<0) x += _fd;
678
679 _fd = INT2FIX(_this->height);
680 repeat_t = _this->mod & GF_TEXTURE_REPEAT_T;
681 if (!repeat_t && (y < - _fd)) y = 0;
682 while (y<0) y += _fd;
683
684 has_alpha = (_this->alpha != 255) ? GF_TRUE : GF_FALSE;
685 has_replace_cmat = _this->cmat_is_replace ? GF_TRUE : GF_FALSE;
686 if (has_replace_cmat) has_cmat = GF_FALSE;
687 else has_cmat = _this->cmat.identity ? GF_FALSE : GF_TRUE;
688
689 replace_col = _this->replace_col;
690
691 while (count) {
692 x0 = FIX2INT(x);
693 assert((s32)x0 >=0);
694 if (repeat_s) {
695 x0 = (x0) % _this->width;
696 } else {
697 x0 = MIN(x0, (s32) _this->width - 1);
698 }
699
700 y0 = FIX2INT(y);
701 assert((s32)y0 >=0);
702 if (repeat_t) {
703 y0 = (y0) % _this->height;
704 } else if (y0 >= (s32) _this->height) {
705 y0 = _this->height-1;
706 }
707
708 pix = _this->tx_get_pixel(_this, x0, y0);
709
710 _x++;
711 tex_untransform_coord(_this, _x, _y, &x, &y);
712
713 if (x<0) x+=INT2FIX(_this->width);
714 if (y<0) y+=INT2FIX(_this->height);
715
716 /*bilinear filtering - disabled (too slow and not precise enough)*/
717 #if USE_BILINEAR
718 if (_this->filter==GF_TEXTURE_FILTER_HIGH_QUALITY) {
719 u32 p00, p01, p10, p11;
720 s32 x1, y1;
721 u8 tx, ty;
722
723 tx = FIX2INT(gf_muldiv(x, 255, _this->width) );
724 ty = FIX2INT(gf_muldiv(y, 255, _this->height) );
725
726 x1 = (x0+incx);
727 if (x1<0) {
728 while (x1<0) x1 += _this->width;
729 } else {
730 x1 = x1 % _this->width;
731 }
732 y1 = (y0+incy);
733 if (y1<0) {
734 while (y1<0) y1+=_this->height;
735 } else {
736 y1 = y1 % _this->height;
737 }
738 if (incx>0) {
739 if (x1<x0) tx = 255-tx;
740 } else {
741 if (x1>x0) tx = 255-tx;
742 }
743 if (incy>0) {
744 if (y1<y0) ty = 255-ty;
745 } else {
746 if (y1>y0) ty = 255-ty;
747 }
748
749 p00 = pix;
750 p01 = _this->tx_get_pixel(_this, x1, y0);
751 p10 = _this->tx_get_pixel(_this, x0, y1);
752 p11 = _this->tx_get_pixel(_this, x1, y1);
753
754 p00 = EVG_LERP(p00, p01, tx);
755 p10 = EVG_LERP(p10, p11, tx);
756 pix = EVG_LERP(p00, p10, ty);
757
758 }
759 #endif
760
761 if (has_alpha) {
762 cx = ((GF_COL_A(pix) + 1) * _this->alpha) >> 8;
763 pix = ( ((cx<<24) & 0xFF000000) ) | (pix & 0x00FFFFFF);
764 }
765 if (has_replace_cmat) {
766 u32 __a;
767 __a = GF_COL_A(pix);
768 __a = (u32) (_this->cmat.m[18] * __a);
769 //replace col is in target pixel format
770 pix = ((__a<<24) | (replace_col & 0x00FFFFFF));
771 }
772 //move pixel to target pixel format, applying color transform matrix
773 else if (_this->is_yuv) {
774 //if surf is rgb, transform
775 if (!surf->yuv_type) {
776 pix = gf_evg_ayuv_to_argb(surf, pix);
777 //apply cmat
778 if (has_cmat)
779 pix = gf_cmx_apply(&_this->cmat, pix);
780 } else if (has_cmat) {
781 //yuv->yuv , use color matrix in yuv domain
782 //this is equivalent to gf_evg_ayuv_to_argb, gf_cmx_apply(&_this->cmat, pix), gf_evg_argb_to_ayuv
783 pix = gf_cmx_apply(&_this->yuv_cmat, pix);
784 }
785 }
786 //texture is RGB
787 else {
788 //apply cmat
789 if (has_cmat)
790 pix = gf_cmx_apply(&_this->cmat, pix);
791
792 //dest is yuv, transform
793 if (surf->yuv_type)
794 pix = gf_evg_argb_to_ayuv(surf, pix);
795 }
796
797 *data++ = pix;
798 count--;
799 }
800 }
801
802
803 /*just a little faster...*/
tex_fill_run_straight(GF_EVGStencil * p,GF_EVGSurface * surf,s32 _x,s32 _y,u32 count)804 static void tex_fill_run_straight(GF_EVGStencil *p, GF_EVGSurface *surf, s32 _x, s32 _y, u32 count)
805 {
806 s32 x0, y0;
807 u32 pix;
808 u32 __a;
809 Bool repeat_s = GF_FALSE;
810 Fixed x, y, _fdim;
811 u32 *data = surf->stencil_pix_run;
812 EVG_Texture *_this = (EVG_Texture *) p;
813
814 if (_this->tx_callback && _this->tx_callback_screen_coords) {
815 tex_fill_run_callback(_this, surf, _x, _y, count);
816 return;
817 }
818
819 /*get texture coords in FIXED - offset*/
820 x = _this->smat.m[0]*_x + _this->smat.m[2];
821 y = _this->smat.m[4]*_y + _this->smat.m[5];
822
823 /*we may have a numerical stability issues, try to figure out whether we are close from 0 or width/height*/
824 if (ABS(x)< FIX_ONE/10) {
825 Fixed test = _this->smat.m[0]*(_x+1) + _this->smat.m[2];
826 if (test<0) x = INT2FIX(_this->width - 1);
827 else x = 0;
828 }
829 if (ABS(y)< FIX_ONE/10) {
830 Fixed test = _this->smat.m[4]*(_y+1) + _this->smat.m[5];
831 if (test<0) y = INT2FIX(_this->height - 1);
832 else y = 0;
833 }
834
835 /* and move in absolute coords*/
836 _fdim = INT2FIX(_this->width);
837 repeat_s = (_this->mod & GF_TEXTURE_REPEAT_S);
838 if (!repeat_s && (x <- _fdim)) x=0;
839 while (x<0) x += _fdim;
840
841 _fdim = INT2FIX(_this->height);
842 if (!(_this->mod & GF_TEXTURE_REPEAT_T) && (y <- _fdim)) y = 0;
843 while (y<0) y += _fdim;
844
845 y0 = FIX2INT(y);
846 y0 = y0 % _this->height;
847
848 while (count) {
849 x0 = FIX2INT(x);
850 if (repeat_s) {
851 x0 = (x0) % _this->width;
852 } else if (x0 >= (s32) _this->width) x0 = _this->width-1;
853
854 x += _this->inc_x;
855 pix = _this->tx_get_pixel(_this, x0, y0);
856
857 //replace_col is in destination format
858 if (_this->replace_col) {
859 __a = GF_COL_A(pix);
860 pix = ((__a<<24) | (_this->replace_col & 0x00FFFFFF));
861 }
862 //move pixel to target pixel format
863 else if (_this->is_yuv && !surf->yuv_type) {
864 pix = gf_evg_ayuv_to_argb(surf, pix);
865 }
866 else if (!_this->is_yuv && surf->yuv_type) {
867 pix = gf_evg_argb_to_ayuv(surf, pix);
868 }
869
870 *data++ = pix;
871 count--;
872 }
873 }
874
evg_col_to_wide(u32 col)875 u64 evg_col_to_wide( u32 col)
876 {
877 u32 a = GF_COL_A(col) << 8 | 0xFF;
878 u32 r = GF_COL_R(col) << 8 | 0xFF;
879 u32 g = GF_COL_G(col) << 8 | 0xFF;
880 u32 b = GF_COL_B(col) << 8 | 0xFF;
881 return evg_make_col_wide(a, r, g, b);
882 }
883
tex_fill_run_wide(GF_EVGStencil * p,GF_EVGSurface * surf,s32 _x,s32 _y,u32 count)884 static void tex_fill_run_wide(GF_EVGStencil *p, GF_EVGSurface *surf, s32 _x, s32 _y, u32 count)
885 {
886 s32 x0, y0;
887 u64 pix, replace_col;
888 Bool has_alpha, has_replace_cmat, has_cmat, repeat_s, repeat_t;
889 Fixed x, y, _fd;
890 #if USE_BILINEAR
891 s32 incx, incy;
892 #endif
893 u64 *data = surf->stencil_pix_run;
894 EVG_Texture *_this = (EVG_Texture *) p;
895
896 if (_this->tx_callback && _this->tx_callback_screen_coords) {
897 tex_fill_run_callback_wide(_this, surf, _x, _y, count);
898 return;
899 }
900
901 tex_untransform_coord(_this, _x, _y, &x, &y);
902
903 #if USE_BILINEAR
904 incx = (_this->inc_x>0) ? 1 : -1;
905 incy = (_this->inc_y>0) ? 1 : -1;
906 #endif
907
908 _fd = INT2FIX(_this->width);
909 repeat_s = _this->mod & GF_TEXTURE_REPEAT_S;
910 if (!repeat_s && (x < - _fd)) x = 0;
911 while (x<0) x += _fd;
912
913 _fd = INT2FIX(_this->height);
914 repeat_t = _this->mod & GF_TEXTURE_REPEAT_T;
915 if (!repeat_t && (y < - _fd)) y = 0;
916 while (y<0) y += _fd;
917
918 has_alpha = (_this->alpha != 255) ? GF_TRUE : GF_FALSE;
919 has_replace_cmat = _this->cmat_is_replace ? GF_TRUE : GF_FALSE;
920 if (has_replace_cmat) has_cmat = GF_FALSE;
921 else has_cmat = _this->cmat.identity ? GF_FALSE : GF_TRUE;
922
923 replace_col = evg_col_to_wide(_this->replace_col);
924
925 while (count) {
926 x0 = FIX2INT(x);
927 assert((s32)x0 >=0);
928 if (repeat_s) {
929 x0 = (x0) % _this->width;
930 } else {
931 x0 = MIN(x0, (s32) _this->width - 1);
932 }
933
934 y0 = FIX2INT(y);
935 assert((s32)y0 >=0);
936 if (repeat_t) {
937 y0 = (y0) % _this->height;
938 } else if (y0 >= (s32) _this->height) {
939 y0 = _this->height-1;
940 }
941
942 if (_this->tx_get_pixel_wide) {
943 pix = _this->tx_get_pixel_wide(_this, x0, y0);
944 } else {
945 pix = evg_col_to_wide( _this->tx_get_pixel(_this, x0, y0) );
946 }
947 _x++;
948 tex_untransform_coord(_this, _x, _y, &x, &y);
949
950 if (x<0) x+=INT2FIX(_this->width);
951 if (y<0) y+=INT2FIX(_this->height);
952
953 /*bilinear filtering - disabled (too slow and not precise enough)*/
954 #if USE_BILINEAR
955 if (_this->filter==GF_TEXTURE_FILTER_HIGH_QUALITY) {
956 u64 p00, p01, p10, p11;
957 s32 x1, y1;
958 u8 tx, ty;
959
960 tx = FIX2INT(gf_muldiv(x, 255, _this->width) );
961 ty = FIX2INT(gf_muldiv(y, 255, _this->height) );
962
963 if (tx>120 || ty>120) {
964 x1 = (x0+incx);
965 if (x1<0) {
966 while (x1<0) x1 += _this->width;
967 } else {
968 x1 = x1 % _this->width;
969 }
970 y1 = (y0+incy);
971 if (y1<0) {
972 while (y1<0) y1+=_this->height;
973 } else {
974 y1 = y1 % _this->height;
975 }
976 if (incx>0) {
977 if (x1<x0) tx = 255-tx;
978 } else {
979 if (x1>x0) tx = 255-tx;
980 }
981 if (incy>0) {
982 if (y1<y0) ty = 255-ty;
983 } else {
984 if (y1>y0) ty = 255-ty;
985 }
986
987 p00 = pix;
988 if (_this->tx_get_pixel_wide) {
989 p01 = _this->tx_get_pixel_wide(_this, x1, y0);
990 p10 = _this->tx_get_pixel_wide(_this, x0, y1);
991 p11 = _this->tx_get_pixel_wide(_this, x1, y1);
992 } else {
993 p01 = evg_col_to_wide(_this->tx_get_pixel(_this, x1, y0) );
994 p10 = evg_col_to_wide(_this->tx_get_pixel(_this, x0, y1) );
995 p11 = evg_col_to_wide(_this->tx_get_pixel(_this, x1, y1) );
996 }
997 p00 = EVG_LERP_WIDE(p00, p01, tx);
998 p10 = EVG_LERP_WIDE(p10, p11, tx);
999 pix = EVG_LERP_WIDE(p00, p10, ty);
1000 }
1001 }
1002 #endif
1003
1004 if (has_alpha) {
1005 u64 _a = (pix>>48)&0xFF;
1006 _a = (_a * _this->alpha) >> 8;
1007 _a<<=48;
1008 pix = ( (_a & 0xFFFF000000000000UL) ) | (pix & 0x0000FFFFFFFFFFFFUL);
1009 }
1010 if (has_replace_cmat) {
1011 u64 _a = (pix>>48)&0xFF;
1012 _a = (_a * _this->alpha) >> 8;
1013 _a = (u64) (_this->cmat.m[18] * _a);
1014 _a<<=48;
1015 pix = ( (_a & 0xFFFF000000000000UL) ) | (replace_col & 0x0000FFFFFFFFFFFFUL);
1016 }
1017 //move pixel to target pixel format, applying color transform matrix
1018 else if (_this->is_yuv) {
1019 //if surf is rgb, transform
1020 if (!surf->yuv_type) {
1021 pix = gf_evg_ayuv_to_argb_wide(surf, pix);
1022 //apply cmat
1023 if (has_cmat)
1024 pix = gf_cmx_apply_wide(&_this->cmat, pix);
1025 } else if (has_cmat) {
1026 //yuv->yuv , use color matrix in yuv domain
1027 //this is equivalent to gf_evg_ayuv_to_argb, gf_cmx_apply(&_this->cmat, pix), gf_evg_argb_to_ayuv
1028 pix = gf_cmx_apply_wide(&_this->yuv_cmat, pix);
1029 }
1030 }
1031 //texture is RGB
1032 else {
1033 //apply cmat
1034 if (has_cmat)
1035 pix = gf_cmx_apply_wide(&_this->cmat, pix);
1036
1037 //dest is yuv, transform
1038 if (surf->yuv_type)
1039 pix = gf_evg_argb_to_ayuv_wide(surf, pix);
1040 }
1041
1042 *data++ = pix;
1043 count--;
1044 }
1045 }
1046
1047
1048 /*just a little faster...*/
tex_fill_run_straight_wide(GF_EVGStencil * p,GF_EVGSurface * surf,s32 _x,s32 _y,u32 count)1049 static void tex_fill_run_straight_wide(GF_EVGStencil *p, GF_EVGSurface *surf, s32 _x, s32 _y, u32 count)
1050 {
1051 s32 x0, y0;
1052 u64 pix;
1053 Bool repeat_s = GF_FALSE;
1054 Fixed x, y, _fdim;
1055 u64 *data = surf->stencil_pix_run;
1056 EVG_Texture *_this = (EVG_Texture *) p;
1057
1058 if (_this->tx_callback && _this->tx_callback_screen_coords) {
1059 tex_fill_run_callback_wide(_this, surf, _x, _y, count);
1060 return;
1061 }
1062
1063 /*get texture coords in FIXED - offset*/
1064 x = _this->smat.m[0]*_x + _this->smat.m[2];
1065 y = _this->smat.m[4]*_y + _this->smat.m[5];
1066
1067 /*we may have a numerical stability issues, try to figure out whether we are close from 0 or width/height*/
1068 if (ABS(x)< FIX_ONE/10) {
1069 Fixed test = _this->smat.m[0]*(_x+1) + _this->smat.m[2];
1070 if (test<0) x = INT2FIX(_this->width - 1);
1071 else x = 0;
1072 }
1073 if (ABS(y)< FIX_ONE/10) {
1074 Fixed test = _this->smat.m[4]*(_y+1) + _this->smat.m[5];
1075 if (test<0) y = INT2FIX(_this->height - 1);
1076 else y = 0;
1077 }
1078
1079 /* and move in absolute coords*/
1080 _fdim = INT2FIX(_this->width);
1081 repeat_s = (_this->mod & GF_TEXTURE_REPEAT_S);
1082 if (!repeat_s && (x <- _fdim)) x=0;
1083 while (x<0) x += _fdim;
1084
1085 _fdim = INT2FIX(_this->height);
1086 if (!(_this->mod & GF_TEXTURE_REPEAT_T) && (y <- _fdim)) y = 0;
1087 while (y<0) y += _fdim;
1088
1089 y0 = FIX2INT(y);
1090 y0 = y0 % _this->height;
1091
1092 while (count) {
1093 x0 = FIX2INT(x);
1094 if (repeat_s) {
1095 x0 = (x0) % _this->width;
1096 } else if (x0 >= (s32) _this->width) x0 = _this->width-1;
1097
1098 x += _this->inc_x;
1099
1100 if (_this->tx_get_pixel_wide) {
1101 pix = _this->tx_get_pixel_wide(_this, x0, y0);
1102 } else {
1103 pix = evg_col_to_wide( _this->tx_get_pixel(_this, x0, y0) );
1104 }
1105
1106 //replace_col is in destination format
1107 if (_this->replace_col) {
1108 u64 _a = (pix>>48)&0xFF;
1109 _a = (_a * _this->alpha) >> 8;
1110 _a<<=48;
1111 pix = ( (_a & 0xFFFF000000000000UL) ) | (_this->replace_col & 0x0000FFFFFFFFFFFFUL);
1112 }
1113 //move pixel to target pixel format
1114 else if (_this->is_yuv && !surf->yuv_type) {
1115 pix = gf_evg_ayuv_to_argb_wide(surf, pix);
1116 }
1117 else if (!_this->is_yuv && surf->yuv_type) {
1118 pix = gf_evg_argb_to_ayuv_wide(surf, pix);
1119 }
1120
1121 *data++ = pix;
1122 count--;
1123 }
1124 }
1125
evg_texture_brush()1126 GF_EVGStencil *evg_texture_brush()
1127 {
1128 EVG_Texture *tmp;
1129 GF_SAFEALLOC(tmp, EVG_Texture);
1130 if (!tmp) return 0L;
1131
1132 tmp->fill_run = tex_fill_run;
1133 tmp->type = GF_STENCIL_TEXTURE;
1134 /*default is using the surface settings*/
1135 gf_evg_stencil_set_filter( (GF_EVGStencil *) tmp, GF_TEXTURE_FILTER_DEFAULT);
1136 tmp->mod = 0;
1137 gf_cmx_init(&tmp->cmat);
1138 tmp->alpha = 255;
1139 return (GF_EVGStencil *) tmp;
1140 }
1141
1142
get_pix_argb(EVG_Texture * _this,u32 x,u32 y)1143 u32 get_pix_argb(EVG_Texture *_this, u32 x, u32 y)
1144 {
1145 char *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1146 return GF_COL_ARGB(*(pix) & 0xFF, *(pix+1) & 0xFF, *(pix+2) & 0xFF, *(pix+3) & 0xFF);
1147 }
get_pix_rgba(EVG_Texture * _this,u32 x,u32 y)1148 u32 get_pix_rgba(EVG_Texture *_this, u32 x, u32 y)
1149 {
1150 char *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1151 return GF_COL_ARGB(*(pix+3) & 0xFF, *(pix) & 0xFF, *(pix+1) & 0xFF, *(pix+2) & 0xFF);
1152 }
get_pix_abgr(EVG_Texture * _this,u32 x,u32 y)1153 u32 get_pix_abgr(EVG_Texture *_this, u32 x, u32 y)
1154 {
1155 char *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1156 return GF_COL_ARGB(*(pix) & 0xFF, *(pix+3) & 0xFF, *(pix+2) & 0xFF, *(pix+1) & 0xFF);
1157 }
get_pix_bgra(EVG_Texture * _this,u32 x,u32 y)1158 u32 get_pix_bgra(EVG_Texture *_this, u32 x, u32 y)
1159 {
1160 char *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1161 return GF_COL_ARGB(*(pix+3) & 0xFF, *(pix+2) & 0xFF, *(pix+1) & 0xFF, *(pix) & 0xFF);
1162 }
get_pix_rgbx(EVG_Texture * _this,u32 x,u32 y)1163 u32 get_pix_rgbx(EVG_Texture *_this, u32 x, u32 y)
1164 {
1165 char *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1166 return GF_COL_ARGB(0xFF, *(pix) & 0xFF, *(pix+1) & 0xFF, *(pix+2) & 0xFF);
1167 }
get_pix_xrgb(EVG_Texture * _this,u32 x,u32 y)1168 u32 get_pix_xrgb(EVG_Texture *_this, u32 x, u32 y)
1169 {
1170 char *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1171 return GF_COL_ARGB(0xFF, *(pix+1) & 0xFF, *(pix+2) & 0xFF, *(pix+3) & 0xFF);
1172 }
get_pix_xbgr(EVG_Texture * _this,u32 x,u32 y)1173 u32 get_pix_xbgr(EVG_Texture *_this, u32 x, u32 y)
1174 {
1175 char *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1176 return GF_COL_ARGB(0xFF, *(pix+3) & 0xFF, *(pix+2) & 0xFF, *(pix+1) & 0xFF);
1177 }
get_pix_bgrx(EVG_Texture * _this,u32 x,u32 y)1178 u32 get_pix_bgrx(EVG_Texture *_this, u32 x, u32 y)
1179 {
1180 char *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1181 return GF_COL_ARGB(0xFF, *(pix+2) & 0xFF, *(pix+1) & 0xFF, *(pix) & 0xFF);
1182 }
get_pix_rgb_24(EVG_Texture * _this,u32 x,u32 y)1183 u32 get_pix_rgb_24(EVG_Texture *_this, u32 x, u32 y)
1184 {
1185 char *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1186 return GF_COL_ARGB(0xFF, *pix & 0xFF, *(pix+1) & 0xFF, *(pix+2) & 0xFF);
1187 }
get_pix_bgr_24(EVG_Texture * _this,u32 x,u32 y)1188 u32 get_pix_bgr_24(EVG_Texture *_this, u32 x, u32 y)
1189 {
1190 char *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1191 return GF_COL_ARGB(0xFF, *(pix+2) & 0xFF, * (pix+1) & 0xFF, *pix & 0xFF);
1192 }
get_pix_444(EVG_Texture * _this,u32 x,u32 y)1193 u32 get_pix_444(EVG_Texture *_this, u32 x, u32 y)
1194 {
1195 u8 *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1196 u32 r = pix[0]&0x0f;
1197 u32 g = (pix[1]>>4)&0x0f;
1198 u32 b = pix[1]&0x0f;
1199 return GF_COL_ARGB(0xFF, (r << 4), (g << 4), (b << 4));
1200 }
get_pix_555(EVG_Texture * _this,u32 x,u32 y)1201 u32 get_pix_555(EVG_Texture *_this, u32 x, u32 y)
1202 {
1203 u8 *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1204 u32 r = (pix[0]>>2) & 0x1f;
1205 u32 g = (pix[0])&0x3;
1206 g<<=3;
1207 g |= (pix[1]>>5) & 0x7;
1208 u32 b = pix[1] & 0x1f;
1209 return GF_COL_ARGB(0xFF, (r << 3), (g << 3), (b << 3));
1210 }
get_pix_565(EVG_Texture * _this,u32 x,u32 y)1211 u32 get_pix_565(EVG_Texture *_this, u32 x, u32 y)
1212 {
1213 char *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1214 u32 r = (pix[0]>>3) & 0x1f;
1215 u32 g = (pix[0])&0x7;
1216 g<<=3;
1217 g |= (pix[1]>>5) & 0x7;
1218 u32 b = pix[1] & 0x1f;
1219 return GF_COL_ARGB(0xFF, (r << 3), (g << 2), (b << 3));
1220 }
get_pix_grey(EVG_Texture * _this,u32 x,u32 y)1221 u32 get_pix_grey(EVG_Texture *_this, u32 x, u32 y)
1222 {
1223 char *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1224 u8 val = *pix;
1225 return GF_COL_ARGB(0xFF, val, val, val);
1226 }
get_pix_alphagrey(EVG_Texture * _this,u32 x,u32 y)1227 u32 get_pix_alphagrey(EVG_Texture *_this, u32 x, u32 y)
1228 {
1229 u8 a, g;
1230 char *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1231 a = *pix;
1232 g = *(pix+1);
1233 return GF_COL_ARGB(a, g, g, g);
1234 }
get_pix_greyalpha(EVG_Texture * _this,u32 x,u32 y)1235 u32 get_pix_greyalpha(EVG_Texture *_this, u32 x, u32 y)
1236 {
1237 u8 a, g;
1238 char *pix = _this->pixels + y * _this->stride + _this->Bpp*x;
1239 g = *pix;
1240 a = *(pix+1);
1241 return GF_COL_ARGB(a, g, g, g);
1242 }
get_pix_yuv420p(EVG_Texture * _this,u32 x,u32 y)1243 u32 get_pix_yuv420p(EVG_Texture *_this, u32 x, u32 y)
1244 {
1245 u8 *pY = _this->pixels + y * _this->stride + x;
1246 u8 *pU = _this->pix_u + y/2 * _this->stride/2 + x/2;
1247 u8 *pV = _this->pix_v + y/2 * _this->stride/2 + x/2;
1248 return GF_COL_ARGB(0xFF, *pY, *pU, *pV);
1249 }
1250
1251 #ifdef GPAC_BIG_ENDIAN
1252
1253 #define GET_LE_10BIT_AS_8(_ptr) ( (((u16)(_ptr)[1])<<8 | (u16)(_ptr)[0] ) >> 2 )
1254 #define GET_LE_10BIT_AS_16(_ptr) ( (((u16)(_ptr)[1])<<8 | (u16)(_ptr)[0] ) << 6 )
1255
1256 #define GET_BE_10BIT_AS_8(_ptr) ( (*(u16 *)(_ptr)) >> 2 )
1257 #define GET_BE_10BIT_AS_16(_ptr) ( (*(u16 *)(_ptr)) << 6 )
1258
1259 #else
1260
1261 #define GET_LE_10BIT_AS_8(_ptr) ( (*(u16 *)(_ptr)) >> 2 )
1262 #define GET_LE_10BIT_AS_16(_ptr) ( (*(u16 *)(_ptr)) << 6 )
1263
1264 #define GET_BE_10BIT_AS_8(_ptr) ( (((u16)(_ptr)[0])<<8 | (u16)(_ptr)[1] ) >> 2 )
1265 #define GET_BE_10BIT_AS_16(_ptr) ( (((u16)(_ptr)[0])<<8 | (u16)(_ptr)[1] ) << 6 )
1266
1267 #endif
1268
1269
get_pix_yuv420p_10(EVG_Texture * _this,u32 x,u32 y)1270 u32 get_pix_yuv420p_10(EVG_Texture *_this, u32 x, u32 y)
1271 {
1272 u8 vy, vu, vv;
1273 u8 *pY = _this->pixels + y * _this->stride + x*2;
1274 u8 *pU = _this->pix_u + y/2 * _this->stride/2 + (x/2)*2;
1275 u8 *pV = _this->pix_v + y/2 * _this->stride/2 + (x/2)*2;
1276
1277 vy = GET_LE_10BIT_AS_8(pY);
1278 vu = GET_LE_10BIT_AS_8(pU);
1279 vv = GET_LE_10BIT_AS_8(pV);
1280
1281 return GF_COL_ARGB(0xFF, vy, vu, vv);
1282 }
1283
get_pix_yuv420p_10_wide(EVG_Texture * _this,u32 x,u32 y)1284 u64 get_pix_yuv420p_10_wide(EVG_Texture *_this, u32 x, u32 y)
1285 {
1286 u16 vy, vu, vv;
1287 u8 *pY = _this->pixels + y * _this->stride + x*2;
1288 u8 *pU = _this->pix_u + y/2 * _this->stride/2 + (x/2)*2;
1289 u8 *pV = _this->pix_v + y/2 * _this->stride/2 + (x/2)*2;
1290
1291 vy = GET_LE_10BIT_AS_16(pY);
1292 vu = GET_LE_10BIT_AS_16(pU);
1293 vv = GET_LE_10BIT_AS_16(pV);
1294
1295 return evg_make_col_wide(0xFFFF, vy, vu, vv);
1296 }
get_pix_yuv420p_a(EVG_Texture * _this,u32 x,u32 y)1297 u32 get_pix_yuv420p_a(EVG_Texture *_this, u32 x, u32 y)
1298 {
1299 u8 *pY = _this->pixels + y * _this->stride + x;
1300 u8 *pU = _this->pix_u + y/2 * _this->stride/2 + x/2;
1301 u8 *pV = _this->pix_v + y/2 * _this->stride/2 + x/2;
1302 u8 *pA = _this->pix_a + y * _this->stride + x;
1303
1304 return GF_COL_ARGB(*pA, *pY, *pU, *pV);
1305 }
get_pix_yuv422p(EVG_Texture * _this,u32 x,u32 y)1306 u32 get_pix_yuv422p(EVG_Texture *_this, u32 x, u32 y)
1307 {
1308 u8 *pY = _this->pixels + y * _this->stride + x;
1309 u8 *pU = _this->pix_u + y * _this->stride/2 + x/2;
1310 u8 *pV = _this->pix_v + y * _this->stride/2 + x/2;
1311 return GF_COL_ARGB(0xFF, *pY, *pU, *pV);
1312 }
get_pix_yuv422p_10(EVG_Texture * _this,u32 x,u32 y)1313 u32 get_pix_yuv422p_10(EVG_Texture *_this, u32 x, u32 y)
1314 {
1315 u8 vy, vu, vv;
1316 u8 *pY = _this->pixels + y * _this->stride + x*2;
1317 u8 *pU = _this->pix_u + y * _this->stride/2 + (x/2)*2;
1318 u8 *pV = _this->pix_v + y * _this->stride/2 + (x/2)*2;
1319
1320 vy = GET_LE_10BIT_AS_8(pY);
1321 vu = GET_LE_10BIT_AS_8(pU);
1322 vv = GET_LE_10BIT_AS_8(pV);
1323 return GF_COL_ARGB(0xFF, vy, vu, vv);
1324 }
1325
get_pix_yuv422p_10_wide(EVG_Texture * _this,u32 x,u32 y)1326 u64 get_pix_yuv422p_10_wide(EVG_Texture *_this, u32 x, u32 y)
1327 {
1328 u16 vy, vu, vv;
1329 u8 *pY = _this->pixels + y * _this->stride + x*2;
1330 u8 *pU = _this->pix_u + y * _this->stride/2 + (x/2)*2;
1331 u8 *pV = _this->pix_v + y * _this->stride/2 + (x/2)*2;
1332
1333 vy = GET_LE_10BIT_AS_16(pY);
1334 vu = GET_LE_10BIT_AS_16(pU);
1335 vv = GET_LE_10BIT_AS_16(pV);
1336 return evg_make_col_wide(0xFFFF, vy, vu, vv);
1337 }
1338
get_pix_yuv444p(EVG_Texture * _this,u32 x,u32 y)1339 u32 get_pix_yuv444p(EVG_Texture *_this, u32 x, u32 y)
1340 {
1341 u8 *pY = _this->pixels + y * _this->stride + x;
1342 u8 *pU = _this->pix_u + y * _this->stride + x;
1343 u8 *pV = _this->pix_v + y * _this->stride + x;
1344 return GF_COL_ARGB(0xFF, *pY, *pU, *pV);
1345 }
get_pix_yuv444p_10(EVG_Texture * _this,u32 x,u32 y)1346 u32 get_pix_yuv444p_10(EVG_Texture *_this, u32 x, u32 y)
1347 {
1348 u8 vy, vu, vv;
1349 u8 *pY = _this->pixels + y * _this->stride + x*2;
1350 u8 *pU = _this->pix_u + y * _this->stride + x*2;
1351 u8 *pV = _this->pix_v + y * _this->stride + x*2;
1352
1353 vy = GET_LE_10BIT_AS_8(pY);
1354 vu = GET_LE_10BIT_AS_8(pU);
1355 vv = GET_LE_10BIT_AS_8(pV);
1356 return GF_COL_ARGB(0xFF, vy, vu, vv);
1357 }
get_pix_yuv444p_10_wide(EVG_Texture * _this,u32 x,u32 y)1358 u64 get_pix_yuv444p_10_wide(EVG_Texture *_this, u32 x, u32 y)
1359 {
1360 u16 vy, vu, vv;
1361 u8 *pY = _this->pixels + y * _this->stride + x*2;
1362 u8 *pU = _this->pix_u + y * _this->stride + x*2;
1363 u8 *pV = _this->pix_v + y * _this->stride + x*2;
1364
1365 vy = GET_LE_10BIT_AS_16(pY);
1366 vu = GET_LE_10BIT_AS_16(pU);
1367 vv = GET_LE_10BIT_AS_16(pV);
1368 return evg_make_col_wide(0xFFFF, vy, vu, vv);
1369 }
get_pix_yuv444p_a(EVG_Texture * _this,u32 x,u32 y)1370 u32 get_pix_yuv444p_a(EVG_Texture *_this, u32 x, u32 y)
1371 {
1372 u8 *pY = _this->pixels + y * _this->stride + x;
1373 u8 *pU = _this->pix_u + y * _this->stride + x;
1374 u8 *pV = _this->pix_v + y * _this->stride + x;
1375 u8 *pA = _this->pix_a + y * _this->stride + x;
1376 return GF_COL_ARGB(*pA, *pY, *pU, *pV);
1377 }
get_pix_yuv_nv12(EVG_Texture * _this,u32 x,u32 y)1378 u32 get_pix_yuv_nv12(EVG_Texture *_this, u32 x, u32 y)
1379 {
1380 u8 *pY = _this->pixels + y * _this->stride + x;
1381 u8 *pU = _this->pix_u + y/2 * _this->stride + (x/2)*2;
1382 return GF_COL_ARGB(0xFF, *pY, *pU, *(pU+1));
1383 }
1384
get_pix_yuv_nv12_10(EVG_Texture * _this,u32 x,u32 y)1385 u32 get_pix_yuv_nv12_10(EVG_Texture *_this, u32 x, u32 y)
1386 {
1387 u16 vy, vu, vv;
1388 u8 *pY = _this->pixels + y * _this->stride + x*2;
1389 u8 *pU = _this->pix_u + y/2 * _this->stride + (x/2)*4;
1390 vy = GET_LE_10BIT_AS_8(pY);
1391 vu = GET_LE_10BIT_AS_8(pU);
1392 vv = GET_LE_10BIT_AS_8(pU+2);
1393
1394 return GF_COL_ARGB(0xFF, vy, vu, vv);
1395 }
get_pix_yuv_nv12_10_wide(EVG_Texture * _this,u32 x,u32 y)1396 u64 get_pix_yuv_nv12_10_wide(EVG_Texture *_this, u32 x, u32 y)
1397 {
1398 u16 vy, vu, vv;
1399 u8 *pY = _this->pixels + y * _this->stride + x*2;
1400 u8 *pU = _this->pix_u + y/2 * _this->stride + (x/2)*4;
1401
1402 vy = GET_LE_10BIT_AS_16(pY);
1403 vu = GET_LE_10BIT_AS_16(pU);
1404 vv = GET_LE_10BIT_AS_16(pU+2);
1405
1406 return evg_make_col_wide(0xFFFF, vy, vu, vv);
1407 }
get_pix_yuv_nv21(EVG_Texture * _this,u32 x,u32 y)1408 u32 get_pix_yuv_nv21(EVG_Texture *_this, u32 x, u32 y)
1409 {
1410 u8 *pY = _this->pixels + y * _this->stride + x;
1411 u8 *pU = _this->pix_u + y/2 * _this->stride + (x/2)*2;
1412 return GF_COL_ARGB(0xFF, *pY, *(pU+1), *pU);
1413 }
get_pix_yuv_nv21_10(EVG_Texture * _this,u32 x,u32 y)1414 u32 get_pix_yuv_nv21_10(EVG_Texture *_this, u32 x, u32 y)
1415 {
1416 u8 vy, vu, vv;
1417 u8 *pY = _this->pixels + y * _this->stride + x*2;
1418 u8 *pU = _this->pix_u + y/2 * _this->stride + (x/2)*4;
1419
1420 vy = GET_LE_10BIT_AS_8(pY);
1421 vu = GET_LE_10BIT_AS_8(pU);
1422 vv = GET_LE_10BIT_AS_8(pU+2);
1423
1424 return GF_COL_ARGB(0xFF, vy, vv, vu);
1425 }
get_pix_yuv_nv21_10_wide(EVG_Texture * _this,u32 x,u32 y)1426 u64 get_pix_yuv_nv21_10_wide(EVG_Texture *_this, u32 x, u32 y)
1427 {
1428 u16 vy, vu, vv;
1429 u8 *pY = _this->pixels + y * _this->stride + x*2;
1430 u8 *pU = _this->pix_u + y/2 * _this->stride + (x/2)*4;
1431
1432 vy = GET_LE_10BIT_AS_16(pY);
1433 vu = GET_LE_10BIT_AS_16(pU);
1434 vv = GET_LE_10BIT_AS_16(pU+2);
1435 return evg_make_col_wide(0xFFFF, vy, vv, vu);
1436 }
get_pix_yuyv(EVG_Texture * _this,u32 x,u32 y)1437 u32 get_pix_yuyv(EVG_Texture *_this, u32 x, u32 y)
1438 {
1439 u8 *pY = _this->pixels + y * _this->stride + (x/2)*4;
1440 u8 u = pY[1];
1441 u8 v = pY[3];
1442 u8 luma = (x%2) ? pY[2] : pY[0];
1443 return GF_COL_ARGB(0xFF, luma, u, v);
1444 }
get_pix_yvyu(EVG_Texture * _this,u32 x,u32 y)1445 u32 get_pix_yvyu(EVG_Texture *_this, u32 x, u32 y)
1446 {
1447 u8 *pY = _this->pixels + y * _this->stride + (x/2)*4;
1448 u8 u = pY[3];
1449 u8 v = pY[1];
1450 u8 luma = (x%2) ? pY[2] : pY[0];
1451 return GF_COL_ARGB(0xFF, luma, u, v);
1452 }
get_pix_uyvy(EVG_Texture * _this,u32 x,u32 y)1453 u32 get_pix_uyvy(EVG_Texture *_this, u32 x, u32 y)
1454 {
1455 u8 *pY = _this->pixels + y * _this->stride + (x/2)*4;
1456 u8 u = pY[0];
1457 u8 v = pY[2];
1458 u8 luma = (x%2) ? pY[3] : pY[1];
1459 return GF_COL_ARGB(0xFF, luma, u, v);
1460 }
get_pix_vyuy(EVG_Texture * _this,u32 x,u32 y)1461 u32 get_pix_vyuy(EVG_Texture *_this, u32 x, u32 y)
1462 {
1463 u8 *pY = _this->pixels + y * _this->stride + (x/2)*4;
1464 u8 u = pY[2];
1465 u8 v = pY[0];
1466 u8 luma = (x%2) ? pY[3] : pY[1];
1467 return GF_COL_ARGB(0xFF, luma, u, v);
1468 }
1469
texture_set_callbacks(EVG_Texture * _this)1470 static void texture_set_callbacks(EVG_Texture *_this)
1471 {
1472 if (_this->tx_callback)
1473 return;
1474 switch (_this->pixel_format) {
1475 case GF_PIXEL_RGBA:
1476 _this->tx_get_pixel = get_pix_rgba;
1477 return;
1478 case GF_PIXEL_ARGB:
1479 _this->tx_get_pixel = get_pix_argb;
1480 return;
1481 case GF_PIXEL_ABGR:
1482 _this->tx_get_pixel = get_pix_abgr;
1483 return;
1484 case GF_PIXEL_BGRA:
1485 _this->tx_get_pixel = get_pix_bgra;
1486 return;
1487 case GF_PIXEL_RGBX:
1488 _this->tx_get_pixel = get_pix_rgbx;
1489 return;
1490 case GF_PIXEL_BGRX:
1491 _this->tx_get_pixel = get_pix_bgrx;
1492 return;
1493 case GF_PIXEL_XRGB:
1494 _this->tx_get_pixel = get_pix_xrgb;
1495 return;
1496 case GF_PIXEL_XBGR:
1497 _this->tx_get_pixel = get_pix_xbgr;
1498 return;
1499 case GF_PIXEL_RGB:
1500 _this->tx_get_pixel = get_pix_rgb_24;
1501 return;
1502 case GF_PIXEL_BGR:
1503 _this->tx_get_pixel = get_pix_bgr_24;
1504 return;
1505 case GF_PIXEL_RGB_444:
1506 _this->tx_get_pixel = get_pix_444;
1507 return;
1508 case GF_PIXEL_RGB_555:
1509 _this->tx_get_pixel = get_pix_555;
1510 return;
1511 case GF_PIXEL_RGB_565:
1512 _this->tx_get_pixel = get_pix_565;
1513 return;
1514 case GF_PIXEL_GREYSCALE:
1515 _this->tx_get_pixel = get_pix_grey;
1516 return;
1517 case GF_PIXEL_ALPHAGREY:
1518 _this->tx_get_pixel = get_pix_alphagrey;
1519 return;
1520 case GF_PIXEL_GREYALPHA:
1521 _this->tx_get_pixel = get_pix_greyalpha;
1522 return;
1523 case GF_PIXEL_YUV:
1524 _this->tx_get_pixel = get_pix_yuv420p;
1525 break;
1526 case GF_PIXEL_YUVA:
1527 _this->tx_get_pixel = get_pix_yuv420p_a;
1528 break;
1529 case GF_PIXEL_YUV422:
1530 _this->tx_get_pixel = get_pix_yuv422p;
1531 break;
1532 case GF_PIXEL_YUV444:
1533 _this->tx_get_pixel = get_pix_yuv444p;
1534 break;
1535 case GF_PIXEL_YUVA444:
1536 _this->tx_get_pixel = get_pix_yuv444p_a;
1537 break;
1538 case GF_PIXEL_NV12:
1539 _this->tx_get_pixel = get_pix_yuv_nv12;
1540 break;
1541 case GF_PIXEL_NV21:
1542 _this->tx_get_pixel = get_pix_yuv_nv21;
1543 break;
1544 case GF_PIXEL_YUYV:
1545 _this->tx_get_pixel = get_pix_yuyv;
1546 return;
1547 case GF_PIXEL_YVYU:
1548 _this->tx_get_pixel = get_pix_yvyu;
1549 return;
1550 case GF_PIXEL_UYVY:
1551 _this->tx_get_pixel = get_pix_uyvy;
1552 return;
1553 case GF_PIXEL_VYUY:
1554 _this->tx_get_pixel = get_pix_vyuy;
1555 return;
1556 case GF_PIXEL_YUV_10:
1557 _this->tx_get_pixel = get_pix_yuv420p_10;
1558 _this->tx_get_pixel_wide = get_pix_yuv420p_10_wide;
1559 break;
1560 case GF_PIXEL_YUV422_10:
1561 _this->tx_get_pixel = get_pix_yuv422p_10;
1562 _this->tx_get_pixel_wide = get_pix_yuv422p_10_wide;
1563 break;
1564 case GF_PIXEL_YUV444_10:
1565 _this->tx_get_pixel = get_pix_yuv444p_10;
1566 _this->tx_get_pixel_wide = get_pix_yuv444p_10_wide;
1567 break;
1568 case GF_PIXEL_NV12_10:
1569 _this->tx_get_pixel = get_pix_yuv_nv12_10;
1570 _this->tx_get_pixel_wide = get_pix_yuv_nv12_10_wide;
1571 break;
1572 case GF_PIXEL_NV21_10:
1573 _this->tx_get_pixel = get_pix_yuv_nv21_10;
1574 _this->tx_get_pixel_wide = get_pix_yuv_nv21_10_wide;
1575 break;
1576 default:
1577 return;
1578 }
1579 //assign image planes
1580 if (_this->pix_u) return;
1581
1582 switch (_this->pixel_format) {
1583 case GF_PIXEL_YUV_10:
1584 case GF_PIXEL_YUV:
1585 if (!_this->stride_uv) _this->stride_uv = _this->stride/2;
1586 _this->pix_u = _this->pixels + _this->stride*_this->height;
1587 _this->pix_v = _this->pix_u + _this->stride_uv * _this->height/2;
1588 return;
1589 case GF_PIXEL_YUVA:
1590 if (!_this->stride_uv) _this->stride_uv = _this->stride/2;
1591 _this->pix_u = _this->pixels + _this->stride*_this->height;
1592 _this->pix_v = _this->pix_u + _this->stride_uv * _this->height/2;
1593 _this->pix_a = _this->pix_v + _this->stride_uv * _this->height/2;
1594 return;
1595 case GF_PIXEL_YUV422_10:
1596 case GF_PIXEL_YUV422:
1597 if (!_this->stride_uv) _this->stride_uv = _this->stride/2;
1598 _this->pix_u = _this->pixels + _this->stride*_this->height;
1599 _this->pix_v = _this->pix_u + _this->stride_uv * _this->height;
1600 return;
1601 case GF_PIXEL_YUV444_10:
1602 case GF_PIXEL_YUV444:
1603 if (!_this->stride_uv) _this->stride_uv = _this->stride;
1604 _this->pix_u = _this->pixels + _this->stride*_this->height;
1605 _this->pix_v = _this->pix_u + _this->stride_uv * _this->height;
1606 return;
1607 case GF_PIXEL_YUVA444:
1608 if (!_this->stride_uv) _this->stride_uv = _this->stride;
1609 _this->pix_u = _this->pixels + _this->stride*_this->height;
1610 _this->pix_v = _this->pix_u + _this->stride_uv * _this->height;
1611 _this->pix_a = _this->pix_v + _this->stride_uv * _this->height;
1612 return;
1613 case GF_PIXEL_NV12:
1614 case GF_PIXEL_NV21:
1615 case GF_PIXEL_NV12_10:
1616 case GF_PIXEL_NV21_10:
1617 if (!_this->stride_uv) _this->stride_uv = _this->stride;
1618 _this->pix_u = _this->pixels + _this->stride*_this->height;
1619 return;
1620 }
1621 }
1622
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)1623 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)
1624 {
1625 EVG_Texture *_this = (EVG_Texture *) st;
1626 if (!_this || (_this->type != GF_STENCIL_TEXTURE) || !pixels || !width || !height || _this->owns_texture)
1627 return GF_BAD_PARAM;
1628
1629 _this->pixels = NULL;
1630 _this->is_yuv = GF_FALSE;
1631
1632 switch (pixelFormat) {
1633 case GF_PIXEL_ARGB:
1634 case GF_PIXEL_RGBA:
1635 case GF_PIXEL_ABGR:
1636 case GF_PIXEL_BGRA:
1637 case GF_PIXEL_RGBX:
1638 case GF_PIXEL_XRGB:
1639 case GF_PIXEL_XBGR:
1640 case GF_PIXEL_BGRX:
1641 _this->Bpp = 4;
1642 break;
1643 case GF_PIXEL_RGB:
1644 case GF_PIXEL_BGR:
1645 _this->Bpp = 3;
1646 break;
1647 case GF_PIXEL_RGB_555:
1648 case GF_PIXEL_RGB_565:
1649 case GF_PIXEL_RGB_444:
1650 case GF_PIXEL_ALPHAGREY:
1651 case GF_PIXEL_GREYALPHA:
1652 _this->Bpp = 2;
1653 break;
1654 case GF_PIXEL_GREYSCALE:
1655 _this->Bpp = 1;
1656 break;
1657 case GF_PIXEL_YUV:
1658 case GF_PIXEL_NV12:
1659 case GF_PIXEL_NV21:
1660 case GF_PIXEL_YUV422:
1661 case GF_PIXEL_YUV444:
1662 case GF_PIXEL_YUVA:
1663 case GF_PIXEL_YUVA444:
1664 _this->is_yuv = GF_TRUE;
1665 _this->Bpp = 1;
1666 break;
1667 case GF_PIXEL_YUV_10:
1668 case GF_PIXEL_YUV422_10:
1669 case GF_PIXEL_YUV444_10:
1670 case GF_PIXEL_NV12_10:
1671 case GF_PIXEL_NV21_10:
1672 _this->is_yuv = GF_TRUE;
1673 _this->Bpp = 2;
1674 break;
1675 case GF_PIXEL_YUYV:
1676 case GF_PIXEL_YVYU:
1677 case GF_PIXEL_UYVY:
1678 case GF_PIXEL_VYUY:
1679 _this->is_yuv = GF_TRUE;
1680 _this->Bpp = 1;
1681 if (!stride)
1682 stride = 4 * width;
1683 break;
1684 default:
1685 return GF_NOT_SUPPORTED;
1686 }
1687 if (!stride)
1688 stride = _this->Bpp * width;
1689
1690 _this->pixel_format = pixelFormat;
1691 _this->width = width;
1692 _this->height = height;
1693 _this->stride = stride;
1694 _this->stride_uv = uv_stride;
1695 _this->stride_alpha = alpha_stride ? alpha_stride : stride;
1696 _this->pixels = (char *) pixels;
1697 _this->pix_u = (char *) u_plane;
1698 _this->pix_v = (char *) v_plane;
1699 texture_set_callbacks(_this);
1700 return GF_OK;
1701 }
1702
1703 GF_EXPORT
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)1704 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)
1705 {
1706 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);
1707 }
1708 GF_EXPORT
gf_evg_stencil_set_texture(GF_EVGStencil * stencil,u8 * pixels,u32 width,u32 height,u32 stride,GF_PixelFormat pixelFormat)1709 GF_Err gf_evg_stencil_set_texture(GF_EVGStencil *stencil, u8 *pixels, u32 width, u32 height, u32 stride, GF_PixelFormat pixelFormat)
1710 {
1711 return gf_evg_stencil_set_texture_internal(stencil, width, height, pixelFormat, pixels, stride, NULL, NULL, 0, NULL, 0);
1712 }
1713
1714 GF_EXPORT
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)1715 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)
1716 {
1717 EVG_Texture *_this = (EVG_Texture *) stencil;
1718 u8 data=0;
1719 GF_Err e;
1720 if (!callback) return GF_BAD_PARAM;
1721 e = gf_evg_stencil_set_texture_internal(stencil, width, height, pixelFormat, &data, width, NULL, NULL, 0, NULL, 0);
1722 if (e) return e;
1723 _this->pixels = NULL;
1724 _this->tx_get_pixel = evg_paramtx_get_pixel;
1725 _this->tx_get_pixel_wide = evg_paramtx_get_pixel_wide;
1726
1727 _this->tx_callback = callback;
1728 _this->tx_callback_udta = cbk_data;
1729 _this->tx_callback_screen_coords = use_screen_coords;
1730 return GF_OK;
1731 }
1732
evg_texture_init(GF_EVGStencil * p,GF_EVGSurface * surf)1733 void evg_texture_init(GF_EVGStencil *p, GF_EVGSurface *surf)
1734 {
1735 GF_Point2D p0, p1;
1736 EVG_Texture *_this = (EVG_Texture *) p;
1737
1738 p0.x = p0.y = p1.y = 0;
1739 p1.x = FIX_ONE;
1740 gf_mx2d_apply_point(&_this->smat, &p0);
1741 gf_mx2d_apply_point(&_this->smat, &p1);
1742 _this->inc_x = p1.x - p0.x;
1743 _this->inc_y = p1.y - p0.y;
1744
1745 _this->replace_col = 0;
1746 _this->cmat_is_replace = GF_FALSE;
1747 if (!_this->cmat.identity
1748 && !_this->cmat.m[0] && !_this->cmat.m[1] && !_this->cmat.m[2] && !_this->cmat.m[3]
1749 && !_this->cmat.m[5] && !_this->cmat.m[6] && !_this->cmat.m[7] && !_this->cmat.m[8]
1750 && !_this->cmat.m[10] && !_this->cmat.m[11] && !_this->cmat.m[12] && !_this->cmat.m[13]
1751 && !_this->cmat.m[15] && !_this->cmat.m[16] && !_this->cmat.m[17] && !_this->cmat.m[19]) {
1752 _this->cmat_is_replace = GF_TRUE;
1753 _this->replace_col = GF_COL_ARGB(FIX2INT(_this->cmat.m[18]*255), FIX2INT(_this->cmat.m[4]*255), FIX2INT(_this->cmat.m[9]*255), FIX2INT(_this->cmat.m[14]*255));
1754
1755 if (surf->yuv_type) {
1756 _this->replace_col = gf_evg_argb_to_ayuv(surf, _this->replace_col);
1757 }
1758 }
1759
1760 if ((_this->alpha == 255) && !_this->smat.m[1] && !_this->smat.m[3] && (_this->cmat.identity || _this->cmat_is_replace)) {
1761 if (surf->not_8bits) {
1762 _this->fill_run = tex_fill_run_straight_wide;
1763 } else {
1764 _this->fill_run = tex_fill_run_straight;
1765 }
1766 } else {
1767 if (!_this->cmat.identity && _this->is_yuv && surf->yuv_type) {
1768 evg_make_ayuv_color_mx(&_this->cmat, &_this->yuv_cmat);
1769 }
1770 if (surf->not_8bits) {
1771 _this->fill_run = tex_fill_run_wide;
1772 } else {
1773 _this->fill_run = tex_fill_run;
1774 }
1775 }
1776
1777 texture_set_callbacks(_this);
1778 }
1779
1780
1781
1782 GF_EXPORT
gf_evg_stencil_set_mapping(GF_EVGStencil * st,GF_TextureMapFlags mode)1783 GF_Err gf_evg_stencil_set_mapping(GF_EVGStencil * st, GF_TextureMapFlags mode)
1784 {
1785 EVG_Texture *_this = (EVG_Texture *) st;
1786 if (!_this || (_this->type != GF_STENCIL_TEXTURE)) return GF_BAD_PARAM;
1787 _this->mod = mode;
1788 return GF_OK;
1789 }
1790
1791 GF_EXPORT
gf_evg_stencil_set_filter(GF_EVGStencil * st,GF_TextureFilter filter_mode)1792 GF_Err gf_evg_stencil_set_filter(GF_EVGStencil * st, GF_TextureFilter filter_mode)
1793 {
1794 EVG_Texture *_this = (EVG_Texture *) st;
1795 if (!_this || (_this->type != GF_STENCIL_TEXTURE)) return GF_BAD_PARAM;
1796 _this->filter = filter_mode;
1797 return GF_OK;
1798 }
1799
1800 GF_EXPORT
gf_evg_stencil_set_color_matrix(GF_EVGStencil * st,GF_ColorMatrix * cmat)1801 GF_Err gf_evg_stencil_set_color_matrix(GF_EVGStencil * st, GF_ColorMatrix *cmat)
1802 {
1803 Bool is_grad;
1804 GF_EVGStencil *_this = (GF_EVGStencil *)st;
1805 if (!_this) return GF_BAD_PARAM;
1806 is_grad = ((_this->type==GF_STENCIL_LINEAR_GRADIENT) || (_this->type==GF_STENCIL_RADIAL_GRADIENT)) ? GF_TRUE : GF_FALSE;
1807
1808
1809 if (!cmat) {
1810 if (is_grad && !_this->cmat.identity)
1811 ((EVG_BaseGradient *) _this)->updated = 1;
1812 gf_cmx_init(&_this->cmat);
1813 } else {
1814 if (is_grad && memcmp(&_this->cmat.m, &cmat->m, sizeof(Fixed)*20))
1815 ((EVG_BaseGradient *) _this)->updated = 1;
1816 gf_cmx_copy(&_this->cmat, cmat);
1817 }
1818 return GF_OK;
1819 }
1820
gf_evg_stencil_get_pixel_intern(GF_EVGStencil * st,s32 x,s32 y,Bool want_yuv)1821 static u32 gf_evg_stencil_get_pixel_intern(GF_EVGStencil *st, s32 x, s32 y, Bool want_yuv)
1822 {
1823 u32 col;
1824 EVG_Texture *_this = (EVG_Texture *) st;
1825 if (!_this || (_this->type != GF_STENCIL_TEXTURE) || !_this->tx_get_pixel) return 0;
1826 if (x<0) x=0;
1827 else if ((u32) x>=_this->width) x = _this->width-1;
1828
1829 if (y<0) y=0;
1830 else if ((u32) y>=_this->height) y = _this->height-1;
1831
1832 col = _this->tx_get_pixel(_this, x, y);
1833 if (_this->is_yuv) {
1834 if (!want_yuv) return gf_evg_ayuv_to_argb(NULL, col);
1835 } else {
1836 if (want_yuv) return gf_evg_argb_to_ayuv(NULL, col);
1837 }
1838 return col;
1839 }
1840
1841 GF_EXPORT
gf_evg_stencil_get_pixel(GF_EVGStencil * st,s32 x,s32 y)1842 u32 gf_evg_stencil_get_pixel(GF_EVGStencil *st, s32 x, s32 y)
1843 {
1844 return gf_evg_stencil_get_pixel_intern(st, x, y, GF_FALSE);
1845 }
1846
1847 #if 0 //unused
1848 GF_EXPORT
1849 u32 gf_evg_stencil_get_pixel_yuv(GF_EVGStencil *st, s32 x, s32 y)
1850 {
1851 return gf_evg_stencil_get_pixel_intern(st, x, y, GF_TRUE);
1852 }
1853 #endif
1854
gf_evg_stencil_get_pixel_f_intern(EVG_Texture * _this,Float x,Float y,Float * r,Float * g,Float * b,Float * a,Bool want_yuv)1855 static GF_Err gf_evg_stencil_get_pixel_f_intern(EVG_Texture *_this, Float x, Float y, Float *r, Float *g, Float *b, Float *a, Bool want_yuv)
1856 {
1857 u32 col;
1858 if (!_this->tx_get_pixel) return GF_BAD_PARAM;
1859
1860 if (_this->mod & GF_TEXTURE_FLIP_X) x = -x;
1861 if (_this->mod & GF_TEXTURE_FLIP_Y) y = -y;
1862
1863 x*=_this->width;
1864 y*=_this->height;
1865 if (_this->mod & GF_TEXTURE_REPEAT_S) {
1866 while (x<0) x += _this->width;
1867 while (x>=_this->width) x -= _this->width;
1868 } else {
1869 if (x<0) x=0;
1870 else if (x>=_this->width) x = (Float)_this->width-1;
1871 }
1872
1873 if (_this->mod & GF_TEXTURE_REPEAT_T) {
1874 while (y<0) y += _this->height;
1875 while (y>=_this->height) y -= _this->height;
1876 } else {
1877 if (y<0) y=0;
1878 else if (y>=_this->height) y = (Float)_this->height-1;
1879 }
1880
1881 //10-bit or more texture, use wide and convert to float
1882 if (_this->tx_get_pixel_wide) {
1883 u64 colw;
1884 if (_this->filter==GF_TEXTURE_FILTER_HIGH_SPEED) {
1885 colw = _this->tx_get_pixel_wide(_this, (s32) x, (s32) y);
1886 } else {
1887 u32 _x = (u32) floor(x);
1888 u32 _y = (u32) floor(y);
1889 if (_this->filter==GF_TEXTURE_FILTER_MID) {
1890 if ((x - _x > 0.5) && _x+1<_this->width) _x++;
1891 if ((y - _y > 0.5) && _y+1<_this->height) _y++;
1892 colw = _this->tx_get_pixel_wide(_this, _x, _y);
1893 } else {
1894 u64 col01, col11, col10;
1895 s32 _x1 = _x+1;
1896 s32 _y1 = _y+1;
1897 u8 diff_x = (u8) (255 * (x - _x));
1898 u8 diff_y = (u8) (255 * (y - _y));
1899
1900 if ((u32)_x1>=_this->width) _x1 = _this->width-1;
1901 if ((u32)_y1>=_this->height) _y1 = _this->height-1;
1902 colw = _this->tx_get_pixel_wide(_this, _x, _y);
1903 col10 = _this->tx_get_pixel_wide(_this, _x1, _y);
1904 col01 = _this->tx_get_pixel_wide(_this, _x, _y1);
1905 col11 = _this->tx_get_pixel_wide(_this, _x1, _y1);
1906 colw = EVG_LERP_WIDE(colw, col10, diff_x);
1907 col11 = EVG_LERP_WIDE(col01, col11, diff_x);
1908 colw = EVG_LERP_WIDE(colw, col11, diff_y);
1909 }
1910 }
1911 if (_this->is_yuv) {
1912 if (!want_yuv) colw = gf_evg_ayuv_to_argb_wide(NULL, colw);
1913 } else {
1914 if (want_yuv) colw = gf_evg_argb_to_ayuv_wide(NULL, colw);
1915 }
1916
1917 *r = ((Float) GF_COLW_R(colw) ) / 0xFFFF;
1918 *g = ((Float) GF_COLW_G(colw) ) / 0xFFFF;
1919 *b = ((Float) GF_COLW_B(colw) ) / 0xFFFF;
1920 *a = ((Float) GF_COLW_A(colw) ) / 0xFFFF;
1921 return GF_OK;
1922 }
1923
1924 //8-bit texture, use regular and convert to float
1925 if (_this->filter==GF_TEXTURE_FILTER_HIGH_SPEED) {
1926 col = _this->tx_get_pixel(_this, (s32) x, (s32) y);
1927 } else {
1928 u32 _x = (u32) floor(x);
1929 u32 _y = (u32) floor(y);
1930 if (_this->filter==GF_TEXTURE_FILTER_MID) {
1931 if ((x - _x > 0.5) && _x+1<_this->width) _x++;
1932 if ((y - _y > 0.5) && _y+1<_this->height) _y++;
1933 col = _this->tx_get_pixel(_this, _x, _y);
1934 } else {
1935 u32 col01, col11, col10;
1936 s32 _x1 = _x+1;
1937 s32 _y1 = _y+1;
1938 u8 diff_x = (u8) (255 * (x - _x));
1939 u8 diff_y = (u8) (255 * (y - _y));
1940
1941 if ((u32)_x1>=_this->width) _x1 = _this->width-1;
1942 if ((u32)_y1>=_this->height) _y1 = _this->height-1;
1943 col = _this->tx_get_pixel(_this, _x, _y);
1944 col10 = _this->tx_get_pixel(_this, _x1, _y);
1945 col01 = _this->tx_get_pixel(_this, _x, _y1);
1946 col11 = _this->tx_get_pixel(_this, _x1, _y1);
1947 col = EVG_LERP(col, col10, diff_x);
1948 col11 = EVG_LERP(col01, col11, diff_x);
1949 col = EVG_LERP(col, col11, diff_y);
1950 }
1951 }
1952 if (_this->is_yuv) {
1953 if (!want_yuv) col = gf_evg_ayuv_to_argb(NULL, col);
1954 } else {
1955 if (want_yuv) col = gf_evg_argb_to_ayuv(NULL, col);
1956 }
1957 *r = ((Float) GF_COL_R(col) ) / 255.0f;
1958 *g = ((Float) GF_COL_G(col) ) / 255.0f;
1959 *b = ((Float) GF_COL_B(col) ) / 255.0f;
1960 *a = ((Float) GF_COL_A(col) ) / 255.0f;
1961 return GF_OK;
1962 }
1963
1964 GF_EXPORT
gf_evg_stencil_get_pixel_f(GF_EVGStencil * st,Float x,Float y,Float * r,Float * g,Float * b,Float * a)1965 GF_Err gf_evg_stencil_get_pixel_f(GF_EVGStencil *st, Float x, Float y, Float *r, Float *g, Float *b, Float *a)
1966 {
1967 EVG_Texture *_this = (EVG_Texture *) st;
1968 if (!_this || (_this->type != GF_STENCIL_TEXTURE)) return GF_BAD_PARAM;
1969 return gf_evg_stencil_get_pixel_f_intern(_this, x, y, r, g, b, a, GF_FALSE);
1970 }
1971
1972 GF_EXPORT
gf_evg_stencil_get_pixel_yuv_f(GF_EVGStencil * st,Float x,Float y,Float * r,Float * g,Float * b,Float * a)1973 GF_Err gf_evg_stencil_get_pixel_yuv_f(GF_EVGStencil *st, Float x, Float y, Float *r, Float *g, Float *b, Float *a)
1974 {
1975 EVG_Texture *_this = (EVG_Texture *) st;
1976 if (!_this || (_this->type != GF_STENCIL_TEXTURE)) return GF_BAD_PARAM;
1977 return gf_evg_stencil_get_pixel_f_intern(_this, x, y, r, g, b, a, GF_TRUE);
1978 }
1979
1980 GF_EXPORT
gf_evg_stencil_set_alpha(GF_EVGStencil * st,u8 alpha)1981 GF_Err gf_evg_stencil_set_alpha(GF_EVGStencil * st, u8 alpha)
1982 {
1983 EVG_Texture *_this = (EVG_Texture *)st;
1984 if (!_this) return GF_BAD_PARAM;
1985 if (_this->type==GF_STENCIL_SOLID) return GF_BAD_PARAM;
1986 if (_this->type==GF_STENCIL_TEXTURE)
1987 _this->alpha = alpha;
1988 else {
1989 if ( ((EVG_BaseGradient*)st)->alpha != alpha) {
1990 ((EVG_BaseGradient*)st)->updated = 1;
1991 }
1992 ((EVG_BaseGradient*)st)->alpha = alpha;
1993 }
1994 return GF_OK;
1995 }
1996
evg_fill_run(GF_EVGStencil * p,GF_EVGSurface * surf,s32 x,s32 y,u32 count)1997 void evg_fill_run(GF_EVGStencil *p, GF_EVGSurface *surf, s32 x, s32 y, u32 count)
1998 {
1999 p->fill_run(p, surf, x, y, count);
2000 if (surf->get_alpha) {
2001 u32 i;
2002 EVG_Texture *_p = (EVG_Texture *)p;
2003 if (_p->Bpp>8) {
2004 u64 *coll = (u64 *)surf->stencil_pix_run;
2005 for (i=0; i<count; i++) {
2006 u64 a = (*coll>>48)&0xFFFF;
2007 a = 0xFF * surf->get_alpha(surf->get_alpha_udta, (u8) (a/0xFF), x+i, y);
2008 *coll = (a<<48) | ((*coll) & 0x0000FFFFFFFFFFFFUL);
2009 coll ++;
2010 }
2011 } else {
2012 u32 *col = (u32 *)surf->stencil_pix_run;
2013 for (i=0; i<count; i++) {
2014 u8 a = GF_COL_A(*col);
2015 a = surf->get_alpha(surf->get_alpha_udta, a, x+i, y);
2016 *col = (a<<24) | ((*col) & 0x00FFFFFF);
2017 col ++;
2018 }
2019 }
2020 }
2021 }
2022