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
27
28 #include "rast_soft.h"
29
get_surface_world_matrix(GF_EVGSurface * surf,GF_Matrix2D * mat)30 static void get_surface_world_matrix(GF_EVGSurface *surf, GF_Matrix2D *mat)
31 {
32 gf_mx2d_init(*mat);
33 if (surf->center_coords) {
34 gf_mx2d_add_scale(mat, FIX_ONE, -FIX_ONE);
35 gf_mx2d_add_translation(mat, INT2FIX(surf->width / 2), INT2FIX(surf->height / 2));
36 }
37 }
38
39 GF_EXPORT
gf_evg_surface_new(Bool center_coords)40 GF_EVGSurface *gf_evg_surface_new(Bool center_coords)
41 {
42 GF_EVGSurface *surf;
43 GF_SAFEALLOC(surf, GF_EVGSurface);
44 if (surf) {
45 surf->center_coords = center_coords;
46 surf->texture_filter = GF_TEXTURE_FILTER_DEFAULT;
47 surf->raster = evg_raster_new();
48 surf->yuv_prof=1;
49 }
50 return surf;
51 }
52
53 EVG_Surface3DExt *evg_init_3d_surface(GF_EVGSurface *surf);
54
55 GF_EXPORT
gf_evg_surface3d_new()56 GF_EVGSurface *gf_evg_surface3d_new()
57 {
58 GF_EVGSurface *surf;
59 GF_SAFEALLOC(surf, GF_EVGSurface);
60 if (surf) {
61 surf->texture_filter = GF_TEXTURE_FILTER_DEFAULT;
62 surf->raster = evg_raster_new();
63 surf->yuv_prof=1;
64
65 surf->ext3d = evg_init_3d_surface(surf);
66 if (!surf->ext3d) {
67 gf_free(surf);
68 return NULL;
69 }
70 }
71 return surf;
72 }
73
74 GF_EXPORT
gf_evg_surface_set_center_coords(GF_EVGSurface * surf,Bool center_coords)75 void gf_evg_surface_set_center_coords(GF_EVGSurface *surf, Bool center_coords)
76 {
77 if (surf) surf->center_coords = center_coords;
78 }
79
80 GF_EXPORT
gf_evg_surface_delete(GF_EVGSurface * surf)81 void gf_evg_surface_delete(GF_EVGSurface *surf)
82 {
83 if (!surf)
84 return;
85 if (surf->stencil_pix_run) gf_free(surf->stencil_pix_run);
86 surf->stencil_pix_run = NULL;
87 if (surf->raster) evg_raster_del(surf->raster);
88 surf->raster = NULL;
89 if (surf->uv_alpha) gf_free(surf->uv_alpha);
90
91 if (surf->ext3d) {
92 if (surf->ext3d->pix_vals)
93 gf_free(surf->ext3d->pix_vals);
94 gf_free(surf->ext3d);
95 }
96 gf_free(surf);
97 }
98
99 GF_EXPORT
gf_evg_surface_set_matrix(GF_EVGSurface * surf,GF_Matrix2D * mat)100 GF_Err gf_evg_surface_set_matrix(GF_EVGSurface *surf, GF_Matrix2D *mat)
101 {
102 GF_Matrix2D tmp;
103 if (!surf) return GF_BAD_PARAM;
104 get_surface_world_matrix(surf, &surf->mat);
105 surf->is_3d_matrix = GF_FALSE;
106 if (!mat) return GF_OK;
107
108 gf_mx2d_init(tmp);
109 gf_mx2d_add_matrix(&tmp, mat);
110 gf_mx2d_add_matrix(&tmp, &surf->mat);
111 gf_mx2d_copy(surf->mat, tmp);
112 return GF_OK;
113 }
114
115 GF_EXPORT
gf_evg_surface_set_matrix_3d(GF_EVGSurface * surf,GF_Matrix * mat)116 GF_Err gf_evg_surface_set_matrix_3d(GF_EVGSurface *surf, GF_Matrix *mat)
117 {
118 if (!surf) return GF_BAD_PARAM;
119 get_surface_world_matrix(surf, &surf->mat);
120 surf->is_3d_matrix = GF_FALSE;
121 if (!mat) return GF_OK;
122 gf_mx_copy(surf->mx3d, *mat);
123 surf->is_3d_matrix = GF_TRUE;
124 return GF_OK;
125 }
126
evg_surface_set_components_idx(GF_EVGSurface * surf)127 static void evg_surface_set_components_idx(GF_EVGSurface *surf)
128 {
129 surf->idx_y1=surf->idx_u=surf->idx_v=0;
130 surf->idx_a=surf->idx_r=surf->idx_g=surf->idx_b=0;
131 switch (surf->pixelFormat) {
132 case GF_PIXEL_YUYV:
133 surf->idx_y1=0;
134 surf->idx_u=1;
135 surf->idx_v=3;
136 break;
137 case GF_PIXEL_YVYU:
138 surf->idx_y1=0;
139 surf->idx_u=3;
140 surf->idx_v=1;
141 break;
142 case GF_PIXEL_UYVY:
143 surf->idx_y1=1;
144 surf->idx_u=0;
145 surf->idx_v=2;
146 break;
147 case GF_PIXEL_VYUY:
148 surf->idx_y1=1;
149 surf->idx_u=2;
150 surf->idx_v=0;
151 break;
152 case GF_PIXEL_ALPHAGREY:
153 surf->idx_a = 0;
154 surf->idx_g = 1;
155 break;
156 case GF_PIXEL_GREYALPHA:
157 surf->idx_a = 1;
158 surf->idx_g = 0;
159 break;
160 case GF_PIXEL_ARGB:
161 surf->idx_a=0;
162 surf->idx_r=1;
163 surf->idx_g=2;
164 surf->idx_b=3;
165 break;
166 case GF_PIXEL_RGBA:
167 surf->idx_a=3;
168 surf->idx_r=0;
169 surf->idx_g=1;
170 surf->idx_b=2;
171 break;
172 case GF_PIXEL_BGRA:
173 surf->idx_a=3;
174 surf->idx_r=2;
175 surf->idx_g=1;
176 surf->idx_b=0;
177 break;
178 case GF_PIXEL_ABGR:
179 surf->idx_a=0;
180 surf->idx_r=3;
181 surf->idx_g=2;
182 surf->idx_b=1;
183 break;
184 case GF_PIXEL_RGBX:
185 surf->idx_r=0;
186 surf->idx_g=1;
187 surf->idx_b=2;
188 surf->idx_a=3;
189 break;
190 case GF_PIXEL_BGRX:
191 surf->idx_r=2;
192 surf->idx_g=1;
193 surf->idx_b=0;
194 surf->idx_a=3;
195 break;
196 case GF_PIXEL_XRGB:
197 surf->idx_a=0;
198 surf->idx_r=1;
199 surf->idx_g=2;
200 surf->idx_b=3;
201 break;
202 case GF_PIXEL_XBGR:
203 surf->idx_a=0;
204 surf->idx_r=3;
205 surf->idx_g=2;
206 surf->idx_b=1;
207 break;
208 case GF_PIXEL_RGB:
209 surf->idx_r=0;
210 surf->idx_g=1;
211 surf->idx_b=2;
212 break;
213 case GF_PIXEL_BGR:
214 surf->idx_r=2;
215 surf->idx_g=1;
216 surf->idx_b=0;
217 break;
218 }
219 }
220
221 GF_Err evg_3d_resize(GF_EVGSurface *surf);
222
223
224 GF_EXPORT
gf_evg_surface_attach_to_buffer(GF_EVGSurface * surf,u8 * pixels,u32 width,u32 height,s32 pitch_x,s32 pitch_y,GF_PixelFormat pixelFormat)225 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)
226 {
227 u32 BPP;
228 Bool size_changed=GF_FALSE;
229 if (!surf || !pixels) return GF_BAD_PARAM;
230
231 surf->is_transparent = GF_FALSE;
232 surf->not_8bits = GF_FALSE;
233 switch (pixelFormat) {
234 case GF_PIXEL_GREYSCALE:
235 BPP = 1;
236 break;
237 case GF_PIXEL_ALPHAGREY:
238 case GF_PIXEL_GREYALPHA:
239 BPP = 2;
240 surf->is_transparent = GF_TRUE;
241 break;
242 case GF_PIXEL_RGB_444:
243 case GF_PIXEL_RGB_555:
244 case GF_PIXEL_RGB_565:
245 BPP = 2;
246 break;
247 case GF_PIXEL_ARGB:
248 case GF_PIXEL_BGRA:
249 case GF_PIXEL_RGBA:
250 case GF_PIXEL_ABGR:
251 surf->is_transparent = GF_TRUE;
252 case GF_PIXEL_RGBX:
253 case GF_PIXEL_BGRX:
254 case GF_PIXEL_XRGB:
255 case GF_PIXEL_XBGR:
256 BPP = 4;
257 break;
258 case GF_PIXEL_BGR:
259 case GF_PIXEL_RGB:
260 BPP = 3;
261 break;
262 case GF_PIXEL_YUV:
263 case GF_PIXEL_NV12:
264 case GF_PIXEL_NV21:
265 case GF_PIXEL_YUV422:
266 case GF_PIXEL_YUV444:
267 case GF_PIXEL_YUYV:
268 case GF_PIXEL_YVYU:
269 case GF_PIXEL_UYVY:
270 case GF_PIXEL_VYUY:
271 BPP = 1;
272 break;
273 case GF_PIXEL_YUV_10:
274 case GF_PIXEL_NV12_10:
275 case GF_PIXEL_NV21_10:
276 case GF_PIXEL_YUV422_10:
277 case GF_PIXEL_YUV444_10:
278 BPP = 2;
279 surf->not_8bits = GF_TRUE;
280 break;
281 default:
282 return GF_NOT_SUPPORTED;
283 }
284 if (!pitch_x) pitch_x = BPP;
285 surf->pitch_x = pitch_x;
286 surf->pitch_y = pitch_y;
287 if (!surf->stencil_pix_run || (surf->width != width)) {
288 u32 run_size = sizeof(u32) * (width+2);
289 if (surf->not_8bits) run_size *= 2;
290 if (surf->stencil_pix_run) gf_free(surf->stencil_pix_run);
291 surf->stencil_pix_run = (u32 *) gf_malloc(run_size);
292 }
293 if (surf->width != width) {
294 surf->width = width;
295 size_changed = GF_TRUE;
296 }
297 if (surf->height != height) {
298 surf->height = height;
299 size_changed = GF_TRUE;
300 }
301 surf->pixels = (char*)pixels;
302 surf->pixelFormat = pixelFormat;
303 surf->BPP = BPP;
304 evg_surface_set_components_idx(surf);
305 gf_evg_surface_set_matrix(surf, NULL);
306 if (surf->ext3d && size_changed)
307 evg_3d_resize(surf);
308 return GF_OK;
309 }
310
311
312 GF_EXPORT
gf_evg_surface_attach_to_texture(GF_EVGSurface * surf,GF_EVGStencil * sten)313 GF_Err gf_evg_surface_attach_to_texture(GF_EVGSurface *surf, GF_EVGStencil * sten)
314 {
315 EVG_Texture *tx = (EVG_Texture *) sten;
316 if (!surf || (tx->type != GF_STENCIL_TEXTURE)) return GF_BAD_PARAM;
317
318 return gf_evg_surface_attach_to_buffer(surf, tx->pixels, tx->width, tx->height, 0, tx->stride, tx->pixel_format);
319 }
320
321
322 GF_EXPORT
gf_evg_surface_clear(GF_EVGSurface * surf,GF_IRect * rc,u32 color)323 GF_Err gf_evg_surface_clear(GF_EVGSurface *surf, GF_IRect *rc, u32 color)
324 {
325 GF_IRect clear;
326 if (!surf) return GF_BAD_PARAM;
327
328 if (rc) {
329 s32 _x, _y;
330 if (surf->center_coords) {
331 _x = rc->x + surf->width / 2;
332 _y = surf->height / 2 - rc->y;
333 } else {
334 _x = rc->x;
335 _y = rc->y - rc->height;
336 }
337 /*clip is outside our bounds, ignore*/
338 if ((_x>=(s32) surf->width) || (_x + rc->width < 0))
339 return GF_OK;
340 if ((_y>= (s32) surf->height) || (_y + rc->height < 0))
341 return GF_OK;
342
343 clear.width = (u32) rc->width;
344 if (_x>=0) {
345 clear.x = (u32) _x;
346 } else {
347 if ( (s32) clear.width + _x < 0) return GF_BAD_PARAM;
348 clear.width += _x;
349 clear.x = 0;
350 }
351 if (clear.x + clear.width > (s32) surf->width)
352 clear.width = surf->width - clear.x;
353
354 if (!clear.width)
355 return GF_OK;
356
357 clear.height = (u32) rc->height;
358 if (_y>=0) {
359 clear.y = _y;
360 } else {
361 if ( (s32) clear.height + _y < 0) return GF_BAD_PARAM;
362 clear.height += _y;
363 clear.y = 0;
364 }
365 if (clear.y + clear.height > (s32) surf->height)
366 clear.height = surf->height - clear.y;
367
368 if (!clear.height)
369 return GF_OK;
370 } else {
371 clear.x = clear.y = 0;
372 clear.width = surf->width;
373 clear.height = surf->height;
374 }
375
376 switch (surf->pixelFormat) {
377 /*RGB formats*/
378 case GF_PIXEL_GREYSCALE:
379 return evg_surface_clear_grey(surf, clear, color);
380 case GF_PIXEL_ALPHAGREY:
381 case GF_PIXEL_GREYALPHA:
382 return evg_surface_clear_alphagrey(surf, clear, color);
383 case GF_PIXEL_ARGB:
384 case GF_PIXEL_BGRA:
385 case GF_PIXEL_RGBA:
386 case GF_PIXEL_ABGR:
387 return evg_surface_clear_argb(surf, clear, color);
388
389 case GF_PIXEL_RGBX:
390 case GF_PIXEL_BGRX:
391 case GF_PIXEL_XRGB:
392 case GF_PIXEL_XBGR:
393 return evg_surface_clear_rgbx(surf, clear, color);
394
395 case GF_PIXEL_RGB:
396 case GF_PIXEL_BGR:
397 return evg_surface_clear_rgb(surf, clear, color);
398 case GF_PIXEL_RGB_444:
399 return evg_surface_clear_444(surf, clear, color);
400 case GF_PIXEL_RGB_555:
401 return evg_surface_clear_555(surf, clear, color);
402 case GF_PIXEL_RGB_565:
403 return evg_surface_clear_565(surf, clear, color);
404
405 /*YUV formats*/
406 case GF_PIXEL_YUV:
407 return evg_surface_clear_yuv420p(surf, clear, color);
408 case GF_PIXEL_YUV422:
409 return evg_surface_clear_yuv422p(surf, clear, color);
410 case GF_PIXEL_NV12:
411 return evg_surface_clear_nv12(surf, clear, color, GF_FALSE);
412 case GF_PIXEL_NV21:
413 return evg_surface_clear_nv12(surf, clear, color, GF_TRUE);
414 case GF_PIXEL_YUV444:
415 return evg_surface_clear_yuv444p(surf, clear, color);
416 case GF_PIXEL_YUYV:
417 case GF_PIXEL_YVYU:
418 case GF_PIXEL_UYVY:
419 case GF_PIXEL_VYUY:
420 return evg_surface_clear_yuyv(surf, clear, color);
421 case GF_PIXEL_YUV_10:
422 return evg_surface_clear_yuv420p_10(surf, clear, color);
423 case GF_PIXEL_NV12_10:
424 return evg_surface_clear_nv12_10(surf, clear, color, GF_FALSE);
425 case GF_PIXEL_NV21_10:
426 return evg_surface_clear_nv12_10(surf, clear, color, GF_TRUE);
427 case GF_PIXEL_YUV422_10:
428 return evg_surface_clear_yuv422p_10(surf, clear, color);
429 case GF_PIXEL_YUV444_10:
430 return evg_surface_clear_yuv444p_10(surf, clear, color);
431 default:
432 return GF_BAD_PARAM;
433 }
434 }
435
436 GF_EXPORT
gf_evg_surface_set_raster_level(GF_EVGSurface * surf,GF_RasterQuality RasterSetting)437 GF_Err gf_evg_surface_set_raster_level(GF_EVGSurface *surf, GF_RasterQuality RasterSetting)
438 {
439 if (!surf) return GF_BAD_PARAM;
440 switch (RasterSetting) {
441 case GF_RASTER_HIGH_QUALITY:
442 surf->texture_filter = GF_TEXTURE_FILTER_HIGH_QUALITY;
443 break;
444 case GF_RASTER_MID:
445 surf->texture_filter = GF_TEXTURE_FILTER_HIGH_QUALITY;
446 break;
447 case GF_RASTER_HIGH_SPEED:
448 default:
449 surf->texture_filter = GF_TEXTURE_FILTER_HIGH_SPEED;
450 break;
451 }
452 return GF_OK;
453 }
454
455
456 GF_EXPORT
gf_evg_surface_set_clipper(GF_EVGSurface * surf,GF_IRect * rc)457 GF_Err gf_evg_surface_set_clipper(GF_EVGSurface *surf , GF_IRect *rc)
458 {
459 if (!surf) return GF_BAD_PARAM;
460 if (rc) {
461 surf->clipper = *rc;
462 surf->useClipper = 1;
463 /*clipper was given in BIFS like coords, we work with bottom-min for rect, (0,0) top-left of surface*/
464 if (surf->center_coords) {
465 surf->clipper.x += surf->width / 2;
466 surf->clipper.y = surf->height / 2 - rc->y;
467 } else {
468 surf->clipper.y -= rc->height;
469 }
470
471 if (surf->clipper.x <=0) {
472 if (surf->clipper.x + (s32) surf->clipper.width < 0) return GF_BAD_PARAM;
473 surf->clipper.width += surf->clipper.x;
474 surf->clipper.x = 0;
475 }
476 if (surf->clipper.y <=0) {
477 if (surf->clipper.y + (s32) surf->clipper.height < 0) return GF_BAD_PARAM;
478 surf->clipper.height += surf->clipper.y;
479 surf->clipper.y = 0;
480 }
481 if (surf->clipper.x + surf->clipper.width > (s32) surf->width) {
482 surf->clipper.width = surf->width - surf->clipper.x;
483 }
484 if (surf->clipper.y + surf->clipper.height > (s32) surf->height) {
485 surf->clipper.height = surf->height - surf->clipper.y;
486 }
487 } else {
488 surf->useClipper = 0;
489 }
490 return GF_OK;
491 }
492
493
setup_grey_callback(GF_EVGSurface * surf,Bool for_3d)494 static Bool setup_grey_callback(GF_EVGSurface *surf, Bool for_3d)
495 {
496 u32 a, uv_alpha_size=0;
497 Bool use_const = GF_TRUE;
498
499 //in 3D mode, we only write one pixel at a time except in YUV modes
500 if (for_3d) {
501 a = 1;
502 use_const = GF_TRUE;
503 }
504 else if (surf->sten->type == GF_STENCIL_SOLID) {
505 surf->fill_col = ((EVG_Brush *)surf->sten)->color;
506 a = GF_COL_A(surf->fill_col);
507 } else {
508 a = 0;
509 use_const = GF_FALSE;
510 }
511
512 if (use_const && !a && !surf->is_transparent) return GF_FALSE;
513
514 surf->is_422 = GF_FALSE;
515 surf->yuv_type = 0;
516 surf->swap_uv = GF_FALSE;
517 surf->yuv_flush_uv = NULL;
518
519 if (surf->comp_mode) a=100;
520 else if (surf->get_alpha) a=100;
521 surf->fill_single = NULL;
522 surf->fill_single_a = NULL;
523
524 switch (surf->pixelFormat) {
525 case GF_PIXEL_GREYSCALE:
526 if (use_const) {
527 if (a!=0xFF) {
528 surf->gray_spans = (EVG_Raster_Span_Func) evg_grey_fill_const_a;
529 } else {
530 surf->gray_spans = (EVG_Raster_Span_Func) evg_grey_fill_const;
531 }
532 } else {
533 surf->gray_spans = (EVG_Raster_Span_Func) evg_grey_fill_var;
534 }
535 if (surf->ext3d) {
536 surf->fill_single = evg_grey_fill_single;
537 surf->fill_single_a = evg_grey_fill_single_a;
538 }
539 break;
540 case GF_PIXEL_ALPHAGREY:
541 case GF_PIXEL_GREYALPHA:
542 if (use_const) {
543 if (a!=0xFF) {
544 surf->gray_spans = (EVG_Raster_Span_Func) evg_alphagrey_fill_const_a;
545 } else {
546 surf->gray_spans = (EVG_Raster_Span_Func) evg_alphagrey_fill_const;
547 }
548 } else {
549 surf->gray_spans = (EVG_Raster_Span_Func) evg_alphagrey_fill_var;
550 }
551 if (surf->ext3d) {
552 surf->fill_single = evg_alphagrey_fill_single;
553 surf->fill_single_a = evg_alphagrey_fill_single_a;
554 }
555 break;
556 case GF_PIXEL_ARGB:
557 case GF_PIXEL_RGBA:
558 case GF_PIXEL_BGRA:
559 case GF_PIXEL_ABGR:
560 if (use_const) {
561 if (!a) {
562 surf->gray_spans = (EVG_Raster_Span_Func) evg_argb_fill_erase;
563 } else if (a!=0xFF) {
564 surf->gray_spans = (EVG_Raster_Span_Func) evg_argb_fill_const_a;
565 } else {
566 surf->gray_spans = (EVG_Raster_Span_Func) evg_argb_fill_const;
567 }
568 } else {
569 surf->gray_spans = (EVG_Raster_Span_Func) evg_argb_fill_var;
570 }
571 if (surf->ext3d) {
572 surf->fill_single = evg_argb_fill_single;
573 surf->fill_single_a = evg_argb_fill_single_a;
574 }
575 break;
576
577 case GF_PIXEL_RGBX:
578 case GF_PIXEL_BGRX:
579 case GF_PIXEL_XRGB:
580 case GF_PIXEL_XBGR:
581 if (use_const) {
582 if (a!=0xFF) {
583 surf->gray_spans = (EVG_Raster_Span_Func) evg_rgbx_fill_const_a;
584 } else {
585 surf->gray_spans = (EVG_Raster_Span_Func) evg_rgbx_fill_const;
586 }
587 } else {
588 surf->gray_spans = (EVG_Raster_Span_Func) evg_rgbx_fill_var;
589 }
590 if (surf->ext3d) {
591 surf->fill_single = evg_rgbx_fill_single;
592 surf->fill_single_a = evg_rgbx_fill_single_a;
593 }
594 break;
595
596 case GF_PIXEL_RGB:
597 case GF_PIXEL_BGR:
598 if (use_const) {
599 if (a!=0xFF) {
600 surf->gray_spans = (EVG_Raster_Span_Func) evg_rgb_fill_const_a;
601 } else {
602 surf->gray_spans = (EVG_Raster_Span_Func) evg_rgb_fill_const;
603 }
604 } else {
605 surf->gray_spans = (EVG_Raster_Span_Func) evg_rgb_fill_var;
606 }
607 if (surf->ext3d) {
608 surf->fill_single = evg_rgb_fill_single;
609 surf->fill_single_a = evg_rgb_fill_single_a;
610 }
611 break;
612
613 case GF_PIXEL_RGB_565:
614 if (use_const) {
615 if (a!=0xFF) {
616 surf->gray_spans = (EVG_Raster_Span_Func) evg_565_fill_const_a;
617 } else {
618 surf->gray_spans = (EVG_Raster_Span_Func) evg_565_fill_const;
619 }
620 } else {
621 surf->gray_spans = (EVG_Raster_Span_Func) evg_565_fill_var;
622 assert(surf->sten->fill_run);
623 }
624 if (surf->ext3d) {
625 surf->fill_single = evg_565_fill_single;
626 surf->fill_single_a = evg_565_fill_single_a;
627 }
628 break;
629 case GF_PIXEL_RGB_444:
630 if (use_const) {
631 if (a!=0xFF) {
632 surf->gray_spans = (EVG_Raster_Span_Func) evg_444_fill_const_a;
633 } else {
634 surf->gray_spans = (EVG_Raster_Span_Func) evg_444_fill_const;
635 }
636 } else {
637 surf->gray_spans = (EVG_Raster_Span_Func) evg_444_fill_var;
638 }
639 if (surf->ext3d) {
640 surf->fill_single = evg_444_fill_single;
641 surf->fill_single_a = evg_444_fill_single_a;
642 }
643 break;
644 case GF_PIXEL_RGB_555:
645 if (use_const) {
646 if (a!=0xFF) {
647 surf->gray_spans = (EVG_Raster_Span_Func) evg_555_fill_const_a;
648 } else {
649 surf->gray_spans = (EVG_Raster_Span_Func) evg_555_fill_const;
650 }
651 } else {
652 surf->gray_spans = (EVG_Raster_Span_Func) evg_555_fill_var;
653 }
654 if (surf->ext3d) {
655 surf->fill_single = evg_555_fill_single;
656 surf->fill_single_a = evg_555_fill_single_a;
657 }
658 break;
659 case GF_PIXEL_YUV:
660 surf->yuv_type = EVG_YUV;
661 if (use_const && !for_3d) {
662 surf->yuv_flush_uv = evg_yuv420p_flush_uv_const;
663
664 if (a!=0xFF) {
665 surf->gray_spans = (EVG_Raster_Span_Func) evg_yuv420p_fill_const_a;
666 } else {
667 surf->gray_spans = (EVG_Raster_Span_Func) evg_yuv420p_fill_const;
668 }
669 uv_alpha_size=2*surf->width;
670 } else {
671 surf->yuv_flush_uv = evg_yuv420p_flush_uv_var;
672 surf->gray_spans = (EVG_Raster_Span_Func) evg_yuv420p_fill_var;
673 uv_alpha_size = 2 * 3*surf->width;
674 if (for_3d)
675 surf->sten = &surf->ext3d->yuv_sten;
676 }
677 break;
678 case GF_PIXEL_NV21:
679 surf->swap_uv = GF_TRUE;
680 case GF_PIXEL_NV12:
681 surf->yuv_type = EVG_YUV;
682
683 if (surf->swap_uv) {
684 surf->idx_u = 1;
685 surf->idx_v = 0;
686 } else {
687 surf->idx_u = 0;
688 surf->idx_v = 1;
689 }
690
691 if (use_const && !for_3d) {
692 surf->yuv_flush_uv = evg_nv12_flush_uv_const;
693
694 if (a!=0xFF) {
695 surf->gray_spans = (EVG_Raster_Span_Func) evg_yuv420p_fill_const_a;
696 } else {
697 surf->gray_spans = (EVG_Raster_Span_Func) evg_yuv420p_fill_const;
698 }
699 uv_alpha_size = 2*surf->width;
700 } else {
701 surf->yuv_flush_uv = evg_nv12_flush_uv_var;
702 surf->gray_spans = (EVG_Raster_Span_Func) evg_yuv420p_fill_var;
703 uv_alpha_size = 2 * 3*surf->width;
704 }
705 break;
706 case GF_PIXEL_YUV422:
707 surf->yuv_type = EVG_YUV;
708 surf->is_422 = GF_TRUE;
709 if (use_const && !for_3d) {
710 surf->yuv_flush_uv = evg_yuv422p_flush_uv_const;
711
712 if (a!=0xFF) {
713 surf->gray_spans = (EVG_Raster_Span_Func) evg_yuv420p_fill_const_a;
714 } else {
715 surf->gray_spans = (EVG_Raster_Span_Func) evg_yuv420p_fill_const;
716 }
717 uv_alpha_size = 2*surf->width;
718 } else {
719 surf->yuv_flush_uv = evg_yuv422p_flush_uv_var;
720 surf->gray_spans = (EVG_Raster_Span_Func) evg_yuv420p_fill_var;
721 uv_alpha_size = 2 * 3*surf->width;
722 }
723 break;
724 case GF_PIXEL_YUV444:
725 surf->yuv_type = EVG_YUV_444;
726 if (use_const) {
727 if (a!=0xFF) {
728 surf->gray_spans = (EVG_Raster_Span_Func) evg_yuv444p_fill_const_a;
729 } else {
730 surf->gray_spans = (EVG_Raster_Span_Func) evg_yuv444p_fill_const;
731 }
732 } else {
733 surf->gray_spans = (EVG_Raster_Span_Func) evg_yuv444p_fill_var;
734 }
735 break;
736 case GF_PIXEL_YUYV:
737 case GF_PIXEL_YVYU:
738 case GF_PIXEL_UYVY:
739 case GF_PIXEL_VYUY:
740 surf->yuv_type = EVG_YUV;
741 if (use_const && !for_3d) {
742 if (a!=0xFF) {
743 surf->gray_spans = (EVG_Raster_Span_Func) evg_yuyv_fill_const_a;
744 } else {
745 surf->gray_spans = (EVG_Raster_Span_Func) evg_yuyv_fill_const;
746 }
747 uv_alpha_size = 2*surf->width;
748 } else {
749 surf->gray_spans = (EVG_Raster_Span_Func) evg_yuyv_fill_var;
750 uv_alpha_size = 2 * 3*surf->width;
751 }
752 break;
753
754 case GF_PIXEL_YUV_10:
755 surf->yuv_type = EVG_YUV;
756 if (use_const && !for_3d) {
757 surf->yuv_flush_uv = evg_yuv420p_10_flush_uv_const;
758
759 if (a!=0xFF) {
760 surf->gray_spans = (EVG_Raster_Span_Func) evg_yuv420p_10_fill_const_a;
761 } else {
762 surf->gray_spans = (EVG_Raster_Span_Func) evg_yuv420p_10_fill_const;
763 }
764 uv_alpha_size = 4*surf->width;
765 } else {
766 surf->yuv_flush_uv = evg_yuv420p_10_flush_uv_var;
767 surf->gray_spans = (EVG_Raster_Span_Func) evg_yuv420p_10_fill_var;
768 uv_alpha_size = 4*3*surf->width;
769 }
770 break;
771 case GF_PIXEL_NV21_10:
772 surf->swap_uv = GF_TRUE;
773 case GF_PIXEL_NV12_10:
774 surf->yuv_type = EVG_YUV;
775
776 if (surf->swap_uv) {
777 surf->idx_u = 1;
778 surf->idx_v = 0;
779 } else {
780 surf->idx_u = 0;
781 surf->idx_v = 1;
782 }
783
784 if (use_const && !for_3d) {
785 surf->yuv_flush_uv = evg_nv12_10_flush_uv_const;
786
787 if (a!=0xFF) {
788 surf->gray_spans = (EVG_Raster_Span_Func) evg_yuv420p_10_fill_const_a;
789 } else {
790 surf->gray_spans = (EVG_Raster_Span_Func) evg_yuv420p_10_fill_const;
791 }
792 uv_alpha_size = 4*surf->width;
793 } else {
794 surf->yuv_flush_uv = evg_nv12_10_flush_uv_var;
795 surf->gray_spans = (EVG_Raster_Span_Func) evg_yuv420p_10_fill_var;
796 uv_alpha_size = 4 * 3*surf->width;
797 }
798 break;
799 case GF_PIXEL_YUV422_10:
800 surf->yuv_type = EVG_YUV;
801 surf->is_422 = GF_TRUE;
802 if (use_const && !for_3d) {
803 surf->yuv_flush_uv = evg_yuv422p_10_flush_uv_const;
804
805 if (a!=0xFF) {
806 surf->gray_spans = (EVG_Raster_Span_Func) evg_yuv420p_10_fill_const_a;
807 } else {
808 surf->gray_spans = (EVG_Raster_Span_Func) evg_yuv420p_10_fill_const;
809 }
810 uv_alpha_size = 4*surf->width;
811 } else {
812 surf->yuv_flush_uv = evg_yuv422p_10_flush_uv_var;
813 surf->gray_spans = (EVG_Raster_Span_Func) evg_yuv420p_10_fill_var;
814 uv_alpha_size = 4 * 3*surf->width;
815 }
816 break;
817 case GF_PIXEL_YUV444_10:
818 surf->yuv_type = EVG_YUV_444;
819 if (use_const) {
820 if (a!=0xFF) {
821 surf->gray_spans = (EVG_Raster_Span_Func) evg_yuv444p_10_fill_const_a;
822 } else {
823 surf->gray_spans = (EVG_Raster_Span_Func) evg_yuv444p_10_fill_const;
824 }
825 } else {
826 surf->gray_spans = (EVG_Raster_Span_Func) evg_yuv444p_10_fill_var;
827 }
828 break;
829 default:
830 return GF_FALSE;
831 }
832
833 if (uv_alpha_size) {
834 if (surf->uv_alpha_alloc < uv_alpha_size) {
835 surf->uv_alpha_alloc = uv_alpha_size;
836 surf->uv_alpha = gf_realloc(surf->uv_alpha, uv_alpha_size);
837 memset(surf->uv_alpha, 0, uv_alpha_size);
838 }
839 memset(surf->uv_alpha, 0, sizeof(char)*surf->uv_alpha_alloc);
840 }
841 if (surf->yuv_type && for_3d)
842 surf->sten = &surf->ext3d->yuv_sten;
843
844 if (use_const && surf->yuv_type) {
845 u8 y, cb, cr;
846 gf_evg_rgb_to_yuv(surf, surf->fill_col, &y, &cb, &cr);
847 if (surf->swap_uv) {
848 u8 t = cb;
849 cb = cr;
850 cr = (u8) t;
851 surf->swap_uv = GF_FALSE;
852 }
853
854 surf->fill_col = GF_COL_ARGB(a, y, cb, cr);
855 surf->fill_col_wide = evg_col_to_wide(surf->fill_col);
856 }
857
858 return GF_TRUE;
859 }
860
861
862 GF_EXPORT
gf_evg_surface_set_path(GF_EVGSurface * surf,GF_Path * gp)863 GF_Err gf_evg_surface_set_path(GF_EVGSurface *surf, GF_Path *gp)
864 {
865 if (!surf) return GF_BAD_PARAM;
866 if (!gp || !gp->n_points) {
867 surf->ftoutline.n_points = 0;
868 surf->ftoutline.n_contours = 0;
869 return GF_OK;
870 }
871 gf_path_flatten(gp);
872 surf->ftoutline.n_points = gp->n_points;
873 surf->ftoutline.n_contours = gp->n_contours;
874
875 surf->ftoutline.tags = gp->tags;
876 surf->ftoutline.contours = (s32*) gp->contours;
877
878 /*store path bounds for gradient/textures*/
879 gf_path_get_bounds(gp, &surf->path_bounds);
880 /*invert Y (ft uses min Y)*/
881 surf->path_bounds.y -= surf->path_bounds.height;
882
883 surf->ftoutline.flags = 0;
884 if (gp->flags & GF_PATH_FILL_ZERO_NONZERO) surf->ftoutline.flags = GF_PATH_FILL_ZERO_NONZERO;
885
886 surf->ftoutline.n_points = gp->n_points;
887 surf->ftoutline.points = gp->points;
888 surf->mx = &surf->mat;
889 return GF_OK;
890 }
891
892 /* static void gray_spans_stub(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf){} */
893
894 GF_EXPORT
gf_evg_surface_fill(GF_EVGSurface * surf,GF_EVGStencil * sten)895 GF_Err gf_evg_surface_fill(GF_EVGSurface *surf, GF_EVGStencil *sten)
896 {
897 GF_Err e;
898 GF_Rect rc;
899 u32 max_gray;
900 GF_Matrix2D mat, st_mat;
901 Bool restore_filter;
902 if (!surf || !sten) return GF_BAD_PARAM;
903 if (!surf->ftoutline.n_points) return GF_OK;
904 surf->sten = sten;
905
906 /*setup ft raster calllbacks*/
907 if (!setup_grey_callback(surf, GF_FALSE)) return GF_OK;
908
909 /* surf->gray_spans = gray_spans_stub; */
910
911 /*TODO, check matrix with 3D transform*/
912
913 get_surface_world_matrix(surf, &mat);
914 restore_filter = GF_FALSE;
915 /*get path frame for texture convertion */
916 if (sten->type != GF_STENCIL_SOLID) {
917 rc = surf->path_bounds;
918 gf_mx2d_apply_rect(&mat, &rc);
919 rc.x = rc.y = 0;
920 /*assign target frame and matrix*/
921 sten->frame = rc;
922 gf_mx2d_copy(sten->pmat, surf->mat);
923 gf_mx2d_inverse(&sten->pmat);
924
925 gf_mx2d_copy(st_mat, sten->smat);
926 gf_mx2d_init(sten->smat);
927
928 switch (sten->type) {
929 case GF_STENCIL_TEXTURE:
930 if ( ((EVG_Texture *)sten)->tx_callback) {
931
932 } else {
933 if (! ((EVG_Texture *)sten)->pixels) return GF_BAD_PARAM;
934 }
935
936 if (((EVG_Texture *)sten)->mod & GF_TEXTURE_FLIP_Y) {
937 if (!surf->center_coords) gf_mx2d_add_scale(&sten->smat, FIX_ONE, -FIX_ONE);
938 } else {
939 if (surf->center_coords) gf_mx2d_add_scale(&sten->smat, FIX_ONE, -FIX_ONE);
940 }
941 gf_mx2d_add_matrix(&sten->smat, &st_mat);
942 gf_mx2d_add_matrix(&sten->smat, &mat);
943 gf_mx2d_inverse(&sten->smat);
944
945 evg_texture_init(sten, surf);
946 if (((EVG_Texture *)sten)->filter == GF_TEXTURE_FILTER_DEFAULT) {
947 restore_filter = GF_TRUE;
948 ((EVG_Texture *)sten)->filter = surf->texture_filter;
949 }
950
951 break;
952 case GF_STENCIL_LINEAR_GRADIENT:
953 {
954 EVG_LinearGradient *lin = (EVG_LinearGradient *)sten;
955 gf_mx2d_add_matrix(&sten->smat, &st_mat);
956 gf_mx2d_add_matrix(&sten->smat, &mat);
957 gf_mx2d_inverse(&sten->smat);
958 /*and finalize matrix in gradient coord system*/
959 gf_mx2d_add_matrix(&sten->smat, &lin->vecmat);
960 gf_mx2d_add_scale(&sten->smat, INT2FIX(1<<EVGGRADIENTBITS), INT2FIX(1<<EVGGRADIENTBITS));
961
962 /*init*/
963 evg_gradient_precompute((EVG_BaseGradient *)lin, surf);
964
965 }
966 break;
967 case GF_STENCIL_RADIAL_GRADIENT:
968 {
969 EVG_RadialGradient *rad = (EVG_RadialGradient*)sten;
970 gf_mx2d_copy(sten->smat, st_mat);
971 gf_mx2d_add_matrix(&sten->smat, &mat);
972 gf_mx2d_inverse(&sten->smat);
973 gf_mx2d_add_translation(&sten->smat, -rad->center.x, -rad->center.y);
974 gf_mx2d_add_scale(&sten->smat, gf_invfix(rad->radius.x), gf_invfix(rad->radius.y));
975
976 rad->d_f.x = gf_divfix(rad->focus.x - rad->center.x, rad->radius.x);
977 rad->d_f.y = gf_divfix(rad->focus.y - rad->center.y, rad->radius.y);
978 /*init*/
979 evg_radial_init(rad);
980 evg_gradient_precompute((EVG_BaseGradient *)rad, surf);
981 }
982 break;
983 }
984 }
985 max_gray = surf->raster->max_gray_spans;
986 /*force complete line callback for YUV 420/422*/
987 if (surf->yuv_type==EVG_YUV)
988 surf->raster->max_gray_spans = 0xFFFFFFFF;
989
990 if (surf->useClipper) {
991 surf->clip_xMin = surf->clipper.x;
992 surf->clip_yMin = surf->clipper.y;
993 surf->clip_xMax = (surf->clipper.x + surf->clipper.width);
994 surf->clip_yMax = (surf->clipper.y + surf->clipper.height);
995 } else {
996 surf->clip_xMin = 0;
997 surf->clip_yMin = 0;
998 surf->clip_xMax = (surf->width);
999 surf->clip_yMax = (surf->height);
1000 }
1001
1002 /*and call the raster*/
1003 if (surf->is_3d_matrix)
1004 e = evg_raster_render_path_3d(surf);
1005 else
1006 e = evg_raster_render(surf);
1007
1008 surf->raster->max_gray_spans = max_gray;
1009
1010 /*restore stencil matrix*/
1011 if (sten->type != GF_STENCIL_SOLID) {
1012 gf_mx2d_copy(sten->smat, st_mat);
1013 if (restore_filter) ((EVG_Texture *)sten)->filter = GF_TEXTURE_FILTER_DEFAULT;
1014 }
1015 surf->sten = 0L;
1016 return e;
1017 }
1018
1019
1020
gf_evg_surface_set_composite_mode(GF_EVGSurface * surf,GF_EVGCompositeMode comp_mode)1021 void gf_evg_surface_set_composite_mode(GF_EVGSurface *surf, GF_EVGCompositeMode comp_mode)
1022 {
1023 if (surf) surf->comp_mode = comp_mode;
1024 }
1025
gf_evg_surface_set_alpha_callback(GF_EVGSurface * surf,u8 (* get_alpha)(void * udta,u8 src_alpha,s32 x,s32 y),void * cbk)1026 void gf_evg_surface_set_alpha_callback(GF_EVGSurface *surf, u8 (*get_alpha)(void *udta, u8 src_alpha, s32 x, s32 y), void *cbk)
1027 {
1028 if (surf) {
1029 surf->get_alpha = get_alpha;
1030 surf->get_alpha_udta = cbk;
1031 }
1032 }
1033
gf_evg_surface_set_projection(GF_EVGSurface * surf,GF_Matrix * mx)1034 GF_Err gf_evg_surface_set_projection(GF_EVGSurface *surf, GF_Matrix *mx)
1035 {
1036 if (!surf || !surf->ext3d) return GF_BAD_PARAM;
1037 gf_mx_copy(surf->ext3d->proj, *mx);
1038 return GF_OK;
1039 }
gf_evg_surface_set_modelview(GF_EVGSurface * surf,GF_Matrix * mx)1040 GF_Err gf_evg_surface_set_modelview(GF_EVGSurface *surf, GF_Matrix *mx)
1041 {
1042 if (!surf || !surf->ext3d) return GF_BAD_PARAM;
1043 gf_mx_copy(surf->ext3d->modelview, *mx);
1044 return GF_OK;
1045 }
1046
1047 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);
1048
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)1049 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)
1050 {
1051 GF_Err e;
1052 u32 max_gray;
1053 if (!surf || !surf->ext3d) return GF_BAD_PARAM;
1054
1055 /*setup ft raster calllbacks*/
1056 if (!setup_grey_callback(surf, GF_TRUE)) return GF_OK;
1057
1058 if (surf->useClipper) {
1059 surf->clip_xMin = surf->clipper.x;
1060 surf->clip_yMin = surf->clipper.y;
1061 surf->clip_xMax = (surf->clipper.x + surf->clipper.width);
1062 surf->clip_yMax = (surf->clipper.y + surf->clipper.height);
1063 } else {
1064 surf->clip_xMin = 0;
1065 surf->clip_yMin = 0;
1066 surf->clip_xMax = (surf->width);
1067 surf->clip_yMax = (surf->height);
1068 }
1069 max_gray = surf->raster->max_gray_spans;
1070 /*force complete line callback for YUV 420/422*/
1071 if (surf->yuv_type==EVG_YUV)
1072 surf->raster->max_gray_spans = 0xFFFFFFFF;
1073
1074 /*and call the raster*/
1075 e = evg_raster_render3d(surf, indices, nb_idx, vertices, nb_vertices, nb_comp, prim_type);
1076 surf->raster->max_gray_spans = max_gray;
1077 return e;
1078 }
1079
1080 GF_Err evg_raster_render3d_path(GF_EVGSurface *surf, GF_Path *path, Float z);
1081
gf_evg_surface_draw_path(GF_EVGSurface * surf,GF_Path * path,Float z)1082 GF_Err gf_evg_surface_draw_path(GF_EVGSurface *surf, GF_Path *path, Float z)
1083 {
1084 GF_Err e;
1085 u32 max_gray;
1086 if (!surf || !surf->ext3d) return GF_BAD_PARAM;
1087
1088 /*setup ft raster calllbacks*/
1089 if (!setup_grey_callback(surf, GF_TRUE)) return GF_OK;
1090
1091 if (surf->useClipper) {
1092 surf->clip_xMin = surf->clipper.x;
1093 surf->clip_yMin = surf->clipper.y;
1094 surf->clip_xMax = (surf->clipper.x + surf->clipper.width);
1095 surf->clip_yMax = (surf->clipper.y + surf->clipper.height);
1096 } else {
1097 surf->clip_xMin = 0;
1098 surf->clip_yMin = 0;
1099 surf->clip_xMax = (surf->width);
1100 surf->clip_yMax = (surf->height);
1101 }
1102 max_gray = surf->raster->max_gray_spans;
1103 /*force complete line callback for YUV 420/422*/
1104 if (surf->yuv_type==EVG_YUV)
1105 surf->raster->max_gray_spans = 0xFFFFFFFF;
1106
1107 /*and call the raster*/
1108 e = evg_raster_render3d_path(surf, path, z);
1109 surf->raster->max_gray_spans = max_gray;
1110 return e;
1111 }
1112