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