LCOV - code coverage report
Current view: top level - evg - stencil.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1015 1082 93.8 %
Date: 2021-04-29 23:48:07 Functions: 84 84 100.0 %

          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 : }

Generated by: LCOV version 1.13