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