Coverage Report

Created: 2026-10-08 07:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gpac/src/evg/surface.c
Line
Count
Source
1
/*
2
 *      GPAC - Multimedia Framework C SDK
3
 *
4
 *      Authors: Jean Le Feuvre
5
 *      Copyright (c) Telecom ParisTech 2000-2025
6
 *          All rights reserved
7
 *
8
 *  This file is part of GPAC / software 2D rasterizer module
9
 *
10
 *  GPAC is free software; you can redistribute it and/or modify
11
 *  it under the terms of the GNU Lesser General Public License as published by
12
 *  the Free Software Foundation; either version 2, or (at your option)
13
 *  any later version.
14
 *
15
 *  GPAC is distributed in the hope that it will be useful,
16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 *  GNU Lesser General Public License for more details.
19
 *
20
 *  You should have received a copy of the GNU Lesser General Public
21
 *  License along with this library; see the file COPYING.  If not, write to
22
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23
 *
24
 *
25
 */
26
27
28
#include "rast_soft.h"
29
30
#ifndef GPAC_DISABLE_EVG
31
32
static void get_surface_world_matrix(GF_EVGSurface *surf, GF_Matrix2D *mat)
33
0
{
34
0
  gf_mx2d_init(*mat);
35
0
  if (surf->center_coords) {
36
0
    gf_mx2d_add_scale(mat, FIX_ONE, -FIX_ONE);
37
0
    gf_mx2d_add_translation(mat, INT2FIX(surf->width / 2), INT2FIX(surf->height / 2));
38
0
  }
39
0
}
40
41
42
static GF_Err evg_raster_ctx_init(EVGRasterCtx *raster_ctx, GF_EVGSurface *surf)
43
0
{
44
0
  raster_ctx->max_gray_spans = raster_ctx->alloc_gray_spans = FT_MAX_GRAY_SPANS;
45
0
  raster_ctx->gray_spans = gf_malloc(sizeof(EVG_Span)* raster_ctx->max_gray_spans);
46
0
  if (!raster_ctx->gray_spans) return GF_OUT_OF_MEM;
47
0
  raster_ctx->surf = surf;
48
0
  return GF_OK;
49
0
}
50
51
static void evg_raster_ctx_uninit(EVGRasterCtx *raster_ctx)
52
0
{
53
0
  if (raster_ctx->gray_spans) gf_free(raster_ctx->gray_spans);
54
0
  if (raster_ctx->stencil_pix_run) gf_free(raster_ctx->stencil_pix_run);
55
0
  if (raster_ctx->stencil_pix_run2) gf_free(raster_ctx->stencil_pix_run2);
56
0
  if (raster_ctx->stencil_pix_run3) gf_free(raster_ctx->stencil_pix_run3);
57
0
  if (raster_ctx->uv_alpha) gf_free(raster_ctx->uv_alpha);
58
0
}
59
60
GF_EXPORT
61
GF_EVGSurface *gf_evg_surface_new(Bool center_coords)
62
0
{
63
0
  GF_Err e;
64
0
  GF_EVGSurface *surf;
65
0
  GF_SAFEALLOC(surf, GF_EVGSurface);
66
0
  if (!surf) return NULL;
67
68
0
  surf->center_coords = center_coords;
69
0
  surf->qlevel = GF_RASTER_HIGH_QUALITY;
70
0
  surf->yuv_prof = 1;
71
0
  e = evg_raster_ctx_init(&surf->raster_ctx, surf);
72
0
  if (e) {
73
0
    gf_free(surf);
74
0
    return NULL;
75
0
  }
76
0
  return surf;
77
0
}
78
79
EVG_Surface3DExt *evg_init_3d_surface(GF_EVGSurface *surf);
80
81
GF_EXPORT
82
GF_Err gf_evg_surface_enable_3d(GF_EVGSurface *surf)
83
0
{
84
0
  if (!surf) return GF_BAD_PARAM;
85
0
  if (surf->ext3d) return GF_OK;
86
0
  surf->ext3d = evg_init_3d_surface(surf);
87
0
  if (!surf->ext3d) return GF_OUT_OF_MEM;
88
0
  return GF_OK;
89
0
}
90
91
GF_EXPORT
92
GF_Err gf_evg_enable_threading(GF_EVGSurface *surf, s32 nb_threads)
93
0
{
94
0
#ifndef GPAC_DISABLE_THREADS
95
0
  u32 i, run_size;
96
0
  char szName[100];
97
0
  if (!surf) return GF_BAD_PARAM;
98
0
  if (surf->nb_threads) return GF_OK;
99
0
  if (gf_opts_get_bool("core", "no-mx")) return GF_OK;
100
101
0
  if (nb_threads<0) {
102
0
    GF_SystemRTInfo rti;
103
0
    gf_sys_get_rti(0, &rti, 0);
104
0
    if (rti.nb_cores<2) return GF_IO_ERR;
105
0
    nb_threads = rti.nb_cores-1;
106
0
  }
107
0
  surf->nb_threads = (u32) nb_threads;
108
0
  if (!surf->nb_threads) return GF_OK;
109
0
  surf->th_raster_ctx = gf_malloc(sizeof(EVGRasterCtx) * surf->nb_threads);
110
0
  sprintf(szName, "EVGMX%p", surf);
111
0
  surf->raster_mutex = gf_mx_new(szName);
112
113
0
  if (!surf->th_raster_ctx || !surf->raster_mutex) {
114
0
    surf->nb_threads = 0;
115
0
    return GF_OUT_OF_MEM;
116
0
  }
117
0
  run_size = surf->width ? (sizeof(u32) * (surf->width+2)) : 0;
118
0
  if (surf->width && surf->not_8bits) run_size *= 2;
119
120
121
0
  memset(surf->th_raster_ctx, 0, sizeof(EVGRasterCtx) * surf->nb_threads);
122
0
  for (i=0; i<surf->nb_threads; i++) {
123
0
    EVGRasterCtx *rctx = &surf->th_raster_ctx[i];
124
0
    sprintf(szName, "gf_evg_%d", i+1);
125
0
    rctx->th = gf_th_new(szName);
126
0
    if (!rctx->th) {
127
0
      surf->nb_threads = i;
128
0
      break;
129
0
    }
130
0
    rctx->surf = surf;
131
0
    rctx->max_gray_spans = rctx->alloc_gray_spans = FT_MAX_GRAY_SPANS;
132
0
    rctx->gray_spans = gf_malloc(sizeof(EVG_Span) * rctx->max_gray_spans);
133
134
0
    if (run_size) {
135
0
      rctx->stencil_pix_run = gf_realloc(rctx->stencil_pix_run, run_size);
136
0
    }
137
    
138
0
    if (!rctx->gray_spans || !rctx->stencil_pix_run) {
139
0
      surf->nb_threads = i;
140
0
      break;
141
0
    }
142
0
    rctx->th_state = 1;
143
0
  }
144
0
  surf->raster_sem = gf_sema_new(surf->nb_threads, 0);
145
0
  if (!surf->raster_sem)
146
0
    surf->nb_threads = 0;
147
148
  //launch all threads
149
0
  for (i=0; i<surf->nb_threads; i++) {
150
0
    EVGRasterCtx *rctx = &surf->th_raster_ctx[i];
151
0
    gf_th_run(rctx->th, th_sweep_lines, rctx);
152
0
  }
153
0
#endif //GPAC_DISABLE_THREADS
154
0
  return GF_OK;
155
0
}
156
157
158
GF_EXPORT
159
void gf_evg_surface_set_center_coords(GF_EVGSurface *surf, Bool center_coords)
160
0
{
161
0
  if (surf) surf->center_coords = center_coords;
162
0
}
163
164
GF_EXPORT
165
void gf_evg_surface_delete(GF_EVGSurface *surf)
166
0
{
167
0
  u32 i;
168
0
  if (!surf)
169
0
    return;
170
171
0
  for (i=0; i<surf->max_lines; i++) {
172
0
    gf_free(surf->scanlines[i].cells);
173
0
    if (surf->scanlines[i].pixels)
174
0
      gf_free(surf->scanlines[i].pixels);
175
0
  }
176
0
  gf_free(surf->scanlines);
177
178
0
  if (surf->internal_mask) gf_free(surf->internal_mask);
179
180
0
  evg_raster_ctx_uninit(&surf->raster_ctx);
181
182
0
  if (surf->ext3d) {
183
0
    gf_free(surf->ext3d);
184
0
  }
185
0
#ifndef GPAC_DISABLE_THREADS
186
0
  if (surf->nb_threads) {
187
0
    for (i=0; i<surf->nb_threads; i++) {
188
0
      EVGRasterCtx *rctx = &surf->th_raster_ctx[i];
189
0
      rctx->th_state = 0;
190
0
    }
191
0
    gf_sema_notify(surf->raster_sem, surf->nb_threads);
192
193
0
    for (i=0; i<surf->nb_threads; i++) {
194
0
      EVGRasterCtx *rctx = &surf->th_raster_ctx[i];
195
      //wait for destruction
196
0
      while (!rctx->th_state) {
197
0
        gf_sleep(0);
198
0
      }
199
0
      gf_th_del(surf->th_raster_ctx[i].th);
200
0
      evg_raster_ctx_uninit(&surf->th_raster_ctx[i]);
201
0
    }
202
0
    gf_free(surf->th_raster_ctx);
203
0
    gf_mx_del(surf->raster_mutex);
204
0
    gf_sema_del(surf->raster_sem);
205
0
  }
206
0
#endif
207
0
  gf_free(surf);
208
0
}
209
210
GF_EXPORT
211
GF_Err gf_evg_surface_set_matrix(GF_EVGSurface *surf, GF_Matrix2D *mat)
212
0
{
213
0
  GF_Matrix2D tmp;
214
0
  if (!surf) return GF_BAD_PARAM;
215
0
  get_surface_world_matrix(surf, &surf->mat);
216
0
  surf->is_3d_matrix = GF_FALSE;
217
0
  if (!mat) {
218
0
    gf_mx2d_init(surf->shader_mx);
219
0
    return GF_OK;
220
0
  }
221
0
  gf_mx2d_init(tmp);
222
0
  gf_mx2d_add_matrix(&tmp, mat);
223
0
  gf_mx2d_add_matrix(&tmp, &surf->mat);
224
0
  gf_mx2d_copy(surf->mat, tmp);
225
0
  gf_mx2d_copy(surf->shader_mx, *mat);
226
227
0
  return GF_OK;
228
0
}
229
230
GF_EXPORT
231
GF_Err gf_evg_surface_set_matrix_3d(GF_EVGSurface *surf, GF_Matrix *mat)
232
0
{
233
0
  if (!surf) return GF_BAD_PARAM;
234
0
  get_surface_world_matrix(surf, &surf->mat);
235
0
  surf->is_3d_matrix = GF_FALSE;
236
0
  if (!mat) return GF_OK;
237
0
  gf_mx_copy(surf->mx3d, *mat);
238
0
  surf->is_3d_matrix = GF_TRUE;
239
0
  return GF_OK;
240
0
}
241
242
static void evg_surface_set_components_idx(GF_EVGSurface *surf)
243
0
{
244
0
  surf->idx_y1=surf->idx_u=surf->idx_v=0;
245
0
  surf->idx_a=surf->idx_r=surf->idx_g=surf->idx_b=0;
246
0
  switch (surf->pixelFormat) {
247
0
  case GF_PIXEL_YUYV:
248
0
    surf->idx_y1=0;
249
0
    surf->idx_u=1;
250
0
    surf->idx_v=3;
251
0
    break;
252
0
  case GF_PIXEL_YVYU:
253
0
    surf->idx_y1=0;
254
0
    surf->idx_u=3;
255
0
    surf->idx_v=1;
256
0
    break;
257
0
  case GF_PIXEL_UYVY:
258
0
    surf->idx_y1=1;
259
0
    surf->idx_u=0;
260
0
    surf->idx_v=2;
261
0
    break;
262
0
  case GF_PIXEL_VYUY:
263
0
    surf->idx_y1=1;
264
0
    surf->idx_u=2;
265
0
    surf->idx_v=0;
266
0
    break;
267
0
  case GF_PIXEL_ALPHAGREY:
268
0
    surf->idx_a = 0;
269
0
    surf->idx_g = 1;
270
0
    break;
271
0
  case GF_PIXEL_GREYALPHA:
272
0
    surf->idx_a = 1;
273
0
    surf->idx_g = 0;
274
0
    break;
275
0
  case GF_PIXEL_ARGB:
276
0
    surf->idx_a=0;
277
0
    surf->idx_r=1;
278
0
    surf->idx_g=2;
279
0
    surf->idx_b=3;
280
0
    break;
281
0
  case GF_PIXEL_RGBA:
282
0
  case GF_PIXEL_YUVA444_PACK:
283
0
    surf->idx_a=3;
284
0
    surf->idx_r=0;
285
0
    surf->idx_g=1;
286
0
    surf->idx_b=2;
287
0
    break;
288
0
  case GF_PIXEL_UYVA444_PACK:
289
0
    surf->idx_a=3;
290
0
    surf->idx_r=1;
291
0
    surf->idx_g=0;
292
0
    surf->idx_b=2;
293
0
    break;
294
0
  case GF_PIXEL_YUV444_PACK:
295
0
    surf->idx_r=0;
296
0
    surf->idx_g=1;
297
0
    surf->idx_b=2;
298
0
    break;
299
0
  case GF_PIXEL_VYU444_PACK:
300
0
    surf->idx_r=1;
301
0
    surf->idx_g=2;
302
0
    surf->idx_b=0;
303
0
    break;
304
0
  case GF_PIXEL_BGRA:
305
0
    surf->idx_a=3;
306
0
    surf->idx_r=2;
307
0
    surf->idx_g=1;
308
0
    surf->idx_b=0;
309
0
    break;
310
0
  case GF_PIXEL_ABGR:
311
0
    surf->idx_a=0;
312
0
    surf->idx_r=3;
313
0
    surf->idx_g=2;
314
0
    surf->idx_b=1;
315
0
    break;
316
0
  case GF_PIXEL_RGBX:
317
0
    surf->idx_r=0;
318
0
    surf->idx_g=1;
319
0
    surf->idx_b=2;
320
0
    surf->idx_a=3;
321
0
    break;
322
0
  case GF_PIXEL_BGRX:
323
0
    surf->idx_r=2;
324
0
    surf->idx_g=1;
325
0
    surf->idx_b=0;
326
0
    surf->idx_a=3;
327
0
    break;
328
0
  case GF_PIXEL_XRGB:
329
0
    surf->idx_a=0;
330
0
    surf->idx_r=1;
331
0
    surf->idx_g=2;
332
0
    surf->idx_b=3;
333
0
    break;
334
0
  case GF_PIXEL_XBGR:
335
0
    surf->idx_a=0;
336
0
    surf->idx_r=3;
337
0
    surf->idx_g=2;
338
0
    surf->idx_b=1;
339
0
    break;
340
0
  case GF_PIXEL_RGB:
341
0
    surf->idx_r=0;
342
0
    surf->idx_g=1;
343
0
    surf->idx_b=2;
344
0
    break;
345
0
  case GF_PIXEL_BGR:
346
0
    surf->idx_r=2;
347
0
    surf->idx_g=1;
348
0
    surf->idx_b=0;
349
0
    break;
350
0
  }
351
0
}
352
353
static GF_Err gf_evg_surface_attach_to_buffer_internal(GF_EVGSurface *surf, u8 *pixels, u32 width, u32 height, s32 pitch_x, s32 pitch_y, GF_PixelFormat pixelFormat, Bool probe_only)
354
0
{
355
0
  u32 BPP;
356
0
  Bool size_changed=GF_FALSE;
357
358
0
  if (!probe_only) {
359
0
    if (!surf || !pixels) return GF_BAD_PARAM;
360
0
    surf->is_transparent = GF_FALSE;
361
0
    surf->not_8bits = GF_FALSE;
362
0
  }
363
0
  switch (pixelFormat) {
364
0
  case GF_PIXEL_GREYSCALE:
365
0
    BPP = 1;
366
0
    break;
367
0
  case GF_PIXEL_ALPHAGREY:
368
0
  case GF_PIXEL_GREYALPHA:
369
0
    BPP = 2;
370
0
    if (!probe_only)
371
0
      surf->is_transparent = GF_TRUE;
372
0
    break;
373
0
  case GF_PIXEL_RGB_332:
374
0
    BPP = 1;
375
0
    break;
376
0
  case GF_PIXEL_RGB_444:
377
0
  case GF_PIXEL_RGB_555:
378
0
  case GF_PIXEL_RGB_565:
379
0
    BPP = 2;
380
0
    break;
381
0
  case GF_PIXEL_ARGB:
382
0
  case GF_PIXEL_BGRA:
383
0
  case GF_PIXEL_RGBA:
384
0
  case GF_PIXEL_ABGR:
385
0
    if (!probe_only)
386
0
      surf->is_transparent = GF_TRUE;
387
0
  case GF_PIXEL_RGBX:
388
0
  case GF_PIXEL_BGRX:
389
0
  case GF_PIXEL_XRGB:
390
0
  case GF_PIXEL_XBGR:
391
0
    BPP = 4;
392
0
    break;
393
0
  case GF_PIXEL_BGR:
394
0
  case GF_PIXEL_RGB:
395
0
    BPP = 3;
396
0
    break;
397
0
  case GF_PIXEL_YUV:
398
0
  case GF_PIXEL_YVU:
399
0
  case GF_PIXEL_NV12:
400
0
  case GF_PIXEL_NV21:
401
0
  case GF_PIXEL_YUV422:
402
0
  case GF_PIXEL_YUV444:
403
0
  case GF_PIXEL_YUYV:
404
0
  case GF_PIXEL_YVYU:
405
0
  case GF_PIXEL_UYVY:
406
0
  case GF_PIXEL_VYUY:
407
0
    BPP = 1;
408
0
    break;
409
0
  case GF_PIXEL_YUV_10:
410
0
  case GF_PIXEL_NV12_10:
411
0
  case GF_PIXEL_NV21_10:
412
0
  case GF_PIXEL_YUV422_10:
413
0
  case GF_PIXEL_YUV444_10:
414
0
    BPP = 2;
415
0
    if (!probe_only)
416
0
      surf->not_8bits = GF_TRUE;
417
0
    break;
418
0
  case GF_PIXEL_YUVA444_PACK:
419
0
  case GF_PIXEL_UYVA444_PACK:
420
0
    if (!probe_only)
421
0
      surf->is_transparent = GF_TRUE;
422
0
    BPP = 4;
423
0
    break;
424
0
  case GF_PIXEL_YUV444_PACK:
425
0
  case GF_PIXEL_VYU444_PACK:
426
0
    BPP = 3;
427
0
    break;
428
0
  default:
429
0
    return GF_NOT_SUPPORTED;
430
0
  }
431
0
  if (probe_only) return GF_OK;
432
433
0
  if (!pitch_x) pitch_x = BPP;
434
0
  if (!pitch_y) {
435
0
    gf_pixel_get_size_info(pixelFormat, width, height, NULL, &pitch_y, NULL, NULL, NULL);
436
0
  }
437
438
0
  surf->pitch_x = pitch_x;
439
0
  surf->pitch_y = pitch_y;
440
0
  if (!surf->raster_ctx.stencil_pix_run || (surf->width != width)) {
441
0
    u32 run_size = sizeof(u32) * (width+2);
442
0
    if (surf->not_8bits) run_size *= 2;
443
0
    surf->raster_ctx.stencil_pix_run = gf_realloc(surf->raster_ctx.stencil_pix_run, run_size);
444
0
    if (!surf->raster_ctx.stencil_pix_run) return GF_OUT_OF_MEM;
445
446
0
    if (surf->raster_ctx.stencil_pix_run2) {
447
0
      surf->raster_ctx.stencil_pix_run2 = gf_realloc(surf->raster_ctx.stencil_pix_run2, run_size);
448
0
      if (!surf->raster_ctx.stencil_pix_run2) return GF_OUT_OF_MEM;
449
0
    }
450
0
    if (surf->raster_ctx.stencil_pix_run3) {
451
0
      surf->raster_ctx.stencil_pix_run3 = gf_realloc(surf->raster_ctx.stencil_pix_run3, run_size);
452
0
      if (!surf->raster_ctx.stencil_pix_run3) return GF_OUT_OF_MEM;
453
0
    }
454
455
0
#ifndef GPAC_DISABLE_THREADS
456
0
    u32 i;
457
0
    for (i=0; i<surf->nb_threads; i++) {
458
0
      EVGRasterCtx *rctx = &surf->th_raster_ctx[i];
459
0
      rctx->stencil_pix_run = gf_realloc(rctx->stencil_pix_run, run_size);
460
0
      if (!rctx->stencil_pix_run) return GF_OUT_OF_MEM;
461
462
0
      if (rctx->stencil_pix_run2) {
463
0
        rctx->stencil_pix_run2 = gf_realloc(rctx->stencil_pix_run2, run_size);
464
0
        if (!rctx->stencil_pix_run2) return GF_OUT_OF_MEM;
465
0
      }
466
0
      if (rctx->stencil_pix_run3) {
467
0
        rctx->stencil_pix_run3 = gf_realloc(rctx->stencil_pix_run3, run_size);
468
0
        if (!rctx->stencil_pix_run3) return GF_OUT_OF_MEM;
469
0
      }
470
0
    }
471
0
#endif
472
0
  }
473
0
  if (surf->width != width) {
474
0
    surf->width = width;
475
0
    size_changed = GF_TRUE;
476
0
  }
477
0
  if (surf->height != height) {
478
0
    surf->height = height;
479
0
    size_changed = GF_TRUE;
480
0
  }
481
0
  surf->pixels = (char*)pixels;
482
0
  surf->pixelFormat = pixelFormat;
483
0
  surf->BPP = BPP;
484
0
  evg_surface_set_components_idx(surf);
485
0
  gf_evg_surface_set_matrix(surf, NULL);
486
487
0
  if (size_changed && surf->internal_mask) {
488
0
    gf_free(surf->internal_mask);
489
0
    surf->internal_mask = NULL;
490
0
  }
491
0
  if (surf->ext3d && size_changed) {
492
0
    surf->ext3d->depth_buffer = NULL;
493
494
0
    if (!surf->vp_w || !surf->vp_h) {
495
0
      surf->vp_x = 0;
496
0
      surf->vp_y = 0;
497
0
      surf->vp_w = surf->width;
498
0
      surf->vp_h = surf->height;
499
0
    }
500
0
  }
501
0
  return GF_OK;
502
0
}
503
504
GF_EXPORT
505
GF_Err gf_evg_surface_attach_to_buffer(GF_EVGSurface *surf, u8 *pixels, u32 width, u32 height, s32 pitch_x, s32 pitch_y, GF_PixelFormat pixelFormat)
506
0
{
507
0
  return gf_evg_surface_attach_to_buffer_internal(surf, pixels, width, height, pitch_x, pitch_y, pixelFormat, GF_FALSE);
508
0
}
509
510
GF_EXPORT
511
GF_Err gf_evg_surface_attach_to_texture(GF_EVGSurface *surf, GF_EVGStencil * sten)
512
0
{
513
0
  EVG_Texture *tx = (EVG_Texture *) sten;
514
0
  if (!surf || (tx->type != GF_STENCIL_TEXTURE)) return GF_BAD_PARAM;
515
516
0
  return gf_evg_surface_attach_to_buffer_internal(surf, tx->pixels, tx->width, tx->height, 0, tx->stride, tx->pixel_format, GF_FALSE);
517
0
}
518
519
GF_EXPORT
520
Bool gf_evg_surface_format_ok(GF_PixelFormat pixelFormat)
521
0
{
522
0
  GF_Err e = gf_evg_surface_attach_to_buffer_internal(NULL, NULL, 0, 0, 0, 0, pixelFormat, GF_TRUE);
523
0
  if (e==GF_OK) return GF_TRUE;
524
0
  return GF_FALSE;
525
0
}
526
527
GF_EXPORT
528
GF_Err gf_evg_surface_clear(GF_EVGSurface *surf, GF_IRect *rc, u32 color)
529
0
{
530
0
  GF_IRect clear;
531
0
  if (!surf) return GF_BAD_PARAM;
532
533
0
  if (rc) {
534
0
    s32 _x, _y;
535
0
    if (surf->center_coords) {
536
0
      _x = rc->x + surf->width / 2;
537
0
      _y = surf->height / 2 - rc->y;
538
0
    } else {
539
0
      _x = rc->x;
540
0
      _y = rc->y - rc->height;
541
0
    }
542
    /*clip is outside our bounds, ignore*/
543
0
    if ((_x>=(s32) surf->width) || (_x + rc->width < 0))
544
0
      return GF_OK;
545
0
    if ((_y>= (s32) surf->height) || (_y + rc->height < 0))
546
0
      return GF_OK;
547
548
0
    clear.width = (u32) rc->width;
549
0
    if (_x>=0) {
550
0
      clear.x = (u32) _x;
551
0
    } else {
552
0
      if ( (s32) clear.width + _x < 0) return GF_BAD_PARAM;
553
0
      clear.width += _x;
554
0
      clear.x = 0;
555
0
    }
556
0
    if (clear.x + clear.width > (s32) surf->width)
557
0
      clear.width = surf->width - clear.x;
558
559
0
    if (!clear.width)
560
0
      return GF_OK;
561
562
0
    clear.height = (u32) rc->height;
563
0
    if (_y>=0) {
564
0
      clear.y = _y;
565
0
    } else {
566
0
      if ( (s32) clear.height + _y < 0) return GF_BAD_PARAM;
567
0
      clear.height += _y;
568
0
      clear.y = 0;
569
0
    }
570
0
    if (clear.y + clear.height > (s32) surf->height)
571
0
      clear.height = surf->height - clear.y;
572
573
0
    if (!clear.height)
574
0
      return GF_OK;
575
0
  } else {
576
0
    clear.x = clear.y = 0;
577
0
    clear.width = surf->width;
578
0
    clear.height = surf->height;
579
0
  }
580
581
0
  switch (surf->pixelFormat) {
582
  /*RGB formats*/
583
0
  case GF_PIXEL_GREYSCALE:
584
0
    return evg_surface_clear_grey(surf, clear, color);
585
0
  case GF_PIXEL_ALPHAGREY:
586
0
  case GF_PIXEL_GREYALPHA:
587
0
    return evg_surface_clear_alphagrey(surf, clear, color);
588
0
  case GF_PIXEL_ARGB:
589
0
  case GF_PIXEL_BGRA:
590
0
  case GF_PIXEL_RGBA:
591
0
  case GF_PIXEL_ABGR:
592
0
    return evg_surface_clear_argb(surf, clear, color);
593
594
0
  case GF_PIXEL_RGBX:
595
0
  case GF_PIXEL_BGRX:
596
0
  case GF_PIXEL_XRGB:
597
0
  case GF_PIXEL_XBGR:
598
0
    return evg_surface_clear_rgbx(surf, clear, color);
599
600
0
  case GF_PIXEL_RGB:
601
0
  case GF_PIXEL_BGR:
602
0
    return evg_surface_clear_rgb(surf, clear, color);
603
0
  case GF_PIXEL_RGB_444:
604
0
    return evg_surface_clear_444(surf, clear, color);
605
0
  case GF_PIXEL_RGB_555:
606
0
    return evg_surface_clear_555(surf, clear, color);
607
0
  case GF_PIXEL_RGB_565:
608
0
    return evg_surface_clear_565(surf, clear, color);
609
0
  case GF_PIXEL_RGB_332:
610
0
    return evg_surface_clear_332(surf, clear, color);
611
612
  /*YUV formats*/
613
0
  case GF_PIXEL_YUV:
614
0
  case GF_PIXEL_YVU:
615
0
    return evg_surface_clear_yuv420p(surf, clear, color);
616
0
  case GF_PIXEL_YUV422:
617
0
    return evg_surface_clear_yuv422p(surf, clear, color);
618
0
  case GF_PIXEL_NV12:
619
0
    return evg_surface_clear_nv12(surf, clear, color, GF_FALSE);
620
0
  case GF_PIXEL_NV21:
621
0
    return evg_surface_clear_nv12(surf, clear, color, GF_TRUE);
622
0
  case GF_PIXEL_YUV444:
623
0
    return evg_surface_clear_yuv444p(surf, clear, color);
624
0
  case GF_PIXEL_YUYV:
625
0
  case GF_PIXEL_YVYU:
626
0
  case GF_PIXEL_UYVY:
627
0
  case GF_PIXEL_VYUY:
628
0
    return evg_surface_clear_yuyv(surf, clear, color);
629
0
  case GF_PIXEL_YUV_10:
630
0
    return evg_surface_clear_yuv420p_10(surf, clear, color);
631
0
  case GF_PIXEL_NV12_10:
632
0
    return evg_surface_clear_nv12_10(surf, clear, color, GF_FALSE);
633
0
  case GF_PIXEL_NV21_10:
634
0
    return evg_surface_clear_nv12_10(surf, clear, color, GF_TRUE);
635
0
  case GF_PIXEL_YUV422_10:
636
0
    return evg_surface_clear_yuv422p_10(surf, clear, color);
637
0
  case GF_PIXEL_YUV444_10:
638
0
    return evg_surface_clear_yuv444p_10(surf, clear, color);
639
640
0
  case GF_PIXEL_YUVA444_PACK:
641
0
  case GF_PIXEL_UYVA444_PACK:
642
0
    return evg_surface_clear_argb(surf, clear, gf_evg_argb_to_ayuv(surf, color) );
643
644
0
  case GF_PIXEL_YUV444_PACK:
645
0
  case GF_PIXEL_VYU444_PACK:
646
0
    return evg_surface_clear_rgb(surf, clear, gf_evg_argb_to_ayuv(surf, color) );
647
0
  default:
648
0
    return GF_BAD_PARAM;
649
0
  }
650
0
}
651
652
GF_EXPORT
653
GF_Err gf_evg_surface_set_raster_level(GF_EVGSurface *surf, GF_RasterQuality RasterSetting)
654
0
{
655
0
  if (!surf) return GF_BAD_PARAM;
656
0
  surf->qlevel = RasterSetting;
657
0
  return GF_OK;
658
0
}
659
GF_EXPORT
660
GF_RasterQuality gf_evg_surface_get_raster_level(GF_EVGSurface *surf)
661
0
{
662
0
  if (!surf) return GF_RASTER_HIGH_QUALITY;
663
0
  return surf->qlevel;
664
0
}
665
666
GF_EXPORT
667
GF_Err gf_evg_surface_force_aa(GF_EVGSurface *surf)
668
0
{
669
0
  if (!surf) return GF_BAD_PARAM;
670
0
  surf->aa_level = 0xFF;
671
0
  return GF_OK;
672
0
}
673
674
675
GF_EXPORT
676
GF_Err gf_evg_surface_set_clipper(GF_EVGSurface *surf , GF_IRect *rc)
677
0
{
678
0
  if (!surf) return GF_BAD_PARAM;
679
0
  if (rc) {
680
0
    surf->clipper = *rc;
681
0
    surf->useClipper = 1;
682
    /*clipper was given in BIFS like coords, we work with bottom-min for rect, (0,0) top-left of surface*/
683
0
    if (surf->center_coords) {
684
0
      surf->clipper.x += surf->width / 2;
685
0
      surf->clipper.y = surf->height / 2 - rc->y;
686
0
    } else {
687
0
      surf->clipper.y -= rc->height;
688
0
    }
689
690
0
    if (surf->clipper.x <=0) {
691
0
      if (surf->clipper.x + (s32) surf->clipper.width < 0) return GF_BAD_PARAM;
692
0
      surf->clipper.width += surf->clipper.x;
693
0
      surf->clipper.x = 0;
694
0
    }
695
0
    if (surf->clipper.y <=0) {
696
0
      if (surf->clipper.y + (s32) surf->clipper.height < 0) return GF_BAD_PARAM;
697
0
      surf->clipper.height += surf->clipper.y;
698
0
      surf->clipper.y = 0;
699
0
    }
700
0
    if (surf->clipper.x + surf->clipper.width > (s32) surf->width) {
701
0
      surf->clipper.width = surf->width - surf->clipper.x;
702
0
    }
703
0
    if (surf->clipper.y + surf->clipper.height > (s32) surf->height) {
704
0
      surf->clipper.height = surf->height - surf->clipper.y;
705
0
    }
706
0
  } else {
707
0
    surf->useClipper = 0;
708
0
  }
709
0
  return GF_OK;
710
0
}
711
712
GF_EXPORT
713
Bool gf_evg_surface_use_clipper(GF_EVGSurface *surf)
714
0
{
715
0
  if (!surf) return 0;
716
0
  return surf->useClipper ? GF_TRUE : GF_FALSE;
717
0
}
718
719
static Bool setup_grey_callback(GF_EVGSurface *surf, Bool for_3d, Bool multi_sten)
720
0
{
721
0
  u32 a, uv_alpha_size=0;
722
0
  Bool use_const = GF_TRUE;
723
724
  //default fill_run callback
725
0
  surf->fill_run = evg_fill_run;
726
727
  //mask mode draw,
728
0
  if (surf->mask_mode == GF_EVGMASK_DRAW) {
729
0
    if (surf->sten && (surf->sten->type == GF_STENCIL_SOLID)) {
730
0
      EVG_Brush *sc = (EVG_Brush *)surf->sten;
731
0
      u32 col = sc->color;
732
0
      if (sc->alpha < 0xFF) {
733
0
        u32 ca = ((u32) (GF_COL_A(col) + 1) * sc->alpha) >> 8;
734
0
        col = ( ((ca<<24) & 0xFF000000) ) | (col & 0x00FFFFFF);
735
0
      }
736
0
      surf->fill_col = col;
737
0
      surf->fill_col_wide = evg_col_to_wide(surf->fill_col);
738
0
      if (GF_COL_A(col)<0xFF)
739
0
        surf->fill_spans = (EVG_SpanFunc) evg_grey_fill_const_a;
740
0
      else
741
0
        surf->fill_spans = (EVG_SpanFunc) evg_grey_fill_const;
742
0
    } else {
743
0
      surf->fill_spans = (EVG_SpanFunc) evg_grey_fill_var;
744
0
    }
745
0
    if (surf->ext3d) {
746
0
      surf->fill_single = evg_grey_fill_single;
747
0
      surf->fill_single_a = evg_grey_fill_single_a;
748
0
    }
749
0
    return GF_TRUE;
750
0
  }
751
752
  //in 3D mode, we only write one pixel at a time except in YUV modes
753
0
  if (for_3d) {
754
0
    a = 1;
755
0
    use_const = GF_TRUE;
756
0
  }
757
0
  else if (!multi_sten && surf->sten && (surf->sten->type == GF_STENCIL_SOLID)) {
758
0
    EVG_Brush *sc = (EVG_Brush *)surf->sten;
759
0
    u32 col = sc->color;
760
0
    if (sc->alpha < 0xFF) {
761
0
      u32 ca = ((u32) (GF_COL_A(col) + 1) * sc->alpha) >> 8;
762
0
      col = ( ((ca<<24) & 0xFF000000) ) | (col & 0x00FFFFFF);
763
0
    }
764
0
    surf->fill_col = col;
765
0
    a = GF_COL_A(surf->fill_col);
766
0
  } else {
767
0
    a = 0;
768
0
    use_const = GF_FALSE;
769
0
  }
770
  //mask is used, force fill with variable alpha (xxx_fill_var) and use masking callback for fill_run
771
0
  if ((surf->mask_mode == GF_EVGMASK_USE) || (surf->mask_mode == GF_EVGMASK_RECORD) ){
772
0
    a = 0;
773
0
    use_const = GF_FALSE;
774
0
    if (surf->mask_mode == GF_EVGMASK_USE)
775
0
      surf->fill_run = evg_fill_run_mask;
776
0
  } else if (surf->mask_mode == GF_EVGMASK_USE_INV) {
777
0
    a = 0;
778
0
    use_const = GF_FALSE;
779
0
    surf->fill_run = evg_fill_run_mask_inv;
780
0
  }
781
782
0
  if (use_const && !a && !surf->is_transparent) return GF_FALSE;
783
784
0
  surf->is_422 = GF_FALSE;
785
0
  surf->yuv_type = 0;
786
0
  surf->swap_uv = GF_FALSE;
787
0
  surf->yuv_flush_uv = NULL;
788
0
  surf->direct_yuv_3d = GF_FALSE;
789
790
0
  if (surf->comp_mode) a=100;
791
0
  else if (surf->get_alpha) a=100;
792
0
  surf->fill_single = NULL;
793
0
  surf->fill_single_a = NULL;
794
  
795
0
  switch (surf->pixelFormat) {
796
0
  case GF_PIXEL_GREYSCALE:
797
0
    if (use_const) {
798
0
      if (a!=0xFF) {
799
0
        surf->fill_spans = (EVG_SpanFunc) evg_grey_fill_const_a;
800
0
      } else {
801
0
        surf->fill_spans = (EVG_SpanFunc) evg_grey_fill_const;
802
0
      }
803
0
    } else {
804
0
      surf->fill_spans = (EVG_SpanFunc) evg_grey_fill_var;
805
0
    }
806
0
    if (surf->ext3d) {
807
0
      surf->fill_single = evg_grey_fill_single;
808
0
      surf->fill_single_a = evg_grey_fill_single_a;
809
0
    }
810
0
    break;
811
0
  case GF_PIXEL_ALPHAGREY:
812
0
  case GF_PIXEL_GREYALPHA:
813
0
    if (use_const) {
814
0
      if (a!=0xFF) {
815
0
        surf->fill_spans = (EVG_SpanFunc) evg_alphagrey_fill_const_a;
816
0
      } else {
817
0
        surf->fill_spans = (EVG_SpanFunc) evg_alphagrey_fill_const;
818
0
      }
819
0
    } else {
820
0
      surf->fill_spans = (EVG_SpanFunc) evg_alphagrey_fill_var;
821
0
    }
822
0
    if (surf->ext3d) {
823
0
      surf->fill_single = evg_alphagrey_fill_single;
824
0
      surf->fill_single_a = evg_alphagrey_fill_single_a;
825
0
    }
826
0
    break;
827
0
  case GF_PIXEL_YUVA444_PACK:
828
0
  case GF_PIXEL_UYVA444_PACK:
829
0
    surf->yuv_type = EVG_YUV;
830
0
  case GF_PIXEL_ARGB:
831
0
  case GF_PIXEL_RGBA:
832
0
  case GF_PIXEL_BGRA:
833
0
  case GF_PIXEL_ABGR:
834
0
    if (use_const) {
835
0
      if (!a) {
836
0
        surf->fill_spans = (EVG_SpanFunc) evg_argb_fill_erase;
837
0
      } else if (a!=0xFF) {
838
0
        surf->fill_spans = (EVG_SpanFunc) evg_argb_fill_const_a;
839
0
      } else {
840
0
        surf->fill_spans = (EVG_SpanFunc) evg_argb_fill_const;
841
0
      }
842
0
    } else {
843
0
      surf->fill_spans = (EVG_SpanFunc) evg_argb_fill_var;
844
0
    }
845
0
    if (surf->ext3d) {
846
0
      surf->fill_single = evg_argb_fill_single;
847
0
      surf->fill_single_a = evg_argb_fill_single_a;
848
0
    }
849
0
    break;
850
851
0
  case GF_PIXEL_RGBX:
852
0
  case GF_PIXEL_BGRX:
853
0
  case GF_PIXEL_XRGB:
854
0
  case GF_PIXEL_XBGR:
855
0
    if (use_const) {
856
0
      if (a!=0xFF) {
857
0
        surf->fill_spans = (EVG_SpanFunc) evg_rgbx_fill_const_a;
858
0
      } else {
859
0
        surf->fill_spans = (EVG_SpanFunc) evg_rgbx_fill_const;
860
0
      }
861
0
    } else {
862
0
      surf->fill_spans = (EVG_SpanFunc) evg_rgbx_fill_var;
863
0
    }
864
0
    if (surf->ext3d) {
865
0
      surf->fill_single = evg_rgbx_fill_single;
866
0
      surf->fill_single_a = evg_rgbx_fill_single_a;
867
0
    }
868
0
    break;
869
870
0
  case GF_PIXEL_YUV444_PACK:
871
0
  case GF_PIXEL_VYU444_PACK:
872
0
    surf->yuv_type = EVG_YUV;
873
0
  case GF_PIXEL_RGB:
874
0
  case GF_PIXEL_BGR:
875
0
    if (use_const) {
876
0
      if (a!=0xFF) {
877
0
        surf->fill_spans = (EVG_SpanFunc) evg_rgb_fill_const_a;
878
0
      } else {
879
0
        surf->fill_spans = (EVG_SpanFunc) evg_rgb_fill_const;
880
0
      }
881
0
    } else {
882
0
      surf->fill_spans = (EVG_SpanFunc) evg_rgb_fill_var;
883
0
    }
884
0
    if (surf->ext3d) {
885
0
      surf->fill_single = evg_rgb_fill_single;
886
0
      surf->fill_single_a = evg_rgb_fill_single_a;
887
0
    }
888
0
    break;
889
890
0
  case GF_PIXEL_RGB_565:
891
0
    if (use_const) {
892
0
      if (a!=0xFF) {
893
0
        surf->fill_spans = (EVG_SpanFunc) evg_565_fill_const_a;
894
0
      } else {
895
0
        surf->fill_spans = (EVG_SpanFunc) evg_565_fill_const;
896
0
      }
897
0
    } else {
898
0
      surf->fill_spans = (EVG_SpanFunc) evg_565_fill_var;
899
0
    }
900
0
    if (surf->ext3d) {
901
0
      surf->fill_single = evg_565_fill_single;
902
0
      surf->fill_single_a = evg_565_fill_single_a;
903
0
    }
904
0
    break;
905
0
  case GF_PIXEL_RGB_444:
906
0
    if (use_const) {
907
0
      if (a!=0xFF) {
908
0
        surf->fill_spans = (EVG_SpanFunc) evg_444_fill_const_a;
909
0
      } else {
910
0
        surf->fill_spans = (EVG_SpanFunc) evg_444_fill_const;
911
0
      }
912
0
    } else {
913
0
      surf->fill_spans = (EVG_SpanFunc) evg_444_fill_var;
914
0
    }
915
0
    if (surf->ext3d) {
916
0
      surf->fill_single = evg_444_fill_single;
917
0
      surf->fill_single_a = evg_444_fill_single_a;
918
0
    }
919
0
    break;
920
0
  case GF_PIXEL_RGB_555:
921
0
    if (use_const) {
922
0
      if (a!=0xFF) {
923
0
        surf->fill_spans = (EVG_SpanFunc) evg_555_fill_const_a;
924
0
      } else {
925
0
        surf->fill_spans = (EVG_SpanFunc) evg_555_fill_const;
926
0
      }
927
0
    } else {
928
0
      surf->fill_spans = (EVG_SpanFunc) evg_555_fill_var;
929
0
    }
930
0
    if (surf->ext3d) {
931
0
      surf->fill_single = evg_555_fill_single;
932
0
      surf->fill_single_a = evg_555_fill_single_a;
933
0
    }
934
0
    break;
935
0
  case GF_PIXEL_RGB_332:
936
0
    if (use_const) {
937
0
      if (a!=0xFF) {
938
0
        surf->fill_spans = (EVG_SpanFunc) evg_332_fill_const_a;
939
0
      } else {
940
0
        surf->fill_spans = (EVG_SpanFunc) evg_332_fill_const;
941
0
      }
942
0
    } else {
943
0
      surf->fill_spans = (EVG_SpanFunc) evg_332_fill_var;
944
0
    }
945
0
    if (surf->ext3d) {
946
0
      surf->fill_single = evg_332_fill_single;
947
0
      surf->fill_single_a = evg_332_fill_single_a;
948
0
    }
949
0
    break;
950
0
  case GF_PIXEL_YVU:
951
0
    surf->swap_uv = GF_TRUE;
952
0
  case GF_PIXEL_YUV:
953
0
    surf->yuv_type = EVG_YUV;
954
0
    if (use_const && !for_3d) {
955
0
      surf->yuv_flush_uv = evg_yuv420p_flush_uv_const;
956
957
0
      if (a!=0xFF) {
958
0
        surf->fill_spans = (EVG_SpanFunc) evg_yuv420p_fill_const_a;
959
0
      } else {
960
0
        surf->fill_spans = (EVG_SpanFunc) evg_yuv420p_fill_const;
961
0
      }
962
0
      uv_alpha_size=2*surf->width;
963
0
    } else {
964
0
      surf->yuv_flush_uv = evg_yuv420p_flush_uv_var;
965
0
      surf->fill_spans = (EVG_SpanFunc) evg_yuv420p_fill_var;
966
0
      uv_alpha_size = 2 * 3*surf->width;
967
0
      if (for_3d) {
968
0
        surf->sten = &surf->ext3d->yuv_sten;
969
0
        surf->direct_yuv_3d = GF_TRUE;
970
0
      }
971
972
0
    }
973
0
    break;
974
0
  case GF_PIXEL_NV21:
975
0
    surf->swap_uv = GF_TRUE;
976
0
  case GF_PIXEL_NV12:
977
0
    surf->yuv_type = EVG_YUV;
978
979
0
    if (surf->swap_uv) {
980
0
      surf->idx_u = 1;
981
0
      surf->idx_v = 0;
982
0
    } else {
983
0
      surf->idx_u = 0;
984
0
      surf->idx_v = 1;
985
0
    }
986
987
0
    if (use_const && !for_3d) {
988
0
      surf->yuv_flush_uv = evg_nv12_flush_uv_const;
989
990
0
      if (a!=0xFF) {
991
0
        surf->fill_spans = (EVG_SpanFunc) evg_yuv420p_fill_const_a;
992
0
      } else {
993
0
        surf->fill_spans = (EVG_SpanFunc) evg_yuv420p_fill_const;
994
0
      }
995
0
      uv_alpha_size = 2*surf->width;
996
0
    } else {
997
0
      surf->yuv_flush_uv = evg_nv12_flush_uv_var;
998
0
      surf->fill_spans = (EVG_SpanFunc) evg_yuv420p_fill_var;
999
0
      uv_alpha_size = 2 * 3*surf->width;
1000
0
    }
1001
0
    break;
1002
0
  case GF_PIXEL_YUV422:
1003
0
    surf->yuv_type = EVG_YUV;
1004
0
    surf->is_422 = GF_TRUE;
1005
0
    if (use_const && !for_3d) {
1006
0
      surf->yuv_flush_uv = evg_yuv422p_flush_uv_const;
1007
1008
0
      if (a!=0xFF) {
1009
0
        surf->fill_spans = (EVG_SpanFunc) evg_yuv420p_fill_const_a;
1010
0
      } else {
1011
0
        surf->fill_spans = (EVG_SpanFunc) evg_yuv420p_fill_const;
1012
0
      }
1013
0
      uv_alpha_size = 2*surf->width;
1014
0
    } else {
1015
0
      surf->yuv_flush_uv = evg_yuv422p_flush_uv_var;
1016
0
      surf->fill_spans = (EVG_SpanFunc) evg_yuv420p_fill_var;
1017
0
      uv_alpha_size = 2 * 3*surf->width;
1018
0
    }
1019
0
    break;
1020
0
  case GF_PIXEL_YUV444:
1021
0
    surf->yuv_type = EVG_YUV_444;
1022
0
    if (use_const) {
1023
0
      if (a!=0xFF) {
1024
0
        surf->fill_spans = (EVG_SpanFunc) evg_yuv444p_fill_const_a;
1025
0
      } else {
1026
0
        surf->fill_spans = (EVG_SpanFunc) evg_yuv444p_fill_const;
1027
0
      }
1028
0
    } else {
1029
0
      surf->fill_spans = (EVG_SpanFunc) evg_yuv444p_fill_var;
1030
0
    }
1031
0
    break;
1032
0
  case GF_PIXEL_YUYV:
1033
0
  case GF_PIXEL_YVYU:
1034
0
  case GF_PIXEL_UYVY:
1035
0
  case GF_PIXEL_VYUY:
1036
0
    surf->yuv_type = EVG_YUV;
1037
0
    if (use_const && !for_3d) {
1038
0
      if (a!=0xFF) {
1039
0
        surf->fill_spans = (EVG_SpanFunc) evg_yuyv_fill_const_a;
1040
0
      } else {
1041
0
        surf->fill_spans = (EVG_SpanFunc) evg_yuyv_fill_const;
1042
0
      }
1043
0
      uv_alpha_size = 2*surf->width;
1044
0
    } else {
1045
0
      surf->fill_spans = (EVG_SpanFunc) evg_yuyv_fill_var;
1046
0
      uv_alpha_size = 2 * 3*surf->width;
1047
0
    }
1048
0
    break;
1049
1050
0
  case GF_PIXEL_YUV_10:
1051
0
    surf->yuv_type = EVG_YUV;
1052
0
    if (use_const && !for_3d) {
1053
0
      surf->yuv_flush_uv = evg_yuv420p_10_flush_uv_const;
1054
1055
0
      if (a!=0xFF) {
1056
0
        surf->fill_spans = (EVG_SpanFunc) evg_yuv420p_10_fill_const_a;
1057
0
      } else {
1058
0
        surf->fill_spans = (EVG_SpanFunc) evg_yuv420p_10_fill_const;
1059
0
      }
1060
0
      uv_alpha_size = 4*surf->width;
1061
0
    } else {
1062
0
      surf->yuv_flush_uv = evg_yuv420p_10_flush_uv_var;
1063
0
      surf->fill_spans = (EVG_SpanFunc) evg_yuv420p_10_fill_var;
1064
0
      uv_alpha_size = 4*3*surf->width;
1065
0
    }
1066
0
    break;
1067
0
  case GF_PIXEL_NV21_10:
1068
0
    surf->swap_uv = GF_TRUE;
1069
0
  case GF_PIXEL_NV12_10:
1070
0
    surf->yuv_type = EVG_YUV;
1071
1072
0
    if (surf->swap_uv) {
1073
0
      surf->idx_u = 1;
1074
0
      surf->idx_v = 0;
1075
0
    } else {
1076
0
      surf->idx_u = 0;
1077
0
      surf->idx_v = 1;
1078
0
    }
1079
1080
0
    if (use_const && !for_3d) {
1081
0
      surf->yuv_flush_uv = evg_nv12_10_flush_uv_const;
1082
1083
0
      if (a!=0xFF) {
1084
0
        surf->fill_spans = (EVG_SpanFunc) evg_yuv420p_10_fill_const_a;
1085
0
      } else {
1086
0
        surf->fill_spans = (EVG_SpanFunc) evg_yuv420p_10_fill_const;
1087
0
      }
1088
0
      uv_alpha_size = 4*surf->width;
1089
0
    } else {
1090
0
      surf->yuv_flush_uv = evg_nv12_10_flush_uv_var;
1091
0
      surf->fill_spans = (EVG_SpanFunc) evg_yuv420p_10_fill_var;
1092
0
      uv_alpha_size = 4 * 3*surf->width;
1093
0
    }
1094
0
    break;
1095
0
  case GF_PIXEL_YUV422_10:
1096
0
    surf->yuv_type = EVG_YUV;
1097
0
    surf->is_422 = GF_TRUE;
1098
0
    if (use_const && !for_3d) {
1099
0
      surf->yuv_flush_uv = evg_yuv422p_10_flush_uv_const;
1100
1101
0
      if (a!=0xFF) {
1102
0
        surf->fill_spans = (EVG_SpanFunc) evg_yuv420p_10_fill_const_a;
1103
0
      } else {
1104
0
        surf->fill_spans = (EVG_SpanFunc) evg_yuv420p_10_fill_const;
1105
0
      }
1106
0
      uv_alpha_size = 4*surf->width;
1107
0
    } else {
1108
0
      surf->yuv_flush_uv = evg_yuv422p_10_flush_uv_var;
1109
0
      surf->fill_spans = (EVG_SpanFunc) evg_yuv420p_10_fill_var;
1110
0
      uv_alpha_size = 4 * 3*surf->width;
1111
0
    }
1112
0
    break;
1113
0
  case GF_PIXEL_YUV444_10:
1114
0
    surf->yuv_type = EVG_YUV_444;
1115
0
    if (use_const) {
1116
0
      if (a!=0xFF) {
1117
0
        surf->fill_spans = (EVG_SpanFunc) evg_yuv444p_10_fill_const_a;
1118
0
      } else {
1119
0
        surf->fill_spans = (EVG_SpanFunc) evg_yuv444p_10_fill_const;
1120
0
      }
1121
0
    } else {
1122
0
      surf->fill_spans = (EVG_SpanFunc) evg_yuv444p_10_fill_var;
1123
0
    }
1124
0
    break;
1125
0
  default:
1126
0
    return GF_FALSE;
1127
0
  }
1128
1129
0
  if (uv_alpha_size) {
1130
0
#ifndef GPAC_DISABLE_THREADS
1131
0
    u32 i;
1132
0
#endif
1133
    //safety for uneven size in 422/420 rounding (fuzz)
1134
0
    uv_alpha_size += 4;
1135
0
    if (surf->uv_alpha_alloc < uv_alpha_size) {
1136
0
      surf->uv_alpha_alloc = uv_alpha_size;
1137
0
      surf->raster_ctx.uv_alpha = gf_realloc(surf->raster_ctx.uv_alpha, uv_alpha_size);
1138
0
      if (!surf->raster_ctx.uv_alpha) return GF_FALSE;
1139
0
#ifndef GPAC_DISABLE_THREADS
1140
0
      for (i=0;i<surf->nb_threads; i++) {
1141
0
        EVGRasterCtx *rctx = &surf->th_raster_ctx[i];
1142
0
        rctx->uv_alpha = gf_realloc(rctx->uv_alpha, uv_alpha_size);
1143
0
        if (!rctx->uv_alpha) return GF_FALSE;
1144
0
      }
1145
0
#endif
1146
0
    }
1147
0
    memset(surf->raster_ctx.uv_alpha, 0, sizeof(char)*surf->uv_alpha_alloc);
1148
0
#ifndef GPAC_DISABLE_THREADS
1149
0
    for (i=0;i<surf->nb_threads; i++) {
1150
0
      EVGRasterCtx *rctx = &surf->th_raster_ctx[i];
1151
0
      memset(rctx->uv_alpha, 0, sizeof(char)*surf->uv_alpha_alloc);
1152
0
    }
1153
0
#endif
1154
0
  }
1155
0
  if (surf->yuv_type && for_3d) {
1156
0
    surf->sten = &surf->ext3d->yuv_sten;
1157
0
    surf->direct_yuv_3d = GF_TRUE;
1158
0
  }
1159
1160
0
  if (use_const && surf->yuv_type) {
1161
0
    u8 y, cb, cr;
1162
0
    gf_evg_rgb_to_yuv(surf, surf->fill_col, &y, &cb, &cr);
1163
0
    if (surf->swap_uv) {
1164
0
      u8 t = cb;
1165
0
      cb = cr;
1166
0
      cr = (u8) t;
1167
0
      surf->swap_uv = GF_FALSE;
1168
0
    }
1169
1170
0
    surf->fill_col = GF_COL_ARGB(a, y, cb, cr);
1171
0
    surf->fill_col_wide = evg_col_to_wide(surf->fill_col);
1172
0
  }
1173
1174
0
  return GF_TRUE;
1175
0
}
1176
1177
1178
GF_EXPORT
1179
GF_Err gf_evg_surface_set_path(GF_EVGSurface *surf, GF_Path *gp)
1180
0
{
1181
0
  if (!surf) return GF_BAD_PARAM;
1182
0
  surf->aa_level = 0;
1183
0
  if (!gp || !gp->n_points) {
1184
0
    surf->ftoutline.n_points = 0;
1185
0
    surf->ftoutline.n_contours = 0;
1186
0
    return GF_OK;
1187
0
  }
1188
0
  gf_path_flatten(gp);
1189
0
  surf->ftoutline.n_points = gp->n_points;
1190
0
  surf->ftoutline.n_contours = gp->n_contours;
1191
1192
0
  surf->ftoutline.tags = gp->tags;
1193
0
  surf->ftoutline.contours = (s32*) gp->contours;
1194
1195
  /*store path bounds for gradient/textures*/
1196
0
  gf_path_get_bounds(gp, &surf->path_bounds);
1197
  /*invert Y (ft uses min Y)*/
1198
0
  surf->path_bounds.y -= surf->path_bounds.height;
1199
1200
0
  surf->ftoutline.flags = 0;
1201
0
  if (gp->flags & GF_PATH_FILL_ZERO_NONZERO)
1202
0
    surf->ftoutline.flags |= GF_PATH_FILL_ZERO_NONZERO;
1203
0
  if (gp->flags & GF_PATH_FILL_EVEN)
1204
0
    surf->ftoutline.flags |= GF_PATH_FILL_EVEN;
1205
1206
0
  surf->ftoutline.n_points = gp->n_points;
1207
0
  surf->ftoutline.points = gp->points;
1208
0
  surf->mx = &surf->mat;
1209
0
  return GF_OK;
1210
0
}
1211
1212
static u32 shader_get_pix(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *rctx)
1213
0
{
1214
0
  rctx->frag_param.tx_x = x;
1215
0
  rctx->frag_param.tx_y = _this->height-y;
1216
1217
0
  evg_get_fragment(rctx->surf, rctx, NULL);
1218
0
  rctx->frag_param.screen_x += 1;
1219
0
  return rctx->fill_col;
1220
0
}
1221
1222
static u64 shader_get_pix_wide(EVG_Texture *_this, u32 x, u32 y, EVGRasterCtx *rctx)
1223
0
{
1224
0
  rctx->frag_param.tx_x = x;
1225
0
  rctx->frag_param.tx_y = _this->height-y;
1226
1227
0
  evg_get_fragment(rctx->surf, rctx, NULL);
1228
0
  rctx->frag_param.screen_x += 1;
1229
0
  return rctx->fill_col_wide;
1230
0
}
1231
1232
static GF_Err gf_evg_setup_stencil(GF_EVGSurface *surf, GF_EVGStencil *sten, GF_Matrix2D *mat)
1233
0
{
1234
0
  GF_Rect rc;
1235
1236
  /*get path frame for texture convertion */
1237
0
  if (sten->type != GF_STENCIL_SOLID) {
1238
0
    rc = surf->path_bounds;
1239
0
    if (surf->is_shader) {
1240
0
      EVG_Texture *_tx = (EVG_Texture *)sten;
1241
0
      _tx->width = (u32) rc.width;
1242
0
      _tx->height = (u32) rc.height;
1243
0
      _tx->cmat.identity = 1;
1244
0
      _tx->alpha = 255;
1245
0
      gf_mx2d_init(_tx->smat);
1246
0
      gf_mx2d_add_translation(&_tx->smat, rc.width/2, rc.height/2);
1247
0
      gf_mx2d_add_matrix(&_tx->smat, &surf->shader_mx);
1248
//      _tx->fill_run = tex_fill_run;
1249
0
      _tx->tx_get_pixel = shader_get_pix;
1250
0
      _tx->tx_get_pixel_wide = shader_get_pix_wide;
1251
0
      _tx->is_wide = 1;
1252
      
1253
0
      _tx->is_yuv = surf->yuv_type ? 1 : 0;
1254
0
    }
1255
0
    gf_mx2d_apply_rect(mat, &rc);
1256
0
    rc.x = rc.y = 0;
1257
    /*assign target frame and matrix*/
1258
0
    sten->frame = rc;
1259
0
    gf_mx2d_copy(sten->pmat, surf->mat);
1260
0
    gf_mx2d_inverse(&sten->pmat);
1261
1262
0
    gf_mx2d_copy(sten->smat_bck, sten->smat);
1263
0
    gf_mx2d_init(sten->smat);
1264
1265
0
    switch (sten->type) {
1266
0
    case GF_STENCIL_TEXTURE:
1267
1268
      //in 3D mode, we only need the orginal stencil matrix
1269
0
      if (!surf->is_3d_matrix) {
1270
0
        if (!surf->is_shader) {
1271
0
          EVG_Texture *texture = (EVG_Texture *) sten;
1272
0
          if (!texture->tx_callback && ! texture->pixels)
1273
0
            return GF_BAD_PARAM;
1274
1275
0
          if (texture->mod & GF_TEXTURE_FLIP_Y) {
1276
0
            if (!surf->center_coords) gf_mx2d_add_scale(&sten->smat, FIX_ONE, -FIX_ONE);
1277
0
          } else {
1278
0
            if (surf->center_coords) gf_mx2d_add_scale(&sten->smat, FIX_ONE, -FIX_ONE);
1279
0
          }
1280
0
        }
1281
1282
        //add texture transform (normalized)
1283
0
        gf_mx2d_add_matrix(&sten->smat, &sten->smat_bck);
1284
0
        if (sten->auto_mx) {
1285
0
          EVG_Texture *_tx = (EVG_Texture *)sten;
1286
          //move translation to texture size
1287
0
          sten->smat.m[2] *= _tx->width;
1288
0
          sten->smat.m[5] *= _tx->height;
1289
          //in auto mx, matrix is given inverted, as in OpenGL
1290
0
          gf_mx2d_inverse(&sten->smat);
1291
1292
          //add texture -> untransformed path bounds matrix scale and translation
1293
0
          gf_mx2d_add_scale(&sten->smat, surf->path_bounds.width/_tx->width, surf->path_bounds.height/_tx->height);
1294
0
          gf_mx2d_add_translation(&sten->smat, -surf->path_bounds.width/2, surf->path_bounds.height/2);
1295
1296
          //add final path matrix
1297
0
          gf_mx2d_add_matrix(&sten->smat, &surf->shader_mx);
1298
0
        }
1299
1300
        //add surface matrix matrix
1301
0
        gf_mx2d_add_matrix(&sten->smat, mat);
1302
0
        gf_mx2d_inverse(&sten->smat);
1303
0
      } else {
1304
0
        if (!sten->auto_mx) {
1305
0
          return GF_NOT_SUPPORTED;
1306
0
        }
1307
0
      }
1308
1309
0
      evg_texture_init(sten, surf);
1310
0
      if (surf->is_shader) {
1311
0
        EVG_Texture *_tx = (EVG_Texture *)sten;
1312
0
        _tx->tx_get_pixel = shader_get_pix;
1313
0
        _tx->tx_get_pixel_wide = shader_get_pix_wide;
1314
0
      }
1315
0
      break;
1316
0
    case GF_STENCIL_LINEAR_GRADIENT:
1317
0
    {
1318
0
      EVG_LinearGradient *lin = (EVG_LinearGradient *)sten;
1319
0
      gf_mx2d_copy(sten->smat, sten->smat_bck);
1320
0
      if (!surf->is_3d_matrix) {
1321
0
        if (sten->auto_mx) {
1322
          //add [0,1] -> untransformed path bounds and path translation
1323
0
          gf_mx2d_add_translation(&sten->smat, gf_divfix(surf->path_bounds.x, surf->path_bounds.width), gf_divfix(surf->path_bounds.y, surf->path_bounds.height));
1324
0
          gf_mx2d_add_scale(&sten->smat, surf->path_bounds.width, surf->path_bounds.height);
1325
0
          gf_mx2d_add_matrix(&sten->smat, &surf->shader_mx);
1326
0
        }
1327
0
        gf_mx2d_add_matrix(&sten->smat, mat);
1328
0
      } else {
1329
0
        if (!sten->auto_mx) {
1330
0
          return GF_NOT_SUPPORTED;
1331
0
        }
1332
0
      }
1333
0
      gf_mx2d_inverse(&sten->smat);
1334
      /*and finalize matrix in gradient coord system*/
1335
0
      gf_mx2d_add_matrix(&sten->smat, &lin->vecmat);
1336
0
      gf_mx2d_add_scale(&sten->smat, INT2FIX(1<<EVGGRADIENTBITS), INT2FIX(1<<EVGGRADIENTBITS));
1337
1338
      /*init*/
1339
0
      evg_gradient_precompute((EVG_BaseGradient *)lin, surf);
1340
0
    }
1341
0
    break;
1342
0
    case GF_STENCIL_RADIAL_GRADIENT:
1343
0
    {
1344
0
      EVG_RadialGradient *rad = (EVG_RadialGradient*)sten;
1345
0
      gf_mx2d_copy(sten->smat, sten->smat_bck);
1346
0
      if (!surf->is_3d_matrix) {
1347
0
        if (sten->auto_mx) {
1348
          //add [0,1] -> untransformed path bounds and path translation
1349
0
          gf_mx2d_add_translation(&sten->smat, gf_divfix(surf->path_bounds.x, surf->path_bounds.width), gf_divfix(surf->path_bounds.y, surf->path_bounds.height));
1350
0
          gf_mx2d_add_scale(&sten->smat, surf->path_bounds.width, surf->path_bounds.height);
1351
0
          gf_mx2d_add_matrix(&sten->smat, &surf->shader_mx);
1352
0
        }
1353
0
        gf_mx2d_add_matrix(&sten->smat, mat);
1354
0
      } else {
1355
0
        if (!sten->auto_mx) {
1356
0
          return GF_NOT_SUPPORTED;
1357
0
        }
1358
0
      }
1359
0
      gf_mx2d_inverse(&sten->smat);
1360
0
      gf_mx2d_add_translation(&sten->smat, -rad->center.x, -rad->center.y);
1361
0
      gf_mx2d_add_scale(&sten->smat, gf_invfix(rad->radius.x), gf_invfix(rad->radius.y));
1362
1363
0
      rad->d_f.x = gf_divfix(rad->focus.x - rad->center.x, rad->radius.x);
1364
0
      rad->d_f.y = gf_divfix(rad->focus.y - rad->center.y, rad->radius.y);
1365
1366
      /*init*/
1367
0
      evg_radial_init(rad);
1368
0
      evg_gradient_precompute((EVG_BaseGradient *)rad, surf);
1369
0
    }
1370
0
    break;
1371
0
    }
1372
0
  } else {
1373
0
    EVG_Brush *sc = (EVG_Brush *) sten;
1374
0
    u32 col = sc->color;
1375
0
    if (sc->alpha < 0xFF) {
1376
0
      u32 ca = ((u32) (GF_COL_A(col) + 1) * sc->alpha) >> 8;
1377
0
      col = ( ((ca<<24) & 0xFF000000) ) | (col & 0x00FFFFFF);
1378
0
    }
1379
0
    if (surf->yuv_type) {
1380
0
      sc->fill_col = gf_evg_argb_to_ayuv(surf, col);
1381
0
    } else {
1382
0
      sc->fill_col = col;
1383
0
    }
1384
0
    if (surf->not_8bits)
1385
0
      sc->fill_col_wide = evg_col_to_wide(sc->fill_col);
1386
0
  }
1387
0
  return GF_OK;
1388
0
}
1389
1390
static void gf_evg_restore_stencil(GF_EVGSurface *surf, GF_EVGStencil *sten)
1391
0
{
1392
  /*restore stencil matrix*/
1393
0
  if (sten->type != GF_STENCIL_SOLID) {
1394
0
    gf_mx2d_copy(sten->smat, sten->smat_bck);
1395
0
  }
1396
0
}
1397
1398
GF_EXPORT
1399
GF_Err gf_evg_surface_multi_fill(GF_EVGSurface *surf, GF_EVGMultiTextureMode operand, GF_EVGStencil *sten1, GF_EVGStencil *sten2, GF_EVGStencil *sten3, Float params[4])
1400
0
{
1401
0
  GF_Err e;
1402
0
  Bool reset_aa = GF_FALSE;
1403
0
  u32 max_gray;
1404
0
  GF_Matrix2D mat;
1405
0
  if (!surf || (!sten1 && !surf->frag_shader) ) return GF_BAD_PARAM;
1406
0
  if (!surf->ftoutline.n_points) return GF_OK;
1407
0
  surf->sten = sten1;
1408
0
  surf->update_run = NULL;
1409
1410
  /*setup ft raster callbacks*/
1411
0
  if (!setup_grey_callback(surf, GF_FALSE, sten2 ? GF_TRUE : GF_FALSE)) return GF_OK;
1412
1413
0
  get_surface_world_matrix(surf, &mat);
1414
0
  surf->is_shader = GF_FALSE;
1415
0
  if (!sten1) {
1416
0
    sten1 = (GF_EVGStencil *) &surf->shader_sten;
1417
0
    sten1->type = GF_STENCIL_TEXTURE;
1418
0
    surf->is_shader = GF_TRUE;
1419
0
    surf->sten = sten1;
1420
0
    operand = GF_EVG_OPERAND_NONE;
1421
0
  }
1422
1423
0
  e = gf_evg_setup_stencil(surf, sten1, &mat);
1424
0
  if (e) return e;
1425
1426
0
  if (operand) {
1427
0
    e = gf_evg_setup_multi_texture(surf, operand, sten2, sten3, params);
1428
0
    if (e) return e;
1429
0
    if (sten2 && (sten2 != sten1)) {
1430
0
      e = gf_evg_setup_stencil(surf, sten2, &mat);
1431
0
      if (e) return e;
1432
0
    }
1433
0
    if (sten3 && (sten3 != sten1) && (sten3 != sten2)) {
1434
0
      e = gf_evg_setup_stencil(surf, sten3, &mat);
1435
0
      if (e) return e;
1436
0
    }
1437
0
  }
1438
1439
0
  if (!surf->aa_level) {
1440
    //no AA
1441
0
    if (surf->qlevel == GF_RASTER_HIGH_SPEED) surf->aa_level = 0;
1442
    //skip pixles with less than 25% coverage
1443
0
    else if (surf->qlevel == GF_RASTER_MID) surf->aa_level = 63;
1444
0
    else surf->aa_level = 0xFF;
1445
0
    reset_aa = GF_TRUE;
1446
0
  }
1447
1448
1449
0
  max_gray = surf->max_gray_spans;
1450
  /*force complete line callback for YUV 420/422*/
1451
0
  if (surf->yuv_type==EVG_YUV)
1452
0
    surf->max_gray_spans = 0xFFFFFFFF;
1453
1454
0
  if (surf->useClipper) {
1455
0
    surf->clip_xMin = surf->clipper.x;
1456
0
    surf->clip_yMin = surf->clipper.y;
1457
0
    surf->clip_xMax = (surf->clipper.x + surf->clipper.width);
1458
0
    surf->clip_yMax = (surf->clipper.y + surf->clipper.height);
1459
0
  } else {
1460
0
    surf->clip_xMin = 0;
1461
0
    surf->clip_yMin = 0;
1462
0
    surf->clip_xMax = (surf->width);
1463
0
    surf->clip_yMax = (surf->height);
1464
0
  }
1465
1466
0
  if (surf->mask_mode == GF_EVGMASK_DRAW) {
1467
0
    u32 old_pitch_x = surf->pitch_x;
1468
0
    u32 old_pitch_y = surf->pitch_y;
1469
0
    u8 *old_pixels = surf->pixels;
1470
1471
0
    surf->pixels = surf->internal_mask;
1472
0
    surf->pitch_x = 1;
1473
0
    surf->pitch_y = surf->width;
1474
1475
    /*and call the raster*/
1476
0
    if (surf->is_3d_matrix)
1477
0
      e = evg_raster_render_path_3d(surf);
1478
0
    else
1479
0
      e = evg_raster_render(surf);
1480
1481
0
    surf->pitch_x = old_pitch_x;
1482
0
    surf->pitch_y = old_pitch_y;
1483
0
    surf->pixels = old_pixels;
1484
0
  } else {
1485
    /*and call the raster*/
1486
0
    if (surf->is_3d_matrix)
1487
0
      e = evg_raster_render_path_3d(surf);
1488
0
    else
1489
0
      e = evg_raster_render(surf);
1490
0
  }
1491
1492
0
  if (reset_aa) surf->aa_level = 0;
1493
1494
0
  surf->max_gray_spans = max_gray;
1495
1496
0
  gf_evg_restore_stencil(surf, sten1);
1497
0
  if (sten2) gf_evg_restore_stencil(surf, sten2);
1498
0
  if (sten3) gf_evg_restore_stencil(surf, sten3);
1499
0
  surf->sten = surf->sten2 = surf->sten3 = NULL;
1500
0
  return e;
1501
0
}
1502
1503
GF_EXPORT
1504
GF_Err gf_evg_surface_fill(GF_EVGSurface *surf, GF_EVGStencil *sten)
1505
0
{
1506
0
  return gf_evg_surface_multi_fill(surf, 0, sten, NULL, NULL, NULL);
1507
0
}
1508
1509
void gf_evg_surface_set_composite_mode(GF_EVGSurface *surf, GF_EVGCompositeMode comp_mode)
1510
0
{
1511
0
  if (surf) surf->comp_mode = comp_mode;
1512
0
}
1513
1514
void gf_evg_surface_set_alpha_callback(GF_EVGSurface *surf, u8 (*get_alpha)(void *udta, u8 src_alpha, s32 x, s32 y), void *cbk)
1515
0
{
1516
0
  if (surf) {
1517
0
    surf->get_alpha = get_alpha;
1518
0
    surf->get_alpha_udta = cbk;
1519
0
  }
1520
0
}
1521
1522
GF_Err gf_evg_surface_set_projection(GF_EVGSurface *surf, GF_Matrix *mx)
1523
0
{
1524
0
  if (!surf || !surf->ext3d) return GF_BAD_PARAM;
1525
0
  gf_mx_copy(surf->ext3d->proj, *mx);
1526
0
  return GF_OK;
1527
0
}
1528
GF_Err gf_evg_surface_set_modelview(GF_EVGSurface *surf, GF_Matrix *mx)
1529
0
{
1530
0
  if (!surf || !surf->ext3d) return GF_BAD_PARAM;
1531
0
  gf_mx_copy(surf->ext3d->modelview, *mx);
1532
0
  return GF_OK;
1533
0
}
1534
1535
GF_Err evg_raster_render3d(GF_EVGSurface *surf, u32 *indices, u32 nb_idx, Float *vertices, u32 nb_vertices, u32 nb_comp, GF_EVGPrimitiveType prim_type);
1536
1537
GF_Err gf_evg_surface_draw_array(GF_EVGSurface *surf, u32 *indices, u32 nb_idx, Float *vertices, u32 nb_vertices, u32 nb_comp, GF_EVGPrimitiveType prim_type)
1538
0
{
1539
0
  GF_Err e;
1540
0
  u32 max_gray;
1541
0
  if (!surf || !surf->ext3d) return GF_BAD_PARAM;
1542
1543
  /*setup ft raster callbacks*/
1544
0
  if (!setup_grey_callback(surf, GF_TRUE, GF_FALSE)) return GF_OK;
1545
1546
0
  if (surf->useClipper) {
1547
0
    surf->clip_xMin = surf->clipper.x;
1548
0
    surf->clip_yMin = surf->clipper.y;
1549
0
    surf->clip_xMax = (surf->clipper.x + surf->clipper.width);
1550
0
    surf->clip_yMax = (surf->clipper.y + surf->clipper.height);
1551
0
  } else {
1552
0
    surf->clip_xMin = 0;
1553
0
    surf->clip_yMin = 0;
1554
0
    surf->clip_xMax = (surf->width);
1555
0
    surf->clip_yMax = (surf->height);
1556
0
  }
1557
0
  max_gray = surf->max_gray_spans;
1558
  /*force complete line callback for YUV 420/422*/
1559
0
  if (surf->yuv_type==EVG_YUV)
1560
0
    surf->max_gray_spans = 0xFFFFFFFF;
1561
1562
0
  surf->aa_level = 0xFF;
1563
  
1564
  /*and call the raster*/
1565
0
  e = evg_raster_render3d(surf, indices, nb_idx, vertices, nb_vertices, nb_comp, prim_type);
1566
0
  surf->max_gray_spans =  max_gray;
1567
0
  return e;
1568
0
}
1569
1570
GF_Err evg_raster_render3d_path(GF_EVGSurface *surf, GF_Path *path, Float z);
1571
1572
GF_Err gf_evg_surface_draw_path(GF_EVGSurface *surf, GF_Path *path, Float z)
1573
0
{
1574
0
  GF_Err e;
1575
0
  u32 max_gray;
1576
0
  if (!surf || !surf->ext3d) return GF_BAD_PARAM;
1577
1578
  /*setup ft raster callbacks*/
1579
0
  if (!setup_grey_callback(surf, GF_TRUE, GF_FALSE)) return GF_OK;
1580
1581
0
  if (surf->useClipper) {
1582
0
    surf->clip_xMin = surf->clipper.x;
1583
0
    surf->clip_yMin = surf->clipper.y;
1584
0
    surf->clip_xMax = (surf->clipper.x + surf->clipper.width);
1585
0
    surf->clip_yMax = (surf->clipper.y + surf->clipper.height);
1586
0
  } else {
1587
0
    surf->clip_xMin = 0;
1588
0
    surf->clip_yMin = 0;
1589
0
    surf->clip_xMax = (surf->width);
1590
0
    surf->clip_yMax = (surf->height);
1591
0
  }
1592
0
  max_gray = surf->max_gray_spans;
1593
  /*force complete line callback for YUV 420/422*/
1594
0
  if (surf->yuv_type==EVG_YUV)
1595
0
    surf->max_gray_spans = 0xFFFFFFFF;
1596
1597
0
  surf->aa_level = 0xFF;
1598
1599
  /*and call the raster*/
1600
0
  e = evg_raster_render3d_path(surf, path, z);
1601
0
  surf->max_gray_spans =  max_gray;
1602
0
  return e;
1603
0
}
1604
1605
1606
GF_Err gf_evg_surface_set_mask_mode(GF_EVGSurface *surf, GF_EVGMaskMode mask_mode)
1607
0
{
1608
0
  if (!surf) return GF_BAD_PARAM;
1609
1610
0
  if ((mask_mode==GF_EVGMASK_DRAW)
1611
0
    || (mask_mode==GF_EVGMASK_DRAW_NO_CLEAR)
1612
0
    || (mask_mode==GF_EVGMASK_RECORD)
1613
0
  ) {
1614
0
    u8 clear_val = 0;
1615
0
    Bool clear_mask = GF_FALSE;
1616
0
    if (!surf->internal_mask) {
1617
0
      surf->internal_mask = gf_malloc(sizeof(u8) * surf->width * surf->height);
1618
0
      if (!surf->internal_mask) return GF_OUT_OF_MEM;
1619
0
      clear_mask = GF_TRUE;
1620
0
    }
1621
0
    if ((mask_mode==GF_EVGMASK_DRAW) && (surf->mask_mode != GF_EVGMASK_DRAW))
1622
0
      clear_mask = GF_TRUE;
1623
1624
0
    if (mask_mode==GF_EVGMASK_RECORD) {
1625
0
      clear_mask = GF_TRUE;
1626
0
      clear_val = 0xFF;
1627
0
    } else {
1628
0
      mask_mode = GF_EVGMASK_DRAW;
1629
0
    }
1630
1631
0
    if (clear_mask) {
1632
0
      memset(surf->internal_mask, clear_val, sizeof(u8) * surf->width * surf->height);
1633
0
    }
1634
0
  }
1635
0
  surf->mask_mode = mask_mode;
1636
0
  return GF_OK;
1637
0
}
1638
1639
GF_EVGMaskMode gf_evg_surface_get_mask_mode(GF_EVGSurface *surf)
1640
0
{
1641
0
  if (!surf) return GF_EVGMASK_NONE;
1642
0
  return surf->mask_mode;
1643
0
}
1644
1645
#endif // GPAC_DISABLE_EVG