LCOV - code coverage report
Current view: top level - evg - raster3d.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 597 750 79.6 %
Date: 2021-04-29 23:48:07 Functions: 39 39 100.0 %

          Line data    Source code
       1             : /*
       2             : *                       GPAC - Multimedia Framework C SDK
       3             : *
       4             : *                       Authors: Jean Le Feuvre
       5             : *                       Copyright (c) Telecom ParisTech 2019
       6             : *                                       All rights reserved
       7             : *
       8             : *  This file is part of GPAC / software 3D 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             : #include "rast_soft.h"
      28             : 
      29             : 
      30             : 
      31             : #if defined(WIN32) && !defined(__GNUC__)
      32             : # include <intrin.h>
      33             : # define GPAC_HAS_SSE2
      34             : #else
      35             : # ifdef __SSE2__
      36             : #  include <emmintrin.h>
      37             : #  define GPAC_HAS_SSE2
      38             : # endif
      39             : #endif
      40             : 
      41             : #ifdef GPAC_HAS_SSE2
      42             : 
      43             : static Float float_clamp(Float val, Float minval, Float maxval)
      44             : {
      45             :     _mm_store_ss( &val, _mm_min_ss( _mm_max_ss(_mm_set_ss(val),_mm_set_ss(minval)), _mm_set_ss(maxval) ) );
      46             :     return val;
      47             : }
      48             : #else
      49             : 
      50             : #define float_clamp(_val, _minval, _maxval)\
      51             :         (_val<_minval) ? _minval : (_val>_maxval) ? _maxval : _val;
      52             : 
      53             : #endif
      54             : 
      55             : 
      56             : 
      57             : static GFINLINE Bool evg3d_persp_divide(GF_Vec4 *pt)
      58             : {
      59             :         //perspective divide
      60       49741 :         if (!pt->q) return GF_FALSE;
      61       49741 :         pt->q = gf_divfix(FIX_ONE, pt->q);
      62       49741 :         pt->x = gf_mulfix(pt->x, pt->q);
      63       49741 :         pt->y = gf_mulfix(pt->y, pt->q);
      64       49741 :         pt->z = gf_mulfix(pt->z, pt->q);
      65             :         return GF_TRUE;
      66             : }
      67             : 
      68             : static GFINLINE void evg_ndc_to_raster(GF_EVGSurface *surf, GF_Vec4 *pt, TPos *x, TPos *y)
      69             : {
      70             :         //from [-1, 1] to [0,2] to [0,1] to [0,vp_width] to [vp left, vp right]
      71           5 :         pt->x = (pt->x + FIX_ONE) / 2 * surf->width;
      72             :         //idem but flip Y
      73           5 :         pt->y = (FIX_ONE - (pt->y + FIX_ONE)/2) * surf->height;
      74             : 
      75             :         //move Z from [-1, 1] to [min_depth, max_depth]
      76           5 :         pt->z += FIX_ONE;
      77           5 :         pt->z /= 2;
      78             : 
      79             : #ifdef GPAC_FIXED_POINT
      80             :         *x = UPSCALE(pt->x);
      81             :         *y = UPSCALE(pt->y);
      82             : #else
      83           5 :         *x = (s32) (pt->x * ONE_PIXEL);
      84           5 :         *y = (s32) (pt->y * ONE_PIXEL);
      85             : #endif
      86             : }
      87       49736 : static GFINLINE void evg3d_ndc_to_raster(GF_EVGSurface *surf, GF_Vec4 *pt, TPos *x, TPos *y)
      88             : {
      89             :         //from [-1, 1] to [0,2] to [0,1] to [0,vp_width] to [vp left, vp right]
      90       49736 :         pt->x = (pt->x + FIX_ONE) / 2 * surf->ext3d->vp_w + surf->ext3d->vp_x;
      91             :         //idem but flip Y
      92       49736 :         pt->y = (FIX_ONE - (pt->y + FIX_ONE)/2) * surf->ext3d->vp_h + surf->ext3d->vp_y;
      93             :         /*compute depth*/
      94       49736 :         if (!surf->ext3d->clip_zero) {
      95             :                 //move Z from [-1, 1] to [min_depth, max_depth]
      96        3636 :                 pt->z += FIX_ONE;
      97        3636 :                 pt->z /= 2;
      98             :         }
      99       49736 :         pt->z = surf->ext3d->min_depth + pt->z * surf->ext3d->depth_range;
     100             : 
     101             : #ifdef GPAC_FIXED_POINT
     102             :         *x = UPSCALE(pt->x);
     103             :         *y = UPSCALE(pt->y);
     104             : #else
     105       49736 :         *x = (s32) (pt->x * ONE_PIXEL);
     106       49736 :         *y = (s32) (pt->y * ONE_PIXEL);
     107             : #endif
     108       49736 : }
     109             : 
     110        2703 : static GFINLINE int gray3d_move_to(EVG_Raster raster, TPos x, TPos y)
     111             : {
     112             :         TCoord  ex, ey;
     113             : 
     114             :         /* record current cell, if any */
     115        2703 :         gray_record_cell(raster);
     116             : 
     117        2703 :         ex = TRUNC(x);
     118        2703 :         ey = TRUNC(y);
     119        2703 :         if ( ex < raster->min_ex ) ex = (TCoord)(raster->min_ex - 1);
     120        2703 :         raster->area    = 0;
     121        2703 :         raster->cover   = 0;
     122        2703 :         gray_set_cell( raster, ex, ey );
     123        2703 :         if (ey<0) ey=0;
     124        2703 :         raster->last_ey = SUBPIXELS( ey );
     125             : 
     126        2703 :         raster->x = x;
     127        2703 :         raster->y = y;
     128        2703 :         return 0;
     129             : }
     130             : 
     131           1 : GF_Err evg_raster_render_path_3d(GF_EVGSurface *surf)
     132             : {
     133             :         EVG_Vector   v_start;
     134             :         int   n;         /* index of contour in outline     */
     135             :         int   first;     /* index of first point in contour */
     136             :         TPos _x, _y, _sx, _sy;
     137             :         GF_Vec dir;
     138             :         u32 li, size_y;
     139           1 :         EVG_Raster raster = surf->raster;
     140             :         EVG_Outline *outline = &surf->ftoutline;
     141             : 
     142           1 :         raster->render_span  = (EVG_Raster_Span_Func) surf->gray_spans;
     143           1 :         raster->render_span_data = surf;
     144             : 
     145             :         /* Set up state in the raster object */
     146           1 :         raster->min_ex = surf->clip_xMin;
     147           1 :         raster->min_ey = surf->clip_yMin;
     148           1 :         raster->max_ex = surf->clip_xMax;
     149           1 :         raster->max_ey = surf->clip_yMax;
     150             : 
     151             : 
     152           1 :         size_y = (u32) (raster->max_ey - raster->min_ey);
     153           1 :         if ((u32) raster->max_lines < size_y) {
     154           0 :                 raster->scanlines = (AAScanline*)gf_realloc(raster->scanlines, sizeof(AAScanline)*size_y);
     155           0 :                 memset(&raster->scanlines[raster->max_lines], 0, sizeof(AAScanline)*(size_y-raster->max_lines) );
     156           0 :                 raster->max_lines = size_y;
     157             :         }
     158             : 
     159           1 :         raster->ex = (int) (raster->max_ex+1);
     160           1 :         raster->ey = (int) (raster->max_ey+1);
     161           1 :         raster->cover = 0;
     162           1 :         raster->area = 0;
     163           1 :         raster->first_scanline = raster->max_ey;
     164             : 
     165             :         dir.x = dir.y = 0;
     166             :         dir.z = -FIX_ONE;
     167             : 
     168             :         first = 0;
     169           2 :         for ( n = 0; n < outline->n_contours; n++ ) {
     170             :                 GF_Vec4 pt;
     171             :                 EVG_Vector *point;
     172             :                 EVG_Vector *limit;
     173             :                 int  last;  /* index of last point in contour */
     174           1 :                 last  = outline->contours[n];
     175           1 :                 limit = outline->points + last;
     176           1 :                 v_start = outline->points[first];
     177             :                 point = outline->points + first;
     178             : 
     179           1 :                 pt.x = v_start.x;
     180           1 :                 pt.y = v_start.y;
     181           1 :                 pt.z = 0;
     182           1 :                 pt.q = 1;
     183           1 :                 gf_mx_apply_vec_4x4(&surf->mx3d, &pt);
     184             :                 if (!evg3d_persp_divide(&pt)) {
     185           0 :                         continue;
     186             :                 }
     187           1 :                 evg_ndc_to_raster(surf, &pt, &_sx, &_sy);
     188           1 :                 gray3d_move_to(raster, _sx, _sy);
     189           6 :                 while ( point < limit ) {
     190           4 :                         point++;
     191             : 
     192           4 :                         pt.x = point->x;
     193           4 :                         pt.y = point->y;
     194           4 :                         pt.z = 0;
     195           4 :                         pt.q = 1;
     196           4 :                         gf_mx_apply_vec_4x4(&surf->mx3d, &pt);
     197             :                         if (!evg3d_persp_divide(&pt)) {
     198             :                                 break;
     199             :                         }
     200           4 :                         evg_ndc_to_raster(surf, &pt, &_x, &_y);
     201           4 :                         gray_render_line(raster, _x, _y);
     202             :                 }
     203           1 :                 gray_render_line(raster, _sx, _sy);
     204             : 
     205           1 :                 first = last + 1;
     206             :         }
     207             : 
     208           1 :         gray_record_cell( raster );
     209             :         /* sort each scanline and render it*/
     210          17 :         for (li=raster->first_scanline; li<size_y; li++) {
     211          16 :                 AAScanline *sl = &raster->scanlines[li];
     212          16 :                 if (sl->num) {
     213          16 :                         if (sl->num>1) gray_quick_sort(sl->cells, sl->num);
     214          16 :                         gray_sweep_line(raster, sl, li, GF_TRUE);
     215             :                 }
     216             :         }
     217           1 :         return GF_OK;
     218             : }
     219             : 
     220             : 
     221     4812826 : Bool evg3d_get_fragment(GF_EVGSurface *surf, GF_EVGFragmentParam *frag_param, Bool *is_transparent)
     222             : {
     223     4812826 :         surf->fill_col = 0;
     224     4812826 :         surf->fill_col_wide = 0;
     225             : 
     226     4812826 :         if (!surf->ext3d->frag_shader(surf->ext3d->frag_shader_udta, frag_param))
     227             :                 return GF_FALSE;
     228             : 
     229             : #if 0
     230             :         frag_param->color.x = float_clamp(frag_param->color.x, 0.0, 1.0);
     231             :         frag_param->color.y = float_clamp(frag_param->color.y, 0.0, 1.0);
     232             :         frag_param->color.z = float_clamp(frag_param->color.z, 0.0, 1.0);
     233             :         frag_param->color.q = float_clamp(frag_param->color.q, 0.0, 1.0);
     234             : #endif
     235             : 
     236     4812826 :         if (frag_param->color.q<1.0) *is_transparent = GF_TRUE;
     237             : 
     238     4812826 :         if (surf->not_8bits) {
     239           0 :                 surf->fill_col_wide = evg_make_col_wide((u16) frag_param->color.q*0xFFFF, (u16) frag_param->color.x*0xFFFF, (u16) frag_param->color.y*0xFFFF, (u16) frag_param->color.z*0xFFFF);
     240             :         } else {
     241     4812826 :                 u8 a = (u8) (frag_param->color.q*255);
     242     4812826 :                 u8 r = (u8) (frag_param->color.x*255);
     243     4812826 :                 u8 g = (u8) (frag_param->color.y*255);
     244     4812826 :                 u8 b = (u8) (frag_param->color.z*255);
     245     4812826 :                 surf->fill_col = GF_COL_ARGB(a, r, g, b);
     246             :         }
     247             : 
     248     4812826 :         if (surf->not_8bits) {
     249           0 :                 if (surf->yuv_type) {
     250           0 :                         if (frag_param->frag_valid==GF_EVG_FRAG_RGB) {
     251           0 :                                 surf->fill_col_wide = gf_evg_argb_to_ayuv_wide(surf, surf->fill_col_wide);
     252             :                         }
     253             :                 } else {
     254           0 :                         if (frag_param->frag_valid==GF_EVG_FRAG_YUV) {
     255           0 :                                 surf->fill_col_wide = gf_evg_ayuv_to_argb_wide(surf, surf->fill_col_wide);
     256             :                         }
     257             :                 }
     258             :         } else {
     259     4812826 :                 if (surf->yuv_type) {
     260             :                         /*RGB frag*/
     261     1204487 :                         if (frag_param->frag_valid==GF_EVG_FRAG_RGB) {
     262           0 :                                 surf->fill_col = gf_evg_argb_to_ayuv(surf, surf->fill_col);
     263             :                         }
     264             :                 } else {
     265     3608339 :                         if (frag_param->frag_valid==GF_EVG_FRAG_YUV) {
     266           0 :                                 surf->fill_col = gf_evg_ayuv_to_argb(surf, surf->fill_col);
     267             :                         }
     268             :                 }
     269             :         }
     270             :         return GF_TRUE;
     271             : }
     272             : 
     273             : static float edgeFunction(const GF_Vec4 *a, const GF_Vec4 *b, const GF_Vec4 *c)
     274             : {
     275        2812 :         return (c->x - a->x) * (b->y - a->y) - (c->y - a->y) * (b->x - a->x);
     276             : }
     277             : 
     278             : static float edgeFunction_pre(const GF_Vec4 *a, const Float b_minus_a_x, const Float b_minus_a_y, const GF_Vec4 *c)
     279             : {
     280    14571291 :         return (c->x - a->x) * (b_minus_a_y) - (c->y - a->y) * (b_minus_a_x);
     281             : }
     282             : 
     283             : typedef struct
     284             : {
     285             :         GF_EVGSurface *surf;
     286             :         GF_EVGFragmentParam frag_param;
     287             : } EVGFragCallback;
     288             : 
     289      239004 : static void push_patch_pixel(AAScanline *sl, s32 x, u32 col, u8 coverage, Float depth, Float write_depth, u32 idx1, u32 idx2)
     290             : {
     291             :         u32 i;
     292             :         PatchPixel *pp;
     293     2605084 :         for (i=0; i<sl->pnum; i++) {
     294     1137512 :                 if (sl->pixels[i].x>x) break;
     295     1063544 :                 if (sl->pixels[i].x<x) continue;
     296           6 :                 sl->pixels[i].color = col;
     297           6 :                 sl->pixels[i].cover = coverage;
     298           6 :                 sl->pixels[i].depth = depth;
     299           6 :                 sl->pixels[i].write_depth = write_depth;
     300           6 :                 sl->pixels[i].idx1 = idx1;
     301           6 :                 sl->pixels[i].idx2 = idx2;
     302           6 :                 return;
     303             :         }
     304      238998 :         if (coverage==0xFF) return;
     305             : 
     306      238998 :         if (sl->pnum == sl->palloc) {
     307        2654 :                 sl->palloc += AA_CELL_STEP_ALLOC;
     308        2654 :                 sl->pixels = gf_realloc(sl->pixels, sizeof(PatchPixel) * sl->palloc);
     309             :         }
     310      238998 :         if (i==sl->pnum) {
     311      165030 :                 pp = &sl->pixels[sl->pnum];
     312             :         } else {
     313       73968 :                 memmove(&sl->pixels[i+1], &sl->pixels[i], sizeof(PatchPixel)*(sl->pnum - i));
     314       73968 :                 pp = &sl->pixels[i];
     315             :         }
     316      238998 :         sl->pnum++;
     317      238998 :         pp->color = col;
     318      238998 :         pp->cover = coverage;
     319      238998 :         pp->x = x;
     320      238998 :         pp->depth = depth;
     321      238998 :         pp->write_depth = write_depth;
     322      238998 :         pp->idx1 = idx1;
     323      238998 :         pp->idx2 = idx2;
     324             : }
     325             : 
     326             : static PatchPixel *get_patch_pixel(AAScanline *sl, s32 x)
     327             : {
     328             :         u32 i;
     329     9502222 :         for (i=0; i<sl->pnum; i++) {
     330    11817224 :                 if (sl->pixels[i].x>x) break;
     331     9621543 :                 if (sl->pixels[i].x<x) continue;
     332             :                 return &sl->pixels[i];
     333             :         }
     334             :         return NULL;
     335             : }
     336             : 
     337             : 
     338      113754 : static void remove_patch_pixel(AAScanline *sl, s32 x)
     339             : {
     340             :         u32 i;
     341      521942 :         for (i=0; i<sl->pnum; i++) {
     342      317848 :                 if (sl->pixels[i].x>x) break;
     343      317848 :                 if (sl->pixels[i].x<x) continue;
     344      113754 :                 if (i+1<sl->pnum)
     345      102983 :                         memmove(&sl->pixels[i], &sl->pixels[i+1], sizeof(PatchPixel)*(sl->pnum-i-1));
     346      113754 :                 sl->pnum--;
     347             :                 return;
     348             :         }
     349             : }
     350             : 
     351      121262 : void EVG3D_SpanFunc(int y, int count, EVG_Span *spans, void *user)
     352             : {
     353             :         int i;
     354             :         GF_Vec4 pix;
     355             :         EVGFragCallback *fcbck = user;
     356      121262 :         GF_EVGSurface *surf = fcbck->surf;
     357      121262 :         EVG_Surface3DExt *s3d = surf->ext3d;
     358      121262 :         GF_EVGFragmentParam *frag_param = &fcbck->frag_param;
     359      121262 :         AAScanline *sl = &surf->raster->scanlines[y];
     360      121262 :         Float *depth_line = s3d->depth_buffer ? &s3d->depth_buffer[y*surf->width] : NULL;
     361             :         Float depth_buf_val;
     362             : 
     363             :         pix.z=0;
     364             :         pix.q=1;
     365             : 
     366      818954 :         for (i=0; i<count; i++) {
     367      697692 :                 u8 coverage = spans[i].coverage;
     368      697692 :                 u32 j, len = spans[i].len;
     369      697692 :                 s32 sx = spans[i].x;
     370     5554789 :                 for (j=0; j<len; j++) {
     371             : 
     372             : 
     373     4857097 :         Bool transparent=GF_FALSE;
     374             :         Float depth, bc1, bc2, bc3;
     375             :         Bool full_cover=GF_TRUE;
     376             :         Bool edge_merge=GF_FALSE;
     377     4857097 :         s32 x = sx + j;
     378             :         PatchPixel *prev_partial = NULL;
     379             : 
     380             :         /*no AA, force full opacity and test pixel/line below*/
     381     4857097 :         if (s3d->disable_aa)
     382             :                 coverage = 0xFF;
     383     4857097 :         else if (!s3d->mode2d)
     384     4484342 :                 prev_partial = get_patch_pixel(sl, x);
     385             : 
     386     4857097 :         pix.x = (Float)x + 0.5f;
     387     4857097 :         pix.y = (Float)y + 0.5f;
     388             : 
     389     4857097 :         if (s3d->prim_type==GF_EVG_POINTS) {
     390           0 :                 if (s3d->smooth_points) {
     391             :                         Float dx, dy;
     392           0 :                         dx = (Float)x - s3d->s_v1.x;
     393           0 :                         dy = (Float)y - s3d->s_v1.y;
     394           0 :                         dx *=dx;
     395           0 :                         dy *=dy;
     396           0 :                         if (dx+dy > s3d->pt_radius) {
     397           0 :                                 spans[i].coverage=0;
     398      287178 :                                 continue;
     399             :                         }
     400             :                 }
     401           0 :                 depth = s3d->s_v1.z;
     402             : 
     403             :                 bc1 = bc2 = bc3 = 0;
     404           0 :                 if (coverage!=0xFF) {
     405             :                         full_cover = GF_FALSE;
     406             :                 }
     407     4857097 :         } else if (s3d->prim_type==GF_EVG_LINES) {
     408             :                 GF_Vec pt;
     409             : 
     410           0 :                 gf_vec_diff(pt, pix, s3d->s_v1);
     411           0 :                 bc1 = gf_vec_len(pt);
     412           0 :                 bc1 /= s3d->v1v2_length;
     413             :                 bc1 = float_clamp(bc1, 0, 1);
     414           0 :                 bc2 = FIX_ONE - bc1;
     415           0 :                 depth = s3d->s_v1.z * bc1 + s3d->s_v2.z * bc2;
     416             : 
     417             :                 bc3 = 0;
     418           0 :                 if (coverage!=0xFF) {
     419             :                         full_cover = GF_FALSE;
     420             :                 }
     421             :         } else {
     422     4857097 :                 bc1 = edgeFunction_pre(&s3d->s_v2, s3d->s3_m_s2_x, s3d->s3_m_s2_y, &pix);
     423     4857097 :                 bc1 /= s3d->area;
     424     4857097 :                 bc2 = edgeFunction_pre(&s3d->s_v3, s3d->s1_m_s3_x, s3d->s1_m_s3_y, &pix);
     425     4857097 :                 bc2 /= s3d->area;
     426     4857097 :                 bc3 = edgeFunction_pre(&s3d->s_v1, s3d->s2_m_s1_x, s3d->s2_m_s1_y, &pix);
     427     4857097 :                 bc3 /= s3d->area;
     428             :                 //bc3 = 1.0 - bc1 - bc2;
     429             : 
     430             :                 /* in antialiased mode, we don't need to test for bc1>=0 && bc2>=0 && bc3>=0 (ie, is the pixel in the triangle),
     431             :                 because we already know the point is in the triangle since we are called back
     432             :                 in non-AA mode, coverage is forced to full pixel, and we check if we are or not in the triangle*/
     433     4857097 :                 if (s3d->disable_aa)
     434             :                 {
     435           0 :                         if ((bc1<0) || (bc2<0) || (bc3<0)) {
     436           0 :                                 spans[i].coverage=0;
     437           0 :                                 continue;
     438             :                         }
     439             :                 }
     440             :                 /*if coverage is not full, we are on a line - recompute the weights assuming the pixel is exactly on the line*/
     441     4857097 :                 else if (coverage!=0xFF) {
     442             : 
     443             :                 //results are not precise enough to give better results, we always clamp for now
     444             : #if 0
     445             :                         if (!s3d->backface_cull) {
     446             : 
     447             : #if 0
     448             :                                 //method 1, find a subpixel in a 5x5 grid belonging to the triangle
     449             :                                 GF_Vec4 subp;
     450             :                                 u32 k, l;
     451             :                                 subp.q = 1;
     452             :                                 subp.z = 0;
     453             :                                 Bool subp_found=GF_FALSE;
     454             :                                 for (k=0; k<=4; k++) {
     455             :                                         for (l=0; l<=4; l++) {
     456             :                                                 subp.x = (Float) x + 0.25*k;
     457             :                                                 subp.y = (Float) x + 0.25*l;
     458             :                                                 bc1 = edgeFunction_pre(&s3d->s_v2, s3d->s3_m_s2_x, s3d->s3_m_s2_y, &subp);
     459             :                                                 bc1 /= s3d->area;
     460             :                                                 bc2 = edgeFunction_pre(&s3d->s_v3, s3d->s1_m_s3_x, s3d->s1_m_s3_y, &subp);
     461             :                                                 bc2 /= s3d->area;
     462             :                                                 bc3 = 1.0 - bc1 - bc2;
     463             :                                                 if ((bc1<0) || (bc2<0) || (bc3<0)) continue;
     464             :                                                 subp_found = GF_TRUE;
     465             :                                                 break;
     466             :                                         }
     467             :                                 }
     468             : //                              assert(subp_found);
     469             : 
     470             : #else
     471             :                                 //method 2, reproject point on triangle edges
     472             :                                 GF_Vec pt;
     473             :                                 u32 on_line = 0;
     474             : 
     475             :                                 if ((bc1<0) || (bc2<0) || (bc3<0)) {
     476             :                                         if ((bc1<0) && (bc2<0)) { bc3 = 1.0; bc1 = bc2 = 0; }
     477             :                                         else if ((bc1<0) && (bc3<0)) { bc2 = 1.0; bc1 = bc3 = 0; }
     478             :                                         else if ((bc2<0) && (bc3<0)) { bc1 = 1.0; bc2 = bc3 = 0; }
     479             :                                         else if ((bc1<=bc2) && (bc1<=bc3)) on_line = 3;
     480             :                                         else if ((bc2<=bc1) && (bc2<=bc3)) on_line = 2;
     481             :                                         else if ((bc3<=bc1) && (bc3<=bc2)) on_line = 1;
     482             :                                 }
     483             :                                 //project pixel center on line v2v3
     484             :                                 if (on_line==3) {
     485             :                                         bc1 = 0;
     486             :                                         gf_vec_diff(pt, pix, s3d->s_v2);
     487             :                                         pt.z=0;
     488             :                                         bc2 = gf_vec_dot(pt, s3d->v2v3);
     489             :                                         bc2 /= s3d->v2v3_length;
     490             :                                         bc3 = float_clamp(bc2, 0, 1);
     491             :                                         bc2 = FIX_ONE - bc3;
     492             :                                 }
     493             :                                 //project pixel center on line v1v3
     494             :                                 else if (on_line==2) {
     495             :                                         bc2 = 0;
     496             :                                         gf_vec_diff(pt, pix, s3d->s_v1);
     497             :                                         pt.z=0;
     498             :                                         bc1 = gf_vec_dot(pt, s3d->v1v3);
     499             :                                         bc1 /= s3d->v1v3_length;
     500             :                                         bc3 = float_clamp(bc1, 0, 1);
     501             :                                         bc1 = FIX_ONE - bc3;
     502             :                                 }
     503             :                                 //project pixel center on line v1v2
     504             :                                 else if (on_line==1) {
     505             :                                         bc3 = 0;
     506             :                                         gf_vec_diff(pt, pix, s3d->s_v1);
     507             :                                         pt.z=0;
     508             :                                         bc1 = gf_vec_dot(pt, s3d->v1v2);
     509             :                                         bc1 /= s3d->v1v2_length;
     510             :                                         bc2 = float_clamp(bc1, 0, 1);
     511             :                                         bc1 = FIX_ONE - bc2;
     512             :                                 }
     513             : #endif
     514             : 
     515             :                         } else
     516             : #endif
     517      541778 :                         if (!s3d->mode2d) {
     518             :                                 bc1 = float_clamp(bc1, 0, 1);
     519             :                                 bc2 = float_clamp(bc2, 0, 1);
     520             :                                 bc3 = float_clamp(bc3, 0, 1);
     521             :                         }
     522             : 
     523             :                         full_cover = GF_FALSE;
     524      541778 :                         transparent = GF_TRUE;
     525             :                 }
     526     4857097 :                 depth = s3d->s_v1.z * bc1 + s3d->s_v2.z * bc2 + s3d->s_v3.z * bc3;
     527             :         }
     528             : 
     529             :         //clip by depth
     530     4857097 :         if ((depth<s3d->min_depth) || (depth>s3d->max_depth)) {
     531        4692 :                 spans[i].coverage=0;
     532        4692 :                 continue;
     533             :         }
     534             : 
     535     4852405 :         depth_buf_val = depth_line ? depth_line[x] : s3d->max_depth;
     536     4852405 :         if (prev_partial) {
     537      117663 :                 if ((spans[i].idx1==prev_partial->idx1)
     538      115892 :                         || (spans[i].idx1==prev_partial->idx2)
     539        1618 :                         || (spans[i].idx2==prev_partial->idx1)
     540        1110 :                         || (spans[i].idx2==prev_partial->idx2)
     541             :                 ) {
     542      117657 :                         depth = prev_partial->depth;
     543      117657 :                         edge_merge = GF_TRUE;
     544             :                 } else {
     545             :                         edge_merge = GF_FALSE;
     546           6 :                         if (!s3d->depth_test(prev_partial->write_depth, depth_buf_val))
     547           6 :                                 depth_buf_val = prev_partial->write_depth;
     548             :                 }
     549             :         }
     550             : 
     551             : 
     552             :         //do depth test except for edges
     553     4852405 :         if (! edge_merge && s3d->early_depth_test) {
     554     4734748 :                 if (! s3d->depth_test(depth_buf_val, depth)) {
     555       39579 :                         spans[i].coverage=0;
     556       39579 :                         continue;
     557             :                 }
     558             :         }
     559             : 
     560     4812826 :         frag_param->screen_x = pix.x;
     561     4812826 :         frag_param->screen_y = pix.y;
     562             :         //compute Z window coord
     563     4812826 :         frag_param->screen_z = s3d->zw_factor * depth + s3d->zw_offset;
     564     4812826 :         frag_param->depth = depth;
     565     4812826 :         frag_param->color.q = 1.0;
     566     4812826 :         frag_param->frag_valid = 0;
     567             :         /*perspective corrected barycentric, eg bc1/q1, bc2/q2, bc3/q3 - we already have store 1/q in the perspective divide step*/
     568     4812826 :         frag_param->pbc1 = bc1*s3d->s_v1.q;
     569     4812826 :         frag_param->pbc2 = bc2*s3d->s_v2.q;
     570     4812826 :         frag_param->pbc3 = bc3*s3d->s_v3.q;
     571             : 
     572     4812826 :         frag_param->persp_denum = frag_param->pbc1 + frag_param->pbc2 + frag_param->pbc3;
     573             : 
     574     4812826 :         if (!evg3d_get_fragment(surf, frag_param, &transparent)) {
     575           0 :                 spans[i].coverage=0;
     576           0 :                 continue;
     577             :         }
     578     4812826 :         if (!s3d->early_depth_test) {
     579           0 :                 if (! s3d->depth_test(depth_buf_val, frag_param->depth)) {
     580           0 :                         spans[i].coverage=0;
     581           0 :                         continue;
     582             :                 }
     583             :         }
     584             :         //we overwrite a partial
     585     4812826 :         if (prev_partial) {
     586      117663 :                 if (edge_merge) {
     587      117657 :                         u32 ncov = coverage;
     588             : 
     589      117657 :                         ncov += prev_partial->cover;
     590      117657 :                         if (!s3d->depth_test(depth_buf_val, depth)) {
     591           0 :                                 remove_patch_pixel(sl, prev_partial->x);
     592           0 :                                 spans[i].coverage=0;
     593           0 :                                 continue;
     594             :                         }
     595      117657 :                         if (ncov>=0xFF) {
     596      113754 :                                 if (prev_partial->cover==0xFF) {
     597           0 :                                         spans[i].coverage=0;
     598           0 :                                         continue;
     599             :                                 }
     600      113754 :                                 remove_patch_pixel(sl, prev_partial->x);
     601             :                                 full_cover = GF_TRUE;
     602             :                                 coverage = 0xFF;
     603             :                         } else {
     604        3903 :                                 prev_partial->cover = ncov;
     605        3903 :                                 prev_partial->color = surf->fill_col;
     606        3903 :                                 spans[i].coverage=0;
     607        3903 :                                 continue;
     608             :                         }
     609             :                 }
     610           6 :                 else if (s3d->depth_test(prev_partial->write_depth, depth)) {
     611           6 :                         prev_partial->write_depth = depth;
     612             :                 }
     613             :         }
     614             : 
     615             :         //partial coverage, store
     616     4695169 :         if (!full_cover && !s3d->mode2d) {
     617      239004 :                 push_patch_pixel(sl, x, surf->fill_col, coverage, depth, depth_buf_val, spans[i].idx1, spans[i].idx2);
     618      239004 :                 spans[i].coverage=0;
     619      239004 :                 continue;
     620             :         }
     621             :         //full opacity, write
     622             :         else {
     623     4569919 :                 if (surf->fill_single) {
     624     3464500 :                         if (transparent) {
     625      228829 :                                 surf->fill_single_a(y, x, coverage, surf->fill_col, surf);
     626             :                         } else {
     627     3235671 :                                 surf->fill_single(y, x, surf->fill_col, surf);
     628             :                         }
     629             :                 } else {
     630     1105419 :                         spans[i].coverage = 0xFF;
     631     1105419 :                         s3d->pix_vals[x] = surf->fill_col;
     632             :                 }
     633             :         }
     634             : 
     635             :         //write depth
     636     4569919 :         if (s3d->run_write_depth)
     637     4561135 :                 depth_line[x] = frag_param->depth;
     638             : 
     639             : 
     640             :                 }       //end span.len loop
     641             :         } //end spans count loop
     642             : 
     643      121262 :         if (!surf->fill_single) {
     644       42186 :                 surf->gray_spans(y, count, spans, surf);
     645             :         }
     646      121262 : }
     647             : 
     648        2812 : static GFINLINE Bool precompute_tri(EVG_Surface3DExt *s3d, EVGFragCallback *frag_ckck, TPos xmin, TPos xmax, TPos ymin, TPos ymax,
     649             :                                                                         TPos _x1, TPos _y1, TPos _x2, TPos _y2, TPos _x3, TPos _y3,
     650             :                                                                         GF_Vec4 *s_pt1, GF_Vec4 *s_pt2, GF_Vec4 *s_pt3,
     651             :                                                                         u32 vidx1, u32 vidx2, u32 vidx3
     652             : )
     653             : {
     654             :         /*completely outside viewport*/
     655        2812 :         if ((_x1<xmin) && (_x2<xmin) && (_x3<xmin))
     656             :                 return GF_FALSE;
     657        2812 :         if ((_y1<ymin) && (_y2<ymin) && (_y3<ymin))
     658             :                 return GF_FALSE;
     659        2812 :         if ((_x1>=xmax) && (_x2>=xmax) && (_x3>=xmax))
     660             :                 return GF_FALSE;
     661        2812 :         if ((_y1>=ymax) && (_y2>=ymax) && (_y3>=ymax))
     662             :                 return GF_FALSE;
     663             : 
     664        5624 :         s3d->area = edgeFunction(s_pt1, s_pt2, s_pt3);
     665             : 
     666        2812 :         s3d->s_v1 = *s_pt1;
     667        2812 :         s3d->s_v2 = *s_pt2;
     668        2812 :         s3d->s_v3 = *s_pt3;
     669        2812 :         frag_ckck->frag_param.idx1 = vidx1;
     670        2812 :         frag_ckck->frag_param.idx2 = vidx2;
     671        2812 :         frag_ckck->frag_param.idx3 = vidx3;
     672             : 
     673             : 
     674             :         //precompute a few things for this run
     675        2812 :         s3d->s3_m_s2_x = s3d->s_v3.x - s3d->s_v2.x;
     676        2812 :         s3d->s3_m_s2_y = s3d->s_v3.y - s3d->s_v2.y;
     677        2812 :         s3d->s1_m_s3_x = s3d->s_v1.x - s3d->s_v3.x;
     678        2812 :         s3d->s1_m_s3_y = s3d->s_v1.y - s3d->s_v3.y;
     679        2812 :         s3d->s2_m_s1_x = s3d->s_v2.x - s3d->s_v1.x;
     680        2812 :         s3d->s2_m_s1_y = s3d->s_v2.y - s3d->s_v1.y;
     681             : 
     682             :         GF_Vec lv;
     683             :         lv.z=0;
     684        2812 :         gf_vec_diff(lv, *s_pt2, *s_pt1);
     685        2812 :         s3d->v1v2_length = gf_vec_len(lv);
     686        2812 :         gf_vec_norm(&lv);
     687        2812 :         s3d->v1v2 = lv;
     688        2812 :         gf_vec_diff(lv, *s_pt3, *s_pt2);
     689        2812 :         s3d->v2v3_length = gf_vec_len(lv);
     690        2812 :         gf_vec_norm(&lv);
     691        2812 :         s3d->v2v3 = lv;
     692        2812 :         gf_vec_diff(lv, *s_pt3, *s_pt1);
     693        2812 :         s3d->v1v3_length = gf_vec_len(lv);
     694        2812 :         gf_vec_norm(&lv);
     695        2812 :         s3d->v1v3 = lv;
     696             : 
     697        2812 :         return GF_TRUE;
     698             : }
     699             : 
     700         226 : 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)
     701             : {
     702             :         u32 i, li, size_y, nb_comp_1, idx_inc;
     703             :         GF_Matrix projModeView;
     704             :         EVG_Span span;
     705             :         u32 is_strip_fan=0;
     706         226 :         EVG_Raster raster = surf->raster;
     707         226 :         EVG_Surface3DExt *s3d = surf->ext3d;
     708             :         EVGFragCallback frag_ckck;
     709             :         u32 first_patch, last_patch;
     710             :         TPos xmin, xmax, ymin, ymax;
     711             :         Bool glob_quad_done = GF_TRUE;
     712             :         u32 prim_index=0;
     713             :         GF_EVGVertexParam vparam;
     714             :         int hpw=0;
     715             :         int hlw=0;
     716         226 :         if (!surf->ext3d->frag_shader) return GF_BAD_PARAM;
     717             : 
     718         226 :         raster->render_span  = (EVG_Raster_Span_Func) EVG3D_SpanFunc;
     719         226 :         raster->render_span_data = &frag_ckck;
     720             : 
     721             :         /* Set up state in the raster object */
     722         226 :         raster->min_ex = surf->clip_xMin;
     723         226 :         raster->min_ey = surf->clip_yMin;
     724         226 :         raster->max_ex = surf->clip_xMax;
     725         226 :         raster->max_ey = surf->clip_yMax;
     726             : 
     727         226 :         s3d->run_write_depth = s3d->depth_buffer ? s3d->write_depth : GF_FALSE;
     728             : 
     729         226 :         size_y = (u32) (raster->max_ey - raster->min_ey);
     730         226 :         if (raster->max_lines < size_y) {
     731          18 :                 raster->scanlines = (AAScanline*)gf_realloc(raster->scanlines, sizeof(AAScanline)*size_y);
     732          18 :                 memset(&raster->scanlines[raster->max_lines], 0, sizeof(AAScanline)*(size_y-raster->max_lines) );
     733          18 :                 raster->max_lines = size_y;
     734             :         }
     735      140220 :         for (li=0; li<size_y; li++) {
     736      140220 :                 raster->scanlines[li].pnum = 0;
     737             :         }
     738             :         first_patch = 0xFFFFFFFF;
     739             :         last_patch = 0;
     740             : 
     741         226 :         gf_mx_copy(projModeView, s3d->proj);
     742         226 :         gf_mx_add_matrix_4x4(&projModeView, &s3d->modelview);
     743             : 
     744         226 :         switch (prim_type) {
     745           0 :         case GF_EVG_LINE_STRIP:
     746             :                 is_strip_fan = 1;
     747           0 :         case GF_EVG_LINES:
     748             :                 idx_inc = 2;
     749           0 :                 hlw = (int) (s3d->line_size*ONE_PIXEL/2);
     750             :                 prim_type = GF_EVG_LINES;
     751           0 :                 break;
     752             :         case GF_EVG_TRIANGLES:
     753             :                 idx_inc = 3;
     754             :                 break;
     755           0 :         case GF_EVG_TRIANGLE_STRIP:
     756             :                 is_strip_fan = 1;
     757             :                 idx_inc = 3;
     758             :                 prim_type = GF_EVG_TRIANGLES;
     759           0 :                 break;
     760           0 :         case GF_EVG_POLYGON:
     761             :         case GF_EVG_TRIANGLE_FAN:
     762             :                 is_strip_fan = 2;
     763             :                 idx_inc = 3;
     764             :                 prim_type = GF_EVG_TRIANGLES;
     765           0 :                 break;
     766           0 :         case GF_EVG_QUADS:
     767             :                 idx_inc = 4;
     768             :                 glob_quad_done = GF_FALSE;
     769           0 :                 break;
     770           0 :         case GF_EVG_QUAD_STRIP:
     771             :                 idx_inc = 4;
     772             :                 glob_quad_done = GF_FALSE;
     773             :                 is_strip_fan = 1;
     774             :                 prim_type = GF_EVG_QUADS;
     775           0 :                 break;
     776           0 :         default:
     777             :                 idx_inc = 1;
     778           0 :                 hpw = (int) (s3d->point_size*ONE_PIXEL/2);
     779           0 :                 s3d->pt_radius = (Float) (s3d->point_size*s3d->point_size) / 4;
     780             : 
     781           0 :                 break;
     782             :         }
     783         226 :         if (!is_strip_fan && (nb_idx % idx_inc))
     784             :                 return GF_BAD_PARAM;
     785             : 
     786         226 :         s3d->prim_type = prim_type;
     787             :         memset(&frag_ckck, 0, sizeof(EVGFragCallback));
     788         226 :         frag_ckck.surf = surf;
     789         226 :         frag_ckck.frag_param.ptype = prim_type;
     790             :         frag_ckck.frag_param.prim_index = 0;
     791             : 
     792         226 :         xmin = raster->min_ex * ONE_PIXEL;
     793         226 :         xmax = raster->max_ex * ONE_PIXEL;
     794         226 :         ymin = raster->min_ey * ONE_PIXEL;
     795         226 :         ymax = raster->max_ey * ONE_PIXEL;
     796             : 
     797             :         //raster coordinates of points
     798         226 :         TPos _x1=0, _y1=0, _x2=0, _y2=0, _x3=0, _y3=0, _x4=0, _y4=0, _prev_x2=0, _prev_y2=0;
     799             :         /*vertices in raster/window space: x and y are in pixel space, z is [min_depth, max_depth]*/
     800             :         GF_Vec4 s_pt1, s_pt2, s_pt3, s_pt4, prev_s_pt2;
     801             :         u32 idx1=0, idx2=0, idx3=0, idx4=0;
     802             :         u32 vidx1=0, vidx2=0, vidx3=0, vidx4=0, prev_vidx2=0;
     803             : 
     804             :         memset(&vparam, 0, sizeof(GF_EVGVertexParam));
     805         226 :         vparam.ptype = prim_type;
     806             : 
     807         226 :         nb_comp_1 = nb_comp-1;
     808        2938 :         for (i=0; i<nb_idx; i += idx_inc) {
     809             :                 Bool quad_done = glob_quad_done;
     810             :                 GF_Vec4 *vx = &vparam.in_vertex;
     811             : 
     812        2712 :                 if (s3d->vert_shader) {
     813        1500 :                         vparam.prim_index = prim_index;
     814             :                 }
     815        2712 :                 prim_index++;
     816             :                 
     817             : #define GETVEC(_name, _idx)\
     818             :                 vx->x = vertices[_idx];\
     819             :                 vx->y = vertices[_idx+1];\
     820             :                 if (_idx+nb_comp_1>=nb_vertices) return GF_BAD_PARAM;\
     821             :                 vx->z = (nb_comp>2) ? vertices[_idx+2] : 0.0f;\
     822             :                 vx->q = 1.0;\
     823             :                 if (s3d->vert_shader) {\
     824             :                         s3d->vert_shader(s3d->vert_shader_udta, &vparam); \
     825             :                         s_##_name = vparam.out_vertex;\
     826             :                 } else {\
     827             :                         s_##_name.x = vx->x;\
     828             :                         s_##_name.y = vx->y;\
     829             :                         s_##_name.z = vx->z;\
     830             :                         s_##_name.q = 1;\
     831             :                         gf_mx_apply_vec_4x4(&projModeView, &s_##_name);\
     832             :                 }\
     833             :                 if (!evg3d_persp_divide(&s_##_name)) continue;\
     834             : 
     835             :                 /*get vertice, apply transform and perspective divide and translate to raster*/
     836        2712 :                 if (is_strip_fan && i) {
     837             :                         idx_inc=1;
     838           0 :                         if (prim_type==GF_EVG_LINES) {
     839           0 :                                 _x1 = _x2;
     840           0 :                                 _y1 = _y2;
     841           0 :                                 s_pt1 = s_pt2;
     842             :                                 vidx1 = vidx2;
     843           0 :                                 vidx2 = indices[i];
     844           0 :                                 idx2 = vidx2 * nb_comp;
     845           0 :                                 vparam.vertex_idx = vidx2;
     846           0 :                                 vparam.vertex_idx_in_prim = 1;
     847           0 :                                 GETVEC(pt2, idx2)
     848           0 :                                 evg3d_ndc_to_raster(surf, &s_pt2, &_x2, &_y2);
     849             :                         }
     850             :                         //triangle strip
     851           0 :                         else if (is_strip_fan==1) {
     852             :                                 /*triangle strip*/
     853           0 :                                 if (prim_type==GF_EVG_TRIANGLES) {
     854             :                                         /*swap v2 to v1 and v3 to v2*/
     855           0 :                                         _x1 = _x2;
     856           0 :                                         _y1 = _y2;
     857           0 :                                         s_pt1 = s_pt2;
     858             :                                         vidx1 = vidx2;
     859             : 
     860           0 :                                         _x2 = _x3;
     861           0 :                                         _y2 = _y3;
     862           0 :                                         s_pt2 = s_pt3;
     863             :                                         vidx2 = vidx3;
     864             : 
     865           0 :                                         vidx3 = indices[i];
     866           0 :                                         idx3 = vidx3 * nb_comp;
     867           0 :                                         vparam.vertex_idx = vidx3;
     868           0 :                                         vparam.vertex_idx_in_prim = 2;
     869           0 :                                         GETVEC(pt3, idx3)
     870           0 :                                         evg3d_ndc_to_raster(surf, &s_pt3, &_x3, &_y3);
     871             :                                 }
     872             :                                 //quad strip - since we draw [v1, v2, v3, v4] as 2 triangles [v1, v2, v3] and [v1, v3, v4]
     873             :                                 // we only need to restore prev v2 as v1
     874             :                                 else {
     875           0 :                                         _x1 = _prev_x2;
     876           0 :                                         _y1 = _prev_y2;
     877           0 :                                         s_pt1 = prev_s_pt2;
     878             :                                         vidx1 = prev_vidx2;
     879             : 
     880           0 :                                         vidx4 = indices[i];
     881           0 :                                         idx4 = vidx4 * nb_comp;
     882           0 :                                         vparam.vertex_idx = vidx4;
     883           0 :                                         vparam.vertex_idx_in_prim = 3;
     884           0 :                                         GETVEC(pt4, idx4)
     885           0 :                                         evg3d_ndc_to_raster(surf, &s_pt4, &_x4, &_y4);
     886             :                                 }
     887             :                         }
     888             :                         //triangle fan
     889             :                         else {
     890             :                                 //keep center and move 3rd vertex as second
     891           0 :                                 _x2 = _x3;
     892           0 :                                 _y2 = _y3;
     893           0 :                                 s_pt2 = s_pt3;
     894             :                                 vidx2 = vidx3;
     895             : 
     896           0 :                                 vidx3 = indices[i];
     897           0 :                                 idx3 = vidx3 * nb_comp;
     898           0 :                                 vparam.vertex_idx = vidx3;
     899           0 :                                 vparam.vertex_idx_in_prim = 2;
     900           0 :                                 GETVEC(pt3, idx3)
     901           0 :                                 evg3d_ndc_to_raster(surf, &s_pt3, &_x3, &_y3);
     902             :                         }
     903             :                 } else {
     904        2712 :                         vidx1 = indices[i];
     905        2712 :                         idx1 = vidx1 * nb_comp;
     906        2712 :                         vparam.vertex_idx = vidx1;
     907        2712 :                         vparam.vertex_idx_in_prim = 0;
     908        2712 :                         GETVEC(pt1, idx1)
     909        2712 :                         evg3d_ndc_to_raster(surf, &s_pt1, &_x1, &_y1);
     910        2712 :                         if (prim_type>=GF_EVG_LINES) {
     911        2712 :                                 vidx2 = indices[i+1];
     912        2712 :                                 idx2 = vidx2 * nb_comp;
     913        2712 :                                 vparam.vertex_idx = vidx2;
     914        2712 :                                 vparam.vertex_idx_in_prim = 1;
     915        2712 :                                 GETVEC(pt2, idx2)
     916        2712 :                                 evg3d_ndc_to_raster(surf, &s_pt2, &_x2, &_y2);
     917        2712 :                                 if (prim_type>=GF_EVG_TRIANGLES) {
     918        2712 :                                         vidx3 = indices[i+2];
     919        2712 :                                         idx3 = vidx3 * nb_comp;
     920        2712 :                                         vparam.vertex_idx = vidx3;
     921        2712 :                                         vparam.vertex_idx_in_prim = 2;
     922        2712 :                                         GETVEC(pt3, idx3)
     923        2712 :                                         evg3d_ndc_to_raster(surf, &s_pt3, &_x3, &_y3);
     924        2712 :                                         if (prim_type==GF_EVG_QUADS) {
     925           0 :                                                 vidx4 = indices[i+3];
     926           0 :                                                 idx4 = vidx4 * nb_comp;
     927           0 :                                                 vparam.vertex_idx = vidx4;
     928           0 :                                                 vparam.vertex_idx_in_prim = 3;
     929           0 :                                                 GETVEC(pt4, idx4)
     930           0 :                                                 evg3d_ndc_to_raster(surf, &s_pt4, &_x4, &_y4);
     931             :                                         }
     932             :                                 }
     933             :                         }
     934             :                 }
     935             : #undef GETVEC
     936             : 
     937        2712 : restart_quad:
     938        2712 :                 raster->first_scanline = surf->height;
     939        2712 :                 raster->ex = (int) (raster->max_ex+1);
     940        2712 :                 raster->ey = (int) (raster->max_ey+1);
     941        2712 :                 raster->cover = 0;
     942        2712 :                 raster->area = 0;
     943             : 
     944             : 
     945        2712 :                 if (prim_type>=GF_EVG_TRIANGLES) {
     946             : 
     947        2712 :                         if (!precompute_tri(s3d, &frag_ckck, xmin, xmax, ymin, ymax, _x1, _y1, _x2, _y2, _x3, _y3, &s_pt1, &s_pt2, &s_pt3, vidx1, vidx2, vidx3))
     948           0 :                                 continue;
     949             : 
     950             :                         //check backcull
     951        2712 :                         if (s3d->is_ccw) {
     952        2712 :                                 if (s3d->area<0) {
     953        1610 :                                         if (s3d->backface_cull)
     954        1610 :                                                 continue;
     955             :                                 }
     956             :                         } else {
     957           0 :                                 if (s3d->area>0) {
     958           0 :                                         if (s3d->backface_cull)
     959           0 :                                                 continue;
     960             :                                 }
     961             :                         }
     962             :                 } else {
     963           0 :                         s3d->s_v1 = s_pt1;
     964           0 :                         frag_ckck.frag_param.idx1 = vidx1;
     965           0 :                         if (prim_type==GF_EVG_LINES) {
     966             :                                 GF_Vec lv;
     967           0 :                                 s3d->s_v2 = s_pt2;
     968           0 :                                 gf_vec_diff(lv, s_pt2, s_pt1);
     969           0 :                                 lv.z=0;
     970           0 :                                 s3d->v1v2_length = gf_vec_len(lv);
     971           0 :                                 frag_ckck.frag_param.idx2 = vidx2;
     972             :                         }
     973             :                 }
     974        1102 :                 frag_ckck.frag_param.prim_index = prim_index-1;
     975             : 
     976        1102 :                 if (prim_type==GF_EVG_POINTS) {
     977           0 :                         raster->idx1 = raster->idx2 = idx1;
     978             :                         //draw square
     979           0 :                         gray3d_move_to(raster, _x1-hpw, _y1-hpw);
     980           0 :                         gray_render_line(raster, _x1+hpw, _y1-hpw);
     981           0 :                         gray_render_line(raster, _x1+hpw, _y1+hpw);
     982           0 :                         gray_render_line(raster, _x1-hpw, _y1+hpw);
     983             :                         //and close
     984           0 :                         gray_render_line(raster, _x1-hpw, _y1-hpw);
     985           0 :                         gray_record_cell( raster );
     986        1102 :                 } else if (prim_type==GF_EVG_LINES) {
     987           0 :                         raster->idx1 = idx1;
     988           0 :                         raster->idx2 = idx2;
     989           0 :                         gray3d_move_to(raster, _x1+hlw, _y1+hlw);
     990           0 :                         gray_render_line(raster, _x1-hlw, _y1-hlw);
     991           0 :                         gray_render_line(raster, _x2-hlw, _y2-hlw);
     992           0 :                         gray_render_line(raster, _x2+hlw, _y2+hlw);
     993             :                         //and close
     994           0 :                         gray_render_line(raster, _x1+hlw, _y1+hlw);
     995           0 :                         gray_record_cell( raster );
     996             :                 } else {
     997        1102 :                         raster->idx1 = idx1;
     998        1102 :                         raster->idx2 = idx2;
     999        1102 :                         gray3d_move_to(raster, _x1, _y1);
    1000        1102 :                         gray_render_line(raster, _x2, _y2);
    1001        1102 :                         raster->idx1 = idx2;
    1002        1102 :                         raster->idx2 = idx3;
    1003        1102 :                         gray_render_line(raster, _x3, _y3);
    1004             : 
    1005             :                         //and close
    1006        1102 :                         raster->idx1 = idx3;
    1007        1102 :                         raster->idx2 = idx1;
    1008        1102 :                         gray_render_line(raster, _x1, _y1);
    1009        1102 :                         gray_record_cell( raster );
    1010             :                 }
    1011             : 
    1012             :                 /* sort each scanline and render it*/
    1013      113730 :                 for (li=raster->first_scanline; li<size_y; li++) {
    1014      113726 :                         AAScanline *sl = &raster->scanlines[li];
    1015             :                         //if nothing on this line, we are done for this primitive
    1016      113726 :                         if (!sl->num) break;
    1017             : 
    1018      112628 :                         if (sl->num>1) gray_quick_sort(sl->cells, sl->num);
    1019      112628 :                         gray_sweep_line(raster, sl, li, GF_FALSE);
    1020             : 
    1021      112628 :                         if (sl->pnum) {
    1022      111669 :                                 if (first_patch>li) first_patch = li;
    1023      111669 :                                 if (last_patch<li) last_patch = li;
    1024             :                         }
    1025             :                 }
    1026        1102 :                 if (!quad_done) {
    1027           0 :                         if (is_strip_fan) {
    1028           0 :                                 _prev_x2 = _x2;
    1029           0 :                                 _prev_y2 = _y2;
    1030           0 :                                 prev_s_pt2 = s_pt2;
    1031             :                                 prev_vidx2 = vidx2;
    1032             :                         }
    1033             :                         quad_done = GF_TRUE;
    1034           0 :                         _x2 = _x3;
    1035           0 :                         _y2 = _y3;
    1036           0 :                         _x3 = _x4;
    1037           0 :                         _y3 = _y4;
    1038           0 :                         s_pt2 = s_pt3;
    1039           0 :                         s_pt3 = s_pt4;
    1040             :                         vidx2 = vidx3;
    1041             :                         vidx3 = vidx4;
    1042           0 :                         s3d->s_v1 = s3d->s_v2;
    1043           0 :                         s3d->s_v2 = s3d->s_v3;
    1044           0 :                         goto restart_quad;
    1045             :                 }
    1046             :         }
    1047             : 
    1048             :         /*flush all partial fragments*/
    1049         226 :         span.len = 0;
    1050       32090 :         for (li=first_patch; li<=last_patch; li++) {
    1051       31864 :                 AAScanline *sl = &raster->scanlines[li];
    1052       31864 :                 Float *depth_line = &surf->ext3d->depth_buffer[li];
    1053      157108 :                 for (i=0; i<sl->pnum; i++) {
    1054      125244 :                         PatchPixel *pi = &sl->pixels[i];
    1055             : 
    1056      125244 :                         if (pi->cover == 0xFF) continue;
    1057      125244 :                         if (!surf->ext3d->depth_test(pi->write_depth, pi->depth)) continue;
    1058             : 
    1059      125244 :                         if (surf->fill_single) {
    1060       76878 :                                 surf->fill_single_a(li, pi->x, pi->cover, pi->color, surf);
    1061             :                         } else {
    1062       48366 :                                 span.coverage = pi->cover;
    1063       48366 :                                 span.x = pi->x;
    1064       48366 :                                 surf->gray_spans(li, 1, &span, surf);
    1065             :                         }
    1066      125244 :                         if (surf->ext3d->run_write_depth)
    1067      124826 :                                 depth_line[pi->x] = pi->depth;
    1068             :                 }
    1069             :         }
    1070             :         return GF_OK;
    1071             : }
    1072             : 
    1073         100 : GF_Err evg_raster_render3d_path(GF_EVGSurface *surf, GF_Path *path, Float z)
    1074             : {
    1075             : 
    1076             :         EVG_Vector   v_start;
    1077             :         int   n;         /* index of contour in outline     */
    1078             :         int   first;     /* index of first point in contour */
    1079             :         TPos _x, _y, _sx, _sy;
    1080             :         u32 li, size_y;
    1081         100 :         EVG_Raster raster = surf->raster;
    1082             :         EVG_Outline *outline;
    1083             :         GF_Matrix projModeView;
    1084         100 :         EVG_Surface3DExt *s3d = surf->ext3d;
    1085             :         EVGFragCallback frag_ckck;
    1086             :         u32 xmin, xmax, ymin, ymax;
    1087             :         GF_Err e;
    1088             :         GF_Rect rc;
    1089             : 
    1090         100 :         if (!surf->ext3d->frag_shader) return GF_BAD_PARAM;
    1091             : 
    1092         100 :         e = gf_evg_surface_set_path(surf, path);
    1093         100 :         if (e) return e;
    1094             : 
    1095             :         outline = &surf->ftoutline;
    1096             : 
    1097         100 :         raster->render_span  = (EVG_Raster_Span_Func) EVG3D_SpanFunc;
    1098         100 :         raster->render_span_data = &frag_ckck;
    1099             : 
    1100             :         /* Set up state in the raster object */
    1101         100 :         raster->min_ex = surf->clip_xMin;
    1102         100 :         raster->min_ey = surf->clip_yMin;
    1103         100 :         raster->max_ex = surf->clip_xMax;
    1104         100 :         raster->max_ey = surf->clip_yMax;
    1105         100 :         s3d->run_write_depth = s3d->depth_buffer ? s3d->write_depth : GF_FALSE;
    1106             : 
    1107         100 :         size_y = (u32) (raster->max_ey - raster->min_ey);
    1108         100 :         if (raster->max_lines < size_y) {
    1109           0 :                 raster->scanlines = (AAScanline*)gf_realloc(raster->scanlines, sizeof(AAScanline)*size_y);
    1110           0 :                 memset(&raster->scanlines[raster->max_lines], 0, sizeof(AAScanline)*(size_y-raster->max_lines) );
    1111           0 :                 raster->max_lines = size_y;
    1112             :         }
    1113             : 
    1114         100 :         gf_mx_copy(projModeView, s3d->proj);
    1115         100 :         gf_mx_add_matrix_4x4(&projModeView, &s3d->modelview);
    1116             : 
    1117         100 :         s3d->prim_type = GF_EVG_TRIANGLES;
    1118             :         memset(&frag_ckck, 0, sizeof(EVGFragCallback));
    1119         100 :         frag_ckck.surf = surf;
    1120         100 :         frag_ckck.frag_param.ptype = GF_EVG_TRIANGLES;
    1121             :         frag_ckck.frag_param.prim_index = 0;
    1122             : 
    1123         100 :         xmin = raster->min_ex * ONE_PIXEL;
    1124         100 :         xmax = raster->max_ex * ONE_PIXEL;
    1125         100 :         ymin = raster->min_ey * ONE_PIXEL;
    1126         100 :         ymax = raster->max_ey * ONE_PIXEL;
    1127             : 
    1128             :         //raster coordinates of points
    1129             :         TPos _x1, _y1, _x2, _y2, _x3, _y3;
    1130             :         /*vertices in raster/window space: x and y are in pixel space, z is [min_depth, max_depth]*/
    1131             :         GF_Vec4 s_pt1, s_pt2, s_pt3;
    1132             : 
    1133             :         /*get bounds, and compute interpolation from (top-left, top-right, bottom-right) vertices*/
    1134         100 :         gf_path_get_bounds(path, &rc);
    1135         100 :         s_pt1.x = rc.x; s_pt1.y = rc.y; s_pt1.z = z; s_pt1.q = 1;
    1136         100 :         s_pt2.x = rc.x + rc.width; s_pt2.y = rc.y; s_pt2.z = z; s_pt2.q = 1;
    1137         100 :         s_pt3.x = rc.x + rc.width; s_pt3.y = rc.y - rc.height ; s_pt3.z = z; s_pt3.q = 1;
    1138             : 
    1139         100 :         gf_mx_apply_vec_4x4(&projModeView, &s_pt1);
    1140             :         evg3d_persp_divide(&s_pt1);
    1141         100 :         evg3d_ndc_to_raster(surf, &s_pt1, &_x1, &_y1);
    1142         100 :         gf_mx_apply_vec_4x4(&projModeView, &s_pt2);
    1143             :         evg3d_persp_divide(&s_pt2);
    1144         100 :         evg3d_ndc_to_raster(surf, &s_pt2, &_x2, &_y2);
    1145         100 :         gf_mx_apply_vec_4x4(&projModeView, &s_pt3);
    1146             :         evg3d_persp_divide(&s_pt3);
    1147         100 :         evg3d_ndc_to_raster(surf, &s_pt3, &_x3, &_y3);
    1148             : 
    1149         100 :         if (!precompute_tri(s3d, &frag_ckck, xmin, xmax, ymin, ymax, _x1, _y1, _x2, _y2, _x3, _y3, &s_pt1, &s_pt2, &s_pt3, 0, 1, 2))
    1150             :                 return GF_OK;
    1151             : 
    1152         100 :         s3d->mode2d = GF_TRUE;
    1153             :         first = 0;
    1154        1700 :         for ( n = 0; n < outline->n_contours; n++ ) {
    1155             :                 GF_Vec4 pt;
    1156             :                 EVG_Vector *point;
    1157             :                 EVG_Vector *limit;
    1158             :                 int  last;  /* index of last point in contour */
    1159        1600 :                 last  = outline->contours[n];
    1160        1600 :                 limit = outline->points + last;
    1161        1600 :                 v_start = outline->points[first];
    1162             :                 point = outline->points + first;
    1163             : 
    1164        1600 :                 pt.x = v_start.x;
    1165        1600 :                 pt.y = v_start.y;
    1166        1600 :                 pt.z = z;
    1167        1600 :                 pt.q = 1;
    1168        1600 :                 gf_mx_apply_vec_4x4(&projModeView, &pt);
    1169             :                 if (!evg3d_persp_divide(&pt)) {
    1170           0 :                         continue;
    1171             :                 }
    1172        1600 :                 evg3d_ndc_to_raster(surf, &pt, &_sx, &_sy);
    1173        1600 :                 gray3d_move_to(raster, _sx, _sy);
    1174       42900 :                 while ( point < limit ) {
    1175       39700 :                         point++;
    1176             : 
    1177       39700 :                         pt.x = point->x;
    1178       39700 :                         pt.y = point->y;
    1179       39700 :                         pt.z = z;
    1180       39700 :                         pt.q = 1;
    1181       39700 :                         gf_mx_apply_vec_4x4(&projModeView, &pt);
    1182             :                         if (!evg3d_persp_divide(&pt)) {
    1183             :                                 break;
    1184             :                         }
    1185       39700 :                         evg3d_ndc_to_raster(surf, &pt, &_x, &_y);
    1186       39700 :                         gray_render_line(raster, _x, _y);
    1187             :                 }
    1188        1600 :                 gray_render_line(raster, _sx, _sy);
    1189             : 
    1190        1600 :                 first = last + 1;
    1191             :         }
    1192             : 
    1193         100 :         gray_record_cell( raster );
    1194             :         /* sort each scanline and render it*/
    1195       35816 :         for (li=raster->first_scanline; li<size_y; li++) {
    1196       35716 :                 AAScanline *sl = &raster->scanlines[li];
    1197       35716 :                 if (sl->num) {
    1198        7237 :                         if (sl->num>1) gray_quick_sort(sl->cells, sl->num);
    1199        7237 :                         gray_sweep_line(raster, sl, li, GF_TRUE);
    1200             :                 }
    1201             :         }
    1202         100 :         surf->ext3d->mode2d = GF_FALSE;
    1203         100 :         return GF_OK;
    1204             : 
    1205             : }
    1206          19 : GF_Err evg_3d_resize(GF_EVGSurface *surf)
    1207             : {
    1208             : /*      surf->ext3d->depth_buffer = gf_realloc(surf->ext3d->depth_buffer, sizeof(Float)*surf->width*surf->height);
    1209             :         if (!surf->ext3d->depth_buffer) return GF_OUT_OF_MEM;
    1210             : */
    1211          19 :         surf->ext3d->depth_buffer = NULL;
    1212             : 
    1213          19 :         if (!surf->ext3d->vp_w || !surf->ext3d->vp_h) {
    1214          19 :                 surf->ext3d->vp_x = 0;
    1215          19 :                 surf->ext3d->vp_y = 0;
    1216          19 :                 surf->ext3d->vp_w = surf->width;
    1217          19 :                 surf->ext3d->vp_h = surf->height;
    1218             :         }
    1219          19 :         surf->ext3d->pix_vals = gf_realloc(surf->ext3d->pix_vals, sizeof(u32)*surf->width);
    1220          19 :         return GF_OK;
    1221             : }
    1222             : 
    1223             : GF_EXPORT
    1224         226 : GF_Err gf_evg_surface_clear_depth(GF_EVGSurface *surf, Float depth)
    1225             : {
    1226             :         u32 i, lsize;
    1227             :         Float *depths;
    1228             :         u8 *depth_p;
    1229         226 :         if (!surf->ext3d) return GF_BAD_PARAM;
    1230             : 
    1231         226 :         depths = surf->ext3d->depth_buffer;
    1232         226 :         if (!depths) return GF_OK; //GF_BAD_PARAM;
    1233             :         //copy first line
    1234      196780 :         for (i=0; i<surf->width; i++) {
    1235      196780 :                 depths[i] = depth;
    1236             :         }
    1237             :         //copy first line
    1238         226 :         depth_p = (u8 *) surf->ext3d->depth_buffer;
    1239         226 :         lsize = sizeof(Float) * surf->width;
    1240      140220 :         for (i=1; i<surf->height; i++) {
    1241      139994 :                 u8 *depth_l = depth_p + i*lsize;
    1242      139994 :                 memcpy(depth_l, depth_p, lsize);
    1243             :         }
    1244             :         return GF_OK;
    1245             : }
    1246             : 
    1247             : 
    1248             : GF_EXPORT
    1249         226 : GF_Err gf_evg_surface_viewport(GF_EVGSurface *surf, u32 x, u32 y, u32 w, u32 h)
    1250             : {
    1251         226 :         if (!surf->ext3d) return GF_BAD_PARAM;
    1252         226 :         surf->ext3d->vp_x = x;
    1253         226 :         surf->ext3d->vp_y = y;
    1254         226 :         surf->ext3d->vp_w = w;
    1255         226 :         surf->ext3d->vp_h = h;
    1256         226 :         return GF_OK;
    1257             : }
    1258             : 
    1259        9587 : static Bool depth_test_never(Float depth_buf_value, Float frag_value)
    1260             : {
    1261        9587 :         return GF_FALSE;
    1262             : }
    1263       20010 : static Bool depth_test_always(Float depth_buf_value, Float frag_value)
    1264             : {
    1265       20010 :         return GF_TRUE;
    1266             : }
    1267     4898457 : static Bool depth_test_less(Float depth_buf_value, Float frag_value)
    1268             : {
    1269     4898457 :         if (frag_value<depth_buf_value) return GF_TRUE;
    1270       20411 :         return GF_FALSE;
    1271             : }
    1272       10005 : static Bool depth_test_less_equal(Float depth_buf_value, Float frag_value)
    1273             : {
    1274       10005 :         if (frag_value<=depth_buf_value) return GF_TRUE;
    1275           0 :         return GF_FALSE;
    1276             : }
    1277        9587 : static Bool depth_test_equal(Float depth_buf_value, Float frag_value)
    1278             : {
    1279        9587 :         if (frag_value==depth_buf_value) return GF_TRUE;
    1280        9587 :         return GF_FALSE;
    1281             : }
    1282       10005 : static Bool depth_test_greater(Float depth_buf_value, Float frag_value)
    1283             : {
    1284       10005 :         if (frag_value>depth_buf_value) return GF_TRUE;
    1285           0 :         return GF_FALSE;
    1286             : }
    1287       10005 : static Bool depth_test_greater_equal(Float depth_buf_value, Float frag_value)
    1288             : {
    1289       10005 :         if (frag_value>=depth_buf_value) return GF_TRUE;
    1290           0 :         return GF_FALSE;
    1291             : }
    1292       10005 : static Bool depth_test_not_equal(Float depth_buf_value, Float frag_value)
    1293             : {
    1294       10005 :         if (frag_value==depth_buf_value) return GF_FALSE;
    1295       10005 :         return GF_TRUE;
    1296             : }
    1297             : 
    1298             : GF_EXPORT
    1299         226 : GF_Err gf_evg_set_depth_test(GF_EVGSurface *surf, GF_EVGDepthTest mode)
    1300             : {
    1301         226 :         if (!surf->ext3d) return GF_BAD_PARAM;
    1302         226 :         surf->ext3d->write_depth = GF_TRUE;
    1303         226 :         switch (mode) {
    1304           1 :         case GF_EVGDEPTH_NEVER:
    1305           1 :                 surf->ext3d->depth_test = depth_test_never;
    1306           1 :                 return GF_OK;
    1307           1 :         case GF_EVGDEPTH_ALWAYS:
    1308           1 :                 surf->ext3d->depth_test = depth_test_always;
    1309           1 :                 return GF_OK;
    1310           1 :         case GF_EVGDEPTH_EQUAL:
    1311           1 :                 surf->ext3d->depth_test = depth_test_equal;
    1312           1 :                 return GF_OK;
    1313           1 :         case GF_EVGDEPTH_NEQUAL:
    1314           1 :                 surf->ext3d->depth_test = depth_test_not_equal;
    1315           1 :                 return GF_OK;
    1316         218 :         case GF_EVGDEPTH_LESS:
    1317         218 :                 surf->ext3d->depth_test = depth_test_less;
    1318         218 :                 return GF_OK;
    1319           1 :         case GF_EVGDEPTH_LESS_EQUAL:
    1320           1 :                 surf->ext3d->depth_test = depth_test_less_equal;
    1321           1 :                 return GF_OK;
    1322           1 :         case GF_EVGDEPTH_GREATER:
    1323           1 :                 surf->ext3d->depth_test = depth_test_greater;
    1324           1 :                 return GF_OK;
    1325           1 :         case GF_EVGDEPTH_GREATER_EQUAL:
    1326           1 :                 surf->ext3d->depth_test = depth_test_greater_equal;
    1327           1 :                 return GF_OK;
    1328           1 :         case GF_EVGDEPTH_DISABLE:
    1329           1 :                 surf->ext3d->depth_test = depth_test_always;
    1330           1 :                 surf->ext3d->write_depth = GF_FALSE;
    1331           1 :                 return GF_OK;
    1332             :         }
    1333             :         return GF_BAD_PARAM;
    1334             : 
    1335             : }
    1336             : 
    1337         164 : GF_Err evg_3d_update_depth_range(GF_EVGSurface *surf)
    1338             : {
    1339         164 :         if (!surf || !surf->ext3d) return GF_BAD_PARAM;
    1340         145 :         surf->ext3d->depth_range = surf->ext3d->max_depth - surf->ext3d->min_depth;
    1341         145 :         if (surf->ext3d->clip_zero) {
    1342         145 :                 surf->ext3d->zw_factor = surf->ext3d->depth_range;
    1343         145 :                 surf->ext3d->zw_offset = surf->ext3d->min_depth;
    1344             :         } else {
    1345           0 :                 surf->ext3d->zw_factor = surf->ext3d->depth_range / 2;
    1346           0 :                 surf->ext3d->zw_offset = (surf->ext3d->min_depth+surf->ext3d->max_depth)/2;
    1347             : 
    1348             :         }
    1349             :         return GF_OK;
    1350             : }
    1351             : 
    1352      238255 : static void yuv_3d_fill_run(GF_EVGStencil *p, GF_EVGSurface *surf, s32 _x, s32 _y, u32 count)
    1353             : {
    1354      238255 :         u32 *data = surf->stencil_pix_run;
    1355      238255 :         u32 *src = surf->ext3d->pix_vals + _x;
    1356             : 
    1357      238255 :         memcpy(data, src, sizeof(u32)*count);
    1358      238255 : }
    1359             : 
    1360          19 : EVG_Surface3DExt *evg_init_3d_surface(GF_EVGSurface *surf)
    1361             : {
    1362             :         EVG_Surface3DExt *ext3d;
    1363          19 :         GF_SAFEALLOC(ext3d, EVG_Surface3DExt);
    1364          19 :         if (!ext3d) return NULL;
    1365          38 :         gf_mx_init(ext3d->proj);
    1366          38 :         gf_mx_init(ext3d->modelview);
    1367          19 :         ext3d->backface_cull = GF_TRUE;
    1368          19 :         ext3d->is_ccw = GF_TRUE;
    1369          19 :         ext3d->min_depth = 0;
    1370          19 :         ext3d->max_depth = FIX_ONE;
    1371          19 :         ext3d->depth_range = FIX_ONE;
    1372          19 :         ext3d->point_size = FIX_ONE;
    1373          19 :         ext3d->line_size = FIX_ONE;
    1374          19 :         ext3d->clip_zero = GF_FALSE;
    1375          19 :         ext3d->disable_aa = GF_FALSE;
    1376          19 :         ext3d->write_depth = GF_TRUE;
    1377          19 :         ext3d->early_depth_test = GF_TRUE;
    1378          19 :         ext3d->depth_test = depth_test_less;
    1379          19 :         ext3d->yuv_sten.fill_run = yuv_3d_fill_run;
    1380          19 :         evg_3d_update_depth_range(surf);
    1381          19 :         return ext3d;
    1382             : }
    1383             : 
    1384             : 
    1385             : 
    1386         326 : GF_Err gf_evg_surface_set_fragment_shader(GF_EVGSurface *surf, gf_evg_fragment_shader shader, void *shader_udta)
    1387             : {
    1388         326 :         if (!surf || !surf->ext3d) return GF_BAD_PARAM;
    1389         326 :         surf->ext3d->frag_shader = shader;
    1390         326 :         surf->ext3d->frag_shader_udta = shader_udta;
    1391         326 :         return GF_OK;
    1392             : }
    1393             : 
    1394         326 : GF_Err gf_evg_surface_disable_early_depth(GF_EVGSurface *surf, Bool disable)
    1395             : {
    1396         326 :         if (!surf || !surf->ext3d) return GF_BAD_PARAM;
    1397         326 :         surf->ext3d->early_depth_test = !disable;
    1398         326 :         return GF_OK;
    1399             : }
    1400             : 
    1401         225 : GF_Err gf_evg_surface_set_vertex_shader(GF_EVGSurface *surf, gf_evg_vertex_shader shader, void *shader_udta)
    1402             : {
    1403         225 :         if (!surf || !surf->ext3d) return GF_BAD_PARAM;
    1404         225 :         surf->ext3d->vert_shader = shader;
    1405         225 :         surf->ext3d->vert_shader_udta = shader_udta;
    1406         225 :         return GF_OK;
    1407             : }
    1408             : 
    1409          10 : GF_Err gf_evg_surface_set_ccw(GF_EVGSurface *surf, Bool is_ccw)
    1410             : {
    1411          10 :         if (!surf || !surf->ext3d) return GF_BAD_PARAM;
    1412          10 :         surf->ext3d->is_ccw = is_ccw;
    1413          10 :         return GF_OK;
    1414             : }
    1415         226 : GF_Err gf_evg_surface_set_backcull(GF_EVGSurface *surf, Bool backcull)
    1416             : {
    1417         226 :         if (!surf || !surf->ext3d) return GF_BAD_PARAM;
    1418         226 :         surf->ext3d->backface_cull = backcull;
    1419         226 :         return GF_OK;
    1420             : }
    1421         226 : GF_Err gf_evg_surface_set_antialias(GF_EVGSurface *surf, Bool antialias)
    1422             : {
    1423         226 :         if (!surf || !surf->ext3d) return GF_BAD_PARAM;
    1424         226 :         surf->ext3d->disable_aa = antialias ? GF_FALSE : GF_TRUE;
    1425         226 :         return GF_OK;
    1426             : }
    1427          10 : GF_Err gf_evg_surface_set_min_depth(GF_EVGSurface *surf, Float min_depth)
    1428             : {
    1429          10 :         if (!surf || !surf->ext3d) return GF_BAD_PARAM;
    1430          10 :         surf->ext3d->min_depth = min_depth;
    1431          10 :         evg_3d_update_depth_range(surf);
    1432          10 :         return GF_OK;
    1433             : }
    1434          10 : GF_Err gf_evg_surface_set_max_depth(GF_EVGSurface *surf, Float max_depth)
    1435             : {
    1436          10 :         if (!surf || !surf->ext3d) return GF_BAD_PARAM;
    1437          10 :         surf->ext3d->max_depth = max_depth;
    1438          10 :         evg_3d_update_depth_range(surf);
    1439          10 :         return GF_OK;
    1440             : }
    1441             : 
    1442         125 : GF_Err gf_evg_surface_set_clip_zero(GF_EVGSurface *surf, Bool clip_zero)
    1443             : {
    1444         125 :         if (!surf || !surf->ext3d) return GF_BAD_PARAM;
    1445         125 :         surf->ext3d->clip_zero = clip_zero;
    1446         125 :         evg_3d_update_depth_range(surf);
    1447         125 :         return GF_OK;
    1448             : }
    1449             : 
    1450          10 : GF_Err gf_evg_surface_set_point_size(GF_EVGSurface *surf, Float size)
    1451             : {
    1452          10 :         if (!surf || !surf->ext3d) return GF_BAD_PARAM;
    1453          10 :         surf->ext3d->point_size = size;
    1454          10 :         return GF_OK;
    1455             : }
    1456          10 : GF_Err gf_evg_surface_set_line_size(GF_EVGSurface *surf, Float size)
    1457             : {
    1458          10 :         if (!surf || !surf->ext3d) return GF_BAD_PARAM;
    1459          10 :         surf->ext3d->line_size = size;
    1460          10 :         return GF_OK;
    1461             : }
    1462          10 : GF_Err gf_evg_surface_set_point_smooth(GF_EVGSurface *surf, Bool smooth)
    1463             : {
    1464          10 :         if (!surf || !surf->ext3d) return GF_BAD_PARAM;
    1465          10 :         surf->ext3d->smooth_points = smooth;
    1466          10 :         return GF_OK;
    1467             : }
    1468             : 
    1469          10 : GF_Err gf_evg_surface_write_depth(GF_EVGSurface *surf, Bool do_write)
    1470             : {
    1471          10 :         if (!surf || !surf->ext3d) return GF_BAD_PARAM;
    1472          10 :         surf->ext3d->write_depth = do_write;
    1473          10 :         return GF_OK;
    1474             : }
    1475          19 : GF_Err gf_evg_surface_set_depth_buffer(GF_EVGSurface *surf, Float *depth)
    1476             : {
    1477          19 :         if (!surf || !surf->ext3d) return GF_BAD_PARAM;
    1478          19 :         surf->ext3d->depth_buffer = depth;
    1479          19 :         return GF_OK;
    1480             : }

Generated by: LCOV version 1.13