LCOV - code coverage report
Current view: top level - compositor - visual_manager_2d_draw.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 281 339 82.9 %
Date: 2021-04-29 23:48:07 Functions: 16 16 100.0 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2000-2012
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / Scene Compositor sub-project
       9             :  *
      10             :  *  GPAC is free software; you can redistribute it and/or modify
      11             :  *  it under the terms of the GNU Lesser General Public License as published by
      12             :  *  the Free Software Foundation; either version 2, or (at your option)
      13             :  *  any later version.
      14             :  *
      15             :  *  GPAC is distributed in the hope that it will be useful,
      16             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :  *  GNU Lesser General Public License for more details.
      19             :  *
      20             :  *  You should have received a copy of the GNU Lesser General Public
      21             :  *  License along with this library; see the file COPYING.  If not, write to
      22             :  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
      23             :  *
      24             :  */
      25             : 
      26             : #include "visual_manager.h"
      27             : #include "drawable.h"
      28             : #include "nodes_stacks.h"
      29             : #include "texturing.h"
      30             : #include <gpac/options.h>
      31             : 
      32             : //#define SKIP_DRAW
      33             : 
      34       22826 : GF_Err visual_2d_init_raster(GF_VisualManager *visual)
      35             : {
      36       22826 :         if (!visual->raster_surface) {
      37         582 :                 visual->raster_surface = gf_evg_surface_new(visual->center_coords);
      38         582 :                 if (!visual->raster_surface) return GF_IO_ERR;
      39             :         }
      40       22826 :         return visual->GetSurfaceAccess(visual);
      41             : }
      42             : 
      43       22826 : void visual_2d_release_raster(GF_VisualManager *visual)
      44             : {
      45       22826 :         if (visual->raster_surface) {
      46       22826 :                 visual->ReleaseSurfaceAccess(visual);
      47             :         }
      48       22826 : }
      49             : 
      50             : 
      51        3125 : void visual_2d_clear_surface(GF_VisualManager *visual, GF_IRect *rc, u32 BackColor, u32 is_offscreen)
      52             : {
      53             : #ifdef SKIP_DRAW
      54             :         return;
      55             : #endif
      56        3125 :         if (! visual->CheckAttached(visual) ) return;
      57             : 
      58        3125 :         if (!BackColor && !visual->offscreen && !visual->compositor->dyn_filter_mode) {
      59        1796 :                 if ( !(visual->compositor->init_flags & GF_TERM_WINDOW_TRANSPARENT)) {
      60        1796 :                         BackColor = visual->compositor->back_color;
      61             :                 }
      62             :         }
      63             : 
      64        3125 :         gf_evg_surface_clear(visual->raster_surface, rc, BackColor);
      65             : }
      66             : 
      67         166 : static void draw_clipper(GF_VisualManager *visual, struct _drawable_context *ctx)
      68             : {
      69             :         GF_PenSettings clipset;
      70             :         GF_Path *clippath, *cliper;
      71             : 
      72         166 :         if (ctx->flags & CTX_IS_BACKGROUND) return;
      73             : 
      74             :         memset(&clipset, 0, sizeof(GF_PenSettings));
      75         166 :         clipset.width = 2*FIX_ONE;
      76             : 
      77         166 :         clippath = gf_path_new();
      78         166 :         gf_path_add_rect_center(clippath, ctx->bi->unclip.x + ctx->bi->unclip.width/2, ctx->bi->unclip.y - ctx->bi->unclip.height/2, ctx->bi->unclip.width, ctx->bi->unclip.height);
      79         166 :         cliper = gf_path_get_outline(clippath, clipset);
      80         166 :         gf_path_del(clippath);
      81         166 :         gf_evg_surface_set_matrix(visual->raster_surface, NULL);
      82         166 :         gf_evg_surface_set_clipper(visual->raster_surface, NULL);
      83         166 :         gf_evg_surface_set_path(visual->raster_surface, cliper);
      84         166 :         gf_evg_stencil_set_brush_color(visual->raster_brush, 0xFF000000);
      85         166 :         gf_evg_surface_fill(visual->raster_surface, visual->raster_brush);
      86         166 :         gf_path_del(cliper);
      87             : }
      88             : 
      89      685725 : static void visual_2d_fill_path(GF_VisualManager *visual, DrawableContext *ctx, GF_EVGStencil * stencil, GF_TraverseState *tr_state, Bool is_erase)
      90             : {
      91             :         Bool has_modif = GF_FALSE;
      92             :         GF_IRect clip;
      93             : 
      94             :         /*direct drawing : use ctx clip*/
      95      685725 :         if (tr_state->immediate_draw) {
      96       23616 :                 if (ctx->bi->clip.width && ctx->bi->clip.height) {
      97       23616 :                         GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Visual2D] Redrawing node %s [%s] (direct draw)\n", gf_node_get_log_name(ctx->drawable->node), gf_node_get_class_name(ctx->drawable->node) ));
      98             : 
      99       23616 :                         if (stencil) {
     100       23616 :                                 gf_evg_surface_set_clipper(visual->raster_surface, &ctx->bi->clip);
     101       23616 :                                 gf_evg_surface_fill(visual->raster_surface, stencil);
     102             :                         } else {
     103           0 :                                 gf_evg_surface_clear(visual->raster_surface, &ctx->bi->clip, 0);
     104             :                         }
     105             : 
     106             :                         has_modif = GF_TRUE;
     107             :                 }
     108             :         }
     109             :         /*indirect drawing, draw path in all dirty areas*/
     110             :         else {
     111             :                 u32 i;
     112     1184111 :                 for (i=0; i<visual->to_redraw.count; i++) {
     113             :                         /*there's an opaque region above, don't draw*/
     114             : #ifdef TRACK_OPAQUE_REGIONS
     115             :                         if (!is_erase && (visual->draw_node_index<visual->to_redraw.list[i].opaque_node_index)) continue;
     116             : #endif
     117     1184111 :                         clip = ctx->bi->clip;
     118     1184111 :                         gf_irect_intersect(&clip, &visual->to_redraw.list[i].rect);
     119     1184111 :                         if (clip.width && clip.height) {
     120      230629 :                                 GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Visual2D] Redrawing node %s [%s] (indirect draw @ dirty rect idx %d)\n", gf_node_get_log_name(ctx->drawable->node), gf_node_get_class_name(ctx->drawable->node), i));
     121      230629 :                                 if (stencil) {
     122      230629 :                                         gf_evg_surface_set_clipper(visual->raster_surface, &clip);
     123      230629 :                                         gf_evg_surface_fill(visual->raster_surface, stencil);
     124             :                                 } else {
     125           0 :                                         gf_evg_surface_clear(visual->raster_surface, &clip, 0);
     126             :                                 }
     127             :                                 has_modif = 1;
     128             :                         }
     129             :                 }
     130             :         }
     131             : #ifndef GPAC_DISABLE_3D
     132      685725 :         if (!is_erase)
     133      685425 :                 visual->nb_objects_on_canvas_since_last_ogl_flush++;
     134             : #endif
     135      685725 :         if (has_modif) {
     136      253097 :                 visual->has_modif = 1;
     137             : #ifndef GPAC_DISABLE_3D
     138      253097 :                 if (!visual->offscreen && visual->compositor->hybrid_opengl && !is_erase)
     139       21817 :                         ra_union_rect(&visual->hybgl_drawn, &ctx->bi->clip);
     140             : #endif
     141             :         }
     142      685725 : }
     143             : 
     144      674164 : static void visual_2d_set_options(GF_Compositor *compositor, GF_EVGSurface *rend, Bool forText, Bool no_antialias)
     145             : {
     146      674164 :         if (no_antialias) {
     147       14126 :                 gf_evg_surface_set_raster_level(rend, GF_RASTER_HIGH_SPEED);
     148             :         } else {
     149      660078 :                 switch (compositor->aa) {
     150           0 :                 case GF_ANTIALIAS_NONE:
     151           0 :                         gf_evg_surface_set_raster_level(rend, GF_RASTER_HIGH_SPEED);
     152             :                         break;
     153           0 :                 case GF_ANTIALIAS_TEXT:
     154           0 :                         if (forText) {
     155           0 :                                 gf_evg_surface_set_raster_level(rend, GF_RASTER_HIGH_QUALITY);
     156             :                         } else {
     157           0 :                                 gf_evg_surface_set_raster_level(rend, compositor->fast ? GF_RASTER_HIGH_QUALITY : GF_RASTER_MID);
     158             :                         }
     159             :                         break;
     160      660078 :                 case GF_ANTIALIAS_FULL:
     161             :                 default:
     162      660078 :                         gf_evg_surface_set_raster_level(rend, GF_RASTER_HIGH_QUALITY);
     163             :                         break;
     164             :                 }
     165             :         }
     166      674164 : }
     167             : 
     168             : 
     169             : #ifndef GPAC_DISABLE_VRML
     170       16211 : static void visual_2d_get_texture_transform(GF_Node *__appear, GF_TextureHandler *txh, GF_Matrix2D *mat, Bool line_texture, Fixed final_width, Fixed final_height)
     171             : {
     172             :         u32 node_tag;
     173             :         M_Appearance *appear;
     174             :         GF_Node *txtrans = NULL;
     175       32422 :         gf_mx2d_init(*mat);
     176             : 
     177       16211 :         if (!__appear || !txh) return;
     178             :         appear = (M_Appearance *)__appear;
     179             : 
     180       16211 :         if (!line_texture) {
     181       14590 :                 if (!appear->textureTransform) return;
     182             :                 txtrans = appear->textureTransform;
     183             :         } else {
     184        1621 :                 if (gf_node_get_tag(appear->material) != TAG_MPEG4_Material2D) return;
     185        1621 :                 if (gf_node_get_tag(((M_Material2D *)appear->material)->lineProps) != TAG_MPEG4_XLineProperties) return;
     186        1621 :                 txtrans = ((M_XLineProperties *) ((M_Material2D *)appear->material)->lineProps)->textureTransform;
     187             :         }
     188        3260 :         if (!txtrans) return;
     189             : 
     190             :         /*gradient doesn't need bounds info in texture transform*/
     191        1933 :         if (txh->compute_gradient_matrix) {
     192             :                 final_width = final_height = FIX_ONE;
     193             :         }
     194        1933 :         node_tag = gf_node_get_tag(txtrans);
     195        1933 :         if (node_tag==TAG_MPEG4_TextureTransform) {
     196             :                 /*VRML: Tc' = -C � S � R � C � T � Tc*/
     197             :                 M_TextureTransform *txt = (M_TextureTransform *) txtrans;
     198        1051 :                 SFVec2f scale = txt->scale;
     199        1051 :                 if (!scale.x) scale.x = FIX_ONE/100;
     200        1051 :                 if (!scale.y) scale.y = FIX_ONE/100;
     201             : 
     202        1051 :                 gf_mx2d_add_translation(mat, -gf_mulfix(txt->center.x, final_width), -gf_mulfix(txt->center.y, final_height) );
     203        1051 :                 gf_mx2d_add_scale(mat, scale.x, scale.y);
     204        1051 :                 gf_mx2d_add_rotation(mat, 0, 0, txt->rotation);
     205        1051 :                 gf_mx2d_add_translation(mat, gf_mulfix(txt->center.x, final_width), gf_mulfix(txt->center.y, final_height) );
     206        1051 :                 gf_mx2d_add_translation(mat, gf_mulfix(txt->translation.x, final_width), gf_mulfix(txt->translation.y, final_height) );
     207             :                 /*and inverse the matrix (this is texture transform, cf VRML)*/
     208        1051 :                 gf_mx2d_inverse(mat);
     209             :                 return;
     210             :         }
     211         882 :         if (node_tag==TAG_MPEG4_TransformMatrix2D) {
     212         882 :                 tr_mx2d_get_matrix((GF_Node *) txtrans, mat);
     213         882 :                 mat->m[2] = gf_mulfix(mat->m[2], final_width);
     214         882 :                 mat->m[5] = gf_mulfix(mat->m[5], final_height);
     215         882 :                 gf_mx2d_inverse(mat);
     216         882 :                 return;
     217             :         }
     218             : }
     219             : #endif /*GPAC_DISABLE_VRML*/
     220             : 
     221       11692 : static void visual_2d_draw_gradient(GF_VisualManager *visual, GF_Path *path, GF_TextureHandler *txh, struct _drawable_context *ctx, GF_TraverseState *tr_state, GF_Matrix2D *ext_mx, GF_Rect *orig_bounds)
     222             : {
     223             :         GF_Rect rc;
     224             :         GF_EVGStencil * stencil;
     225             :         GF_Matrix2D g_mat;
     226             : 
     227       11692 :         if (!txh) txh = ctx->aspect.fill_texture;
     228             : 
     229       11692 :         gf_path_get_bounds(path, &rc);
     230       11692 :         if (!rc.width || !rc.height || !txh->tx_io) return;
     231             : 
     232       11692 :         if (orig_bounds) {
     233        5134 :                 txh->compute_gradient_matrix(txh, orig_bounds, &g_mat, 0);
     234             :         } else {
     235        6558 :                 txh->compute_gradient_matrix(txh, &rc, &g_mat, 0);
     236             :         }
     237       11692 :         stencil = gf_sc_texture_get_stencil(txh);
     238       11692 :         if (!stencil) return;
     239             : 
     240             : #ifndef GPAC_DISABLE_VRML
     241       11692 :         if (ctx->flags & CTX_HAS_APPEARANCE) {
     242             :                 GF_Matrix2D txt_mat;
     243       11482 :                 visual_2d_get_texture_transform(ctx->appear, txh, &txt_mat, (txh == ctx->aspect.fill_texture) ? 0 : 1, INT2FIX(txh->width), INT2FIX(txh->height));
     244       11482 :                 gf_mx2d_add_matrix(&g_mat, &txt_mat);
     245             :         }
     246             : #endif
     247             : 
     248             :         /*move to bottom-left corner of bounds */
     249       11692 :         if (ext_mx) gf_mx2d_add_matrix(&g_mat, ext_mx);
     250       11692 :         if (orig_bounds) gf_mx2d_add_translation(&g_mat, (orig_bounds->x), (orig_bounds->y - orig_bounds->height));
     251             : 
     252       11692 :         gf_mx2d_add_matrix(&g_mat, &ctx->transform);
     253             : 
     254       11692 :         gf_evg_stencil_set_matrix(stencil, &g_mat);
     255       11692 :         gf_evg_stencil_set_color_matrix(stencil, ctx->col_mat);
     256             : 
     257             :         /*MPEG-4/VRML context or no fill info*/
     258       11692 :         if (ctx->flags & CTX_HAS_APPEARANCE || !ctx->aspect.fill_color)
     259       11482 :                 gf_evg_stencil_set_alpha(stencil, 0xFF);
     260             :         else
     261         210 :                 gf_evg_stencil_set_alpha(stencil, GF_COL_A(ctx->aspect.fill_color) );
     262             : 
     263       11692 :         gf_evg_surface_set_matrix(visual->raster_surface, &ctx->transform);
     264       11692 :         txh->flags |= GF_SR_TEXTURE_USED;
     265             : 
     266       11692 :         gf_evg_surface_set_path(visual->raster_surface, path);
     267       11692 :         visual_2d_fill_path(visual, ctx, stencil, tr_state, 0);
     268       11692 :         gf_evg_surface_set_path(visual->raster_surface, NULL);
     269             : 
     270       11692 :         ctx->flags |= CTX_PATH_FILLED;
     271             : }
     272             : 
     273             : 
     274             : 
     275          40 : void visual_2d_texture_path_text(GF_VisualManager *visual, DrawableContext *txt_ctx, GF_Path *path, GF_Rect *object_bounds, GF_TextureHandler *txh, GF_TraverseState *tr_state)
     276             : {
     277             :         GF_EVGStencil * stencil;
     278             :         Fixed sS, sT;
     279             :         GF_Matrix2D gf_mx2d_txt;
     280             :         GF_Rect orig_rc;
     281             :         u8 alpha, r, g, b;
     282             :         GF_ColorMatrix cmat;
     283             : 
     284          40 :         if (! visual->CheckAttached(visual) ) return;
     285             : 
     286             : 
     287          40 :         stencil = gf_sc_texture_get_stencil(txh);
     288          40 :         if (!stencil) return;
     289             : 
     290          40 :         visual_2d_set_options(visual->compositor, visual->raster_surface, 0, 1);
     291             : 
     292             :         /*get original bounds*/
     293          40 :         orig_rc = *object_bounds;
     294             : 
     295             :         /*get scaling ratio so that active texture view is stretched to original bounds (std 2D shape texture mapping in MPEG4)*/
     296          40 :         sS = gf_divfix(orig_rc.width, INT2FIX(txh->width));
     297          40 :         sT = gf_divfix(orig_rc.height, INT2FIX(txh->height));
     298             : 
     299          40 :         gf_mx2d_init(gf_mx2d_txt);
     300          40 :         gf_mx2d_add_scale(&gf_mx2d_txt, sS, sT);
     301             : 
     302             :         /*move to bottom-left corner of bounds */
     303          40 :         gf_mx2d_add_translation(&gf_mx2d_txt, (orig_rc.x), (orig_rc.y - orig_rc.height));
     304             : 
     305             :         /*move to final coordinate system*/
     306          40 :         gf_mx2d_add_matrix(&gf_mx2d_txt, &txt_ctx->transform);
     307             : 
     308             :         /*set path transform, except for background2D node which is directly build in the final coord system*/
     309          40 :         gf_evg_stencil_set_matrix(stencil, &gf_mx2d_txt);
     310             : 
     311          40 :         alpha = GF_COL_A(txt_ctx->aspect.fill_color);
     312          40 :         r = GF_COL_R(txt_ctx->aspect.fill_color);
     313          40 :         g = GF_COL_G(txt_ctx->aspect.fill_color);
     314          40 :         b = GF_COL_B(txt_ctx->aspect.fill_color);
     315             : 
     316             :         /*if col do a cxmatrix*/
     317          40 :         if (!r && !g && !b) {
     318          40 :                 gf_evg_stencil_set_alpha(stencil, alpha);
     319             :         } else {
     320           0 :                 gf_evg_stencil_set_alpha(stencil, 0xFF);
     321             :                 memset(cmat.m, 0, sizeof(Fixed) * 20);
     322           0 :                 cmat.m[4] = INT2FIX(r)/255;
     323           0 :                 cmat.m[9] = INT2FIX(g)/255;
     324           0 :                 cmat.m[14] = INT2FIX(b)/255;
     325           0 :                 cmat.m[18] = INT2FIX(alpha)/255;
     326           0 :                 cmat.identity = 0;
     327           0 :                 gf_evg_stencil_set_color_matrix(stencil, &cmat);
     328             :         }
     329             : 
     330          40 :         gf_evg_surface_set_matrix(visual->raster_surface, &txt_ctx->transform);
     331          40 :         txh->flags |= GF_SR_TEXTURE_USED;
     332             : 
     333             :         /*push path*/
     334          40 :         gf_evg_surface_set_path(visual->raster_surface, path);
     335             : 
     336          40 :         visual_2d_fill_path(visual, txt_ctx, stencil, tr_state, 0);
     337          40 :         gf_evg_surface_set_path(visual->raster_surface, NULL);
     338          40 :         txt_ctx->flags |= CTX_PATH_FILLED;
     339             : }
     340             : 
     341             : 
     342             : #ifndef GPAC_DISABLE_3D
     343             : 
     344        1553 : void visual_2d_flush_hybgl_canvas(GF_VisualManager *visual, GF_TextureHandler *txh, struct _drawable_context *ctx, GF_TraverseState *tr_state)
     345             : {
     346             :         Bool line_texture = GF_FALSE;
     347             :         u32 i;
     348             :         u32 prev_color;
     349             :         Bool transparent, had_flush = 0;
     350        1553 :         u32 nb_obj_left_on_canvas = visual->nb_objects_on_canvas_since_last_ogl_flush;
     351             :         u8 alpha;
     352             : 
     353        1553 :         if (! visual->hybgl_drawn.count)
     354             :                 return;
     355             : 
     356             :         //we have drawn things on the canvas before this object, flush canvas to GPU
     357             : 
     358        1078 :         if (txh && (txh==ctx->aspect.line_texture)) {
     359             :                 line_texture = GF_TRUE;
     360           0 :                 alpha = GF_COL_A(ctx->aspect.line_color);
     361             :                 prev_color = ctx->aspect.line_color;
     362           0 :                 ctx->aspect.line_texture = NULL;
     363           0 :                 ctx->aspect.line_color = 0;
     364             :         } else {
     365        1078 :                 alpha = GF_COL_A(ctx->aspect.fill_color);
     366        1078 :                 if (!alpha) alpha = GF_COL_A(ctx->aspect.line_color);
     367             :                 prev_color = ctx->aspect.fill_color;
     368        1078 :                 ctx->aspect.fill_texture = NULL;
     369        1078 :                 ctx->aspect.fill_color = 0;
     370             : 
     371             :         }
     372        1078 :         transparent = txh ? (txh->transparent || (alpha!=0xFF)) : GF_TRUE;
     373             :         //clear wherever we have overlap
     374        2165 :         for (i=0; i<visual->hybgl_drawn.count; i++) {
     375        1087 :                 GF_IRect rc = ctx->bi->clip;
     376        1087 :                 gf_irect_intersect(&ctx->bi->clip, &visual->hybgl_drawn.list[i].rect);
     377        1087 :                 if (ctx->bi->clip.width && ctx->bi->clip.height) {
     378             :                         //if something behind this, flush canvas to gpu
     379        1051 :                         if (transparent) {
     380         901 :                                 if (!had_flush) {
     381             :                                         //flush the complete area below this object, regardless of intersections
     382         901 :                                         compositor_2d_hybgl_flush_video(visual->compositor, tr_state->immediate_draw ? NULL : &rc);
     383             :                                         had_flush = 1;
     384             :                                 }
     385             :                                 //if object was not completely in the flush region we will need to flush the canvas
     386         901 :                                 if ( gf_irect_inside(&rc, &visual->hybgl_drawn.list[i].rect)) {
     387             :                                         //it may happen that we had no object on the canvas but syil have their bounds (we only drew textures)
     388         337 :                                         if (nb_obj_left_on_canvas)
     389         186 :                                                 nb_obj_left_on_canvas--;
     390             :                                 }
     391             :                         }
     392             :                         //immediate mode flush, erase all canvas (we just completely flusged it)
     393        1051 :                         if (tr_state->immediate_draw && had_flush && !tr_state->immediate_for_defer) {
     394           1 :                                 gf_evg_surface_clear(visual->raster_surface, NULL, 0);
     395             :                         }
     396             :                         //defer mode, erase all part of the canvas below us
     397        1050 :                         else if (txh) {
     398         300 :                                 visual_2d_draw_path_extended(visual, ctx->drawable->path, ctx, NULL, NULL, tr_state, NULL, NULL, GF_TRUE);
     399             :                         } else {
     400         750 :                                 gf_evg_surface_clear(visual->raster_surface, &ctx->bi->clip, 0);
     401             :                         }
     402             :                 }
     403        1087 :                 ctx->bi->clip = rc;
     404             :         }
     405        1078 :         if (line_texture) {
     406           0 :                 ctx->aspect.line_color = prev_color;
     407           0 :                 ctx->aspect.line_texture = txh;
     408             :         } else {
     409        1078 :                 ctx->aspect.fill_color = prev_color;
     410        1078 :                 ctx->aspect.fill_texture = txh;
     411             :         }
     412             : 
     413        1078 :         if (had_flush) {
     414         901 :                 visual->nb_objects_on_canvas_since_last_ogl_flush = nb_obj_left_on_canvas;
     415             :         }
     416             : }
     417             : 
     418         778 : void visual_2d_texture_path_opengl_auto(GF_VisualManager *visual, GF_Path *path, GF_TextureHandler *txh, struct _drawable_context *ctx, GF_Rect *orig_bounds, GF_Matrix2D *ext_mx, GF_TraverseState *tr_state)
     419             : {
     420             :         GF_Rect clipper;
     421             :         GF_Matrix mx, bck_mx;
     422         778 :         u32 prev_mode = tr_state->traversing_mode;
     423         778 :         u32 prev_type_3d = tr_state->visual->type_3d;
     424             : 
     425         778 :         visual_2d_flush_hybgl_canvas(visual, txh, ctx, tr_state);
     426             : 
     427         778 :         tr_state->visual->type_3d = 4;
     428         778 :         tr_state->appear = ctx->appear;
     429         778 :         if (ctx->col_mat) gf_cmx_copy(&tr_state->color_mat, ctx->col_mat);//
     430         778 :         gf_mx_copy(bck_mx, tr_state->model_matrix);
     431             : 
     432         778 :         tr_state->traversing_mode=TRAVERSE_DRAW_3D;
     433             :         //in hybridGL the 2D camera is always setup as centered-coords, we have to insert flip+translation in case of top-left origin 
     434         778 :         if (tr_state->visual->center_coords) {
     435         772 :                 gf_mx_from_mx2d(&tr_state->model_matrix, &ctx->transform);
     436             :         } else {
     437          12 :                 gf_mx_init(tr_state->model_matrix);
     438           6 :                 gf_mx_add_scale(&tr_state->model_matrix, FIX_ONE, -FIX_ONE, FIX_ONE);
     439           6 :                 gf_mx_add_translation(&tr_state->model_matrix, -tr_state->camera->width/2, -tr_state->camera->height/2, 0);
     440             : 
     441           6 :                 gf_mx_from_mx2d(&mx, &ctx->transform);
     442           6 :                 gf_mx_add_matrix(&tr_state->model_matrix, &mx);
     443             :         }
     444             : 
     445         778 :         clipper.x = INT2FIX(ctx->bi->clip.x);
     446         778 :         clipper.y = INT2FIX(ctx->bi->clip.y);
     447         778 :         clipper.width = INT2FIX(ctx->bi->clip.width);
     448         778 :         clipper.height = INT2FIX(ctx->bi->clip.height);
     449         778 :         visual_3d_set_clipper_2d(tr_state->visual, clipper, NULL);
     450             : 
     451         778 :         gf_node_allow_cyclic_traverse(ctx->drawable->node);
     452         778 :         gf_node_traverse(ctx->drawable->node, tr_state);
     453             : 
     454         778 :         tr_state->visual->type_3d=prev_type_3d;
     455         778 :         tr_state->traversing_mode=prev_mode;
     456         778 :         if (ctx->col_mat) gf_cmx_init(&tr_state->color_mat);
     457             : 
     458         778 :         ctx->flags |= CTX_PATH_FILLED;
     459             : 
     460         778 :         visual_3d_reset_clipper_2d(tr_state->visual);
     461             :         gf_mx_copy(tr_state->model_matrix, bck_mx);
     462         778 : }
     463             : #endif
     464             : 
     465             : 
     466       17692 : void visual_2d_texture_path_extended(GF_VisualManager *visual, GF_Path *path, GF_TextureHandler *txh, struct _drawable_context *ctx, GF_Rect *orig_bounds, GF_Matrix2D *ext_mx, GF_TraverseState *tr_state)
     467             : {
     468             :         Fixed sS, sT;
     469             :         u32 tx_tile;
     470             :         GF_EVGStencil * tx_raster;
     471             :         GF_Matrix2D mx_texture;
     472             :         GF_Rect orig_rc;
     473             : 
     474       30448 :         if (! visual->CheckAttached(visual) ) return;
     475             : 
     476       17692 :         if (!txh) txh = ctx->aspect.fill_texture;
     477       17692 :         if (!txh) return;
     478       17692 :         if (!txh->tx_io && !txh->data) {
     479         286 :                 gf_node_dirty_set(txh->owner, 0, 1);
     480             : 
     481         286 :                 txh->needs_refresh=1;
     482         286 :                 return;
     483             :         }
     484             : 
     485             : 
     486             :         /*this is gradient draw*/
     487       17406 :         if (txh->compute_gradient_matrix) {
     488       11692 :                 visual_2d_draw_gradient(visual, path, txh, ctx, tr_state, ext_mx, orig_bounds);
     489       11692 :                 return;
     490             :         }
     491             : 
     492             : 
     493             : #ifndef GPAC_DISABLE_3D
     494        5714 :         if (visual->compositor->hybrid_opengl) {
     495         778 :                 visual_2d_texture_path_opengl_auto(visual, path, txh, ctx, orig_bounds, ext_mx, tr_state);
     496         778 :                 return;
     497             :         }
     498             : #endif
     499             : 
     500        4936 :         if (txh->flags & GF_SR_TEXTURE_PRIVATE_MEDIA) {
     501             :                 GF_Window src, dst;
     502           0 :                 visual_2d_fill_path(visual, ctx, NULL, tr_state, 0);
     503             : 
     504             :                 /*if texture not ready, update the size before computing output rectangles */
     505           0 :                 if (!txh->width || !txh->height) {
     506           0 :                         gf_mo_get_visual_info(txh->stream, &txh->width, &txh->height, &txh->stride, &txh->pixel_ar, &txh->pixelformat, &txh->is_flipped);
     507             :                         /*in case the node is an MPEG-4 bitmap, force stack rebuild at next frame */
     508           0 :                         gf_node_dirty_set(ctx->drawable->node, GF_SG_NODE_DIRTY, 1);
     509             :                 }
     510             : 
     511           0 :                 compositor_texture_rectangles(visual, txh, &ctx->bi->clip, &ctx->bi->unclip, &src, &dst, NULL, NULL);
     512             :                 return;
     513             :         }
     514             : 
     515        4936 :         if (!gf_sc_texture_push_image(txh, 0, 1)) return;
     516        4936 :         tx_raster = gf_sc_texture_get_stencil(txh);
     517             : 
     518             :         /*setup quality even for background (since quality concerns images)*/
     519        4936 :         visual_2d_set_options(visual->compositor, visual->raster_surface, ctx->flags & CTX_IS_TEXT, ctx->flags & CTX_NO_ANTIALIAS);
     520             : 
     521             :         /*get original bounds*/
     522        4936 :         if (orig_bounds) {
     523           0 :                 orig_rc = *orig_bounds;
     524             :         } else {
     525        4936 :                 gf_path_get_bounds(path, &orig_rc);
     526             :         }
     527             : 
     528             :         /*get scaling ratio so that active texture view is stretched to original bounds (std 2D shape texture mapping in MPEG4)*/
     529        4936 :         sS = orig_rc.width / txh->width;
     530        4936 :         sT = orig_rc.height / txh->height;
     531             : 
     532        4936 :         gf_mx2d_init(mx_texture);
     533        4936 :         gf_mx2d_add_scale(&mx_texture, sS, sT);
     534             : 
     535             : #ifndef GPAC_DISABLE_VRML
     536             :         /*apply texture transform*/
     537        4936 :         if (ctx->flags & CTX_HAS_APPEARANCE) {
     538             :                 GF_Matrix2D tex_trans;
     539        4729 :                 visual_2d_get_texture_transform(ctx->appear, txh, &tex_trans, (txh == ctx->aspect.fill_texture) ? 0 : 1, txh->width * sS, txh->height * sT);
     540        4729 :                 gf_mx2d_add_matrix(&mx_texture, &tex_trans);
     541             :         }
     542             : #endif
     543             : 
     544             :         /*move to bottom-left corner of bounds */
     545        4936 :         gf_mx2d_add_translation(&mx_texture, (orig_rc.x), (orig_rc.y - orig_rc.height));
     546             : 
     547        4936 :         if (ext_mx) gf_mx2d_add_matrix(&mx_texture, ext_mx);
     548             : 
     549             :         /*move to final coordinate system (except background which is built directly in final coord system)*/
     550        4936 :         if (!(ctx->flags & CTX_IS_BACKGROUND) ) gf_mx2d_add_matrix(&mx_texture, &ctx->transform);
     551             : 
     552             :         /*set path transform*/
     553        4936 :         gf_evg_stencil_set_matrix(tx_raster, &mx_texture);
     554             : 
     555             : 
     556             :         tx_tile = 0;
     557        4936 :         if (txh->flags & GF_SR_TEXTURE_REPEAT_S) tx_tile |= GF_TEXTURE_REPEAT_S;
     558        4936 :         if (txh->flags & GF_SR_TEXTURE_REPEAT_T) tx_tile |= GF_TEXTURE_REPEAT_T;
     559        4936 :         if (ctx->flags & CTX_FLIPED_COORDS)
     560           0 :                 tx_tile |= GF_TEXTURE_FLIP_Y;
     561        4936 :         gf_evg_stencil_set_mapping(tx_raster, (GF_TextureMapFlags) tx_tile);
     562             : 
     563        4936 :         if (!(ctx->flags & CTX_IS_BACKGROUND) ) {
     564        4729 :                 u8 a = GF_COL_A(ctx->aspect.fill_color);
     565        4729 :                 if (!a) a = GF_COL_A(ctx->aspect.line_color);
     566             :                 /*texture alpha scale is the original material transparency, NOT the one after color transform*/
     567        4729 :                 gf_evg_stencil_set_alpha(tx_raster, a );
     568        4729 :                 gf_evg_stencil_set_color_matrix(tx_raster, ctx->col_mat);
     569             : 
     570        4729 :                 gf_evg_surface_set_matrix(visual->raster_surface, &ctx->transform);
     571             :         } else {
     572         207 :                 gf_evg_surface_set_matrix(visual->raster_surface, NULL);
     573             :         }
     574        4936 :         txh->flags |= GF_SR_TEXTURE_USED;
     575             : 
     576             :         /*push path & draw*/
     577        4936 :         gf_evg_surface_set_path(visual->raster_surface, path);
     578        4936 :         visual_2d_fill_path(visual, ctx, tx_raster, tr_state, 0);
     579        4936 :         gf_evg_surface_set_path(visual->raster_surface, NULL);
     580             : 
     581             : 
     582             : 
     583        4936 :         ctx->flags |= CTX_PATH_FILLED;
     584             : }
     585             : 
     586       73611 : void visual_2d_texture_path(GF_VisualManager *visual, GF_Path *path, struct _drawable_context *ctx, GF_TraverseState *tr_state)
     587             : {
     588             : #ifdef SKIP_DRAW
     589             :         return;
     590             : #endif
     591       73611 :         if (! visual->CheckAttached(visual) ) return;
     592             : 
     593       73611 :         if ((ctx->flags & CTX_PATH_FILLED) || !ctx->aspect.fill_texture || visual->compositor->is_hidden) return;
     594             : 
     595             :         /*this is ambiguous in the spec, what if the material is filled and the texture is transparent ?
     596             :         let's draw, it's nicer */
     597             : #if 0
     598             :         if (GF_COL_A(ctx->aspect.fill_color) && ctx->aspect.fill_texture->transparent) {
     599             :                 visual_2d_draw_path(visual, path, ctx, NULL, NULL);
     600             :                 ctx->flags &= ~CTX_PATH_FILLED;
     601             :         }
     602             : #endif
     603             : 
     604       10769 :         visual_2d_texture_path_extended(visual, path, NULL, ctx, NULL, NULL, tr_state);
     605             : }
     606             : 
     607             : #define ADAPTATION_SIZE         0
     608             : 
     609             : 
     610      669228 : void visual_2d_draw_path_extended(GF_VisualManager *visual, GF_Path *path, DrawableContext *ctx, GF_EVGStencil * brush, GF_EVGStencil * pen, GF_TraverseState *tr_state, GF_Rect *orig_bounds, GF_Matrix2D *ext_mx, Bool is_erase)
     611             : {
     612             :         Bool dofill, dostrike;
     613             : #ifdef SKIP_DRAW
     614             :         return;
     615             : #endif
     616      669228 :         if (! visual->CheckAttached(visual) ) return;
     617             : 
     618      669228 :         if ((ctx->flags & CTX_PATH_FILLED) && (ctx->flags & CTX_PATH_STROKE) ) {
     619           0 :                 if (visual->compositor->bvol) draw_clipper(visual, ctx);
     620             :                 return;
     621             :         }
     622             : 
     623      669228 :         if (! (ctx->flags & CTX_IS_BACKGROUND) )
     624      669228 :                 visual_2d_set_options(visual->compositor, visual->raster_surface, ctx->flags & CTX_IS_TEXT, ctx->flags & CTX_NO_ANTIALIAS);
     625             : 
     626             :         dofill = dostrike = 0;
     627      669228 :         if (!(ctx->flags & CTX_PATH_FILLED) && (is_erase || GF_COL_A(ctx->aspect.fill_color)) ) {
     628             :                 dofill = 1;
     629      634171 :                 if (!brush) {
     630      634171 :                         brush = visual->raster_brush;
     631      634171 :                         gf_evg_stencil_set_brush_color(brush, ctx->aspect.fill_color);
     632             :                 }
     633             :         }
     634             : 
     635             : 
     636             :         /*compute width based on transform and top_level transform*/
     637      669228 :         if (!(ctx->flags & CTX_PATH_STROKE) && ctx->aspect.pen_props.width) {
     638             :                 dostrike = 1;
     639      632246 :         } else if (!dofill) {
     640             :                 return;
     641             :         }
     642             : 
     643             :         /*set path transform, except for background2D node which is directly build in the final coord system*/
     644      663702 :         gf_evg_surface_set_matrix(visual->raster_surface, (ctx->flags & CTX_IS_BACKGROUND) ? NULL : &ctx->transform);
     645             : 
     646             :         /*fill path*/
     647      663702 :         if (dofill) {
     648             : #if ADAPTATION_SIZE
     649             :                 if ((ctx->bi->clip.width<ADAPTATION_SIZE) && (ctx->bi->clip.height<ADAPTATION_SIZE)) {
     650             :                         gf_evg_surface_clear(visual->raster_surface, &ctx->bi->clip, ctx->aspect.fill_color);
     651             :                 } else
     652             : #endif
     653             :                 {
     654             :                         /*push path*/
     655      634171 :                         gf_evg_surface_set_path(visual->raster_surface, path);
     656      634171 :                         visual_2d_fill_path(visual, ctx, brush, tr_state, is_erase);
     657      634171 :                         gf_evg_surface_set_path(visual->raster_surface, NULL);
     658             :                 }
     659             :         }
     660             : 
     661      663702 :         if (dostrike) {
     662             : #if ADAPTATION_SIZE
     663             :                 if ((ctx->bi->clip.width<ADAPTATION_SIZE) && (ctx->bi->clip.height<ADAPTATION_SIZE)) {
     664             :                 } else
     665             : #endif
     666             :                 {
     667             :                         StrikeInfo2D *si;
     668             : 
     669       36982 :                         if (!pen) {
     670       36982 :                                 pen = visual->raster_brush;
     671       36982 :                                 gf_evg_stencil_set_brush_color(pen, ctx->aspect.line_color);
     672             :                         }
     673             : 
     674       36982 :                         si = drawable_get_strikeinfo(visual->compositor, ctx->drawable, &ctx->aspect, ctx->appear, path, ctx->flags, NULL);
     675       36982 :                         if (si && si->outline) {
     676       36675 :                                 if (ctx->aspect.line_texture) {
     677        1789 :                                         visual_2d_texture_path_extended(visual, si->outline, ctx->aspect.line_texture, ctx, orig_bounds, ext_mx, tr_state);
     678             :                                 } else {
     679       34886 :                                         gf_evg_surface_set_path(visual->raster_surface, si->outline);
     680       34886 :                                         visual_2d_fill_path(visual, ctx, pen, tr_state, 0);
     681             :                                 }
     682             :                                 /*that's ugly, but we cannot cache path outline for IFS2D/ILS2D*/
     683       36675 :                                 if (path && !(ctx->flags & CTX_IS_TEXT) && (path!=ctx->drawable->path) ) {
     684           8 :                                         gf_path_del(si->outline);
     685           8 :                                         si->outline = NULL;
     686             :                                 }
     687             :                         }
     688             : //                      drawable_reset_path_outline(ctx->drawable);
     689             :                 }
     690             :         }
     691             : 
     692      663702 :         if (visual->compositor->bvol) draw_clipper(visual, ctx);
     693             : }
     694             : 
     695      663794 : void visual_2d_draw_path(GF_VisualManager *visual, GF_Path *path, DrawableContext *ctx, GF_EVGStencil * brush, GF_EVGStencil * pen, GF_TraverseState *tr_state)
     696             : {
     697      663794 :         visual_2d_draw_path_extended(visual, path, ctx, brush, pen, tr_state, NULL, NULL, GF_FALSE);
     698      663794 : }
     699             : 
     700        1332 : void visual_2d_fill_rect(GF_VisualManager *visual, DrawableContext *ctx, GF_Rect *_rc, u32 color, u32 strike_color, GF_TraverseState *tr_state)
     701             : {
     702             :         GF_Path *path;
     703             :         GF_Rect *rc;
     704             : #ifdef SKIP_DRAW
     705             :         return;
     706             : #endif
     707             : 
     708        1332 :         if (! visual->CheckAttached(visual) ) return;
     709             : 
     710        1332 :         if (!color && !strike_color) return;
     711             : 
     712           0 :         if ((ctx->flags & CTX_PATH_FILLED) && (ctx->flags & CTX_PATH_STROKE) ) {
     713           0 :                 if (visual->compositor->bvol) draw_clipper(visual, ctx);
     714             :                 return;
     715             :         }
     716             : 
     717             :         /*no aa*/
     718           0 :         visual_2d_set_options(visual->compositor, visual->raster_surface, 0, 1);
     719           0 :         if (_rc) {
     720             :                 rc = _rc;
     721           0 :                 gf_evg_surface_set_matrix(visual->raster_surface, &ctx->transform);
     722             :         }
     723             :         else {
     724           0 :                 rc = &ctx->bi->unclip;
     725           0 :                 gf_evg_surface_set_matrix(visual->raster_surface, NULL);
     726             :         }
     727             : 
     728           0 :         path = gf_path_new();
     729           0 :         gf_path_add_move_to(path, rc->x, rc->y-rc->height);
     730           0 :         gf_path_add_line_to(path, rc->x+rc->width, rc->y-rc->height);
     731           0 :         gf_path_add_line_to(path, rc->x+rc->width, rc->y);
     732           0 :         gf_path_add_line_to(path, rc->x, rc->y);
     733           0 :         gf_path_close(path);
     734             : 
     735             : 
     736           0 :         if (color) {
     737             :                 /*push path*/
     738           0 :                 gf_evg_surface_set_path(visual->raster_surface, path);
     739           0 :                 gf_evg_stencil_set_brush_color(visual->raster_brush, color);
     740           0 :                 visual_2d_fill_path(visual, ctx, visual->raster_brush, tr_state, 0);
     741           0 :                 gf_evg_surface_set_path(visual->raster_surface, NULL);
     742             :         }
     743           0 :         if (strike_color) {
     744             :                 GF_Path *outline;
     745             :                 GF_PenSettings pen;
     746             :                 memset(&pen, 0, sizeof(GF_PenSettings));
     747           0 :                 pen.width = 1;
     748           0 :                 pen.join = GF_LINE_JOIN_BEVEL;
     749           0 :                 pen.dash = GF_DASH_STYLE_DOT;
     750           0 :                 gf_evg_stencil_set_brush_color(visual->raster_brush, strike_color);
     751           0 :                 outline = gf_path_get_outline(path,  pen);
     752           0 :                 outline->flags &= ~GF_PATH_FILL_ZERO_NONZERO;
     753           0 :                 gf_evg_surface_set_path(visual->raster_surface, outline);
     754           0 :                 visual_2d_fill_path(visual, ctx, visual->raster_brush, tr_state, 0);
     755           0 :                 gf_evg_surface_set_path(visual->raster_surface, NULL);
     756           0 :                 gf_path_del(outline);
     757             :         }
     758             : 
     759           0 :         gf_path_del(path);
     760             : }
     761             : 
     762             : #if 0 //unused
     763             : void visual_2d_fill_irect(GF_VisualManager *visual, GF_IRect *rc, u32 fill, u32 strike)
     764             : {
     765             :         GF_Path *path;
     766             :         GF_Path *outline;
     767             :         GF_PenSettings pen;
     768             : #ifdef SKIP_DRAW
     769             :         return;
     770             : #endif
     771             : 
     772             :         if (!rc) return;
     773             : 
     774             :         if (! visual->CheckAttached(visual) ) return;
     775             : 
     776             :         if (!fill && !strike ) return;
     777             : 
     778             :         /*no aa*/
     779             :         visual_2d_set_options(visual->compositor, visual->raster_surface, 0, 1);
     780             :         gf_evg_surface_set_matrix(visual->raster_surface, NULL);
     781             : 
     782             :         gf_evg_surface_set_raster_level(visual->raster_surface, GF_RASTER_HIGH_SPEED);
     783             :         gf_evg_surface_set_matrix(visual->raster_surface, NULL);
     784             : 
     785             :         path = gf_path_new();
     786             :         gf_path_add_move_to(path, INT2FIX(rc->x-1), INT2FIX(rc->y+2-rc->height));
     787             :         gf_path_add_line_to(path, INT2FIX(rc->x+rc->width-2), INT2FIX(rc->y+2-rc->height));
     788             :         gf_path_add_line_to(path, INT2FIX(rc->x+rc->width), INT2FIX(rc->y));
     789             :         gf_path_add_line_to(path, INT2FIX(rc->x), INT2FIX(rc->y));
     790             :         gf_path_close(path);
     791             : 
     792             :         if (fill) {
     793             :                 gf_evg_surface_set_path(visual->raster_surface, path);
     794             :                 gf_evg_stencil_set_brush_color(visual->raster_brush, fill);
     795             : 
     796             :                 gf_evg_surface_set_clipper(visual->raster_surface, rc);
     797             :                 gf_evg_surface_fill(visual->raster_surface, visual->raster_brush);
     798             : 
     799             :                 gf_evg_surface_set_path(visual->raster_surface, NULL);
     800             :         }
     801             : 
     802             :         if (strike) {
     803             :                 memset(&pen, 0, sizeof(GF_PenSettings));
     804             :                 pen.width = 2;
     805             :                 pen.align = GF_PATH_LINE_INSIDE;
     806             :                 pen.join = GF_LINE_JOIN_BEVEL;
     807             :                 outline = gf_path_get_outline(path, pen);
     808             :                 outline->flags &= ~GF_PATH_FILL_ZERO_NONZERO;
     809             : 
     810             :                 gf_evg_surface_set_path(visual->raster_surface, outline);
     811             :                 gf_evg_stencil_set_brush_color(visual->raster_brush, strike);
     812             : 
     813             :                 gf_evg_surface_set_clipper(visual->raster_surface, rc);
     814             :                 gf_evg_surface_fill(visual->raster_surface, visual->raster_brush);
     815             : 
     816             :                 gf_evg_surface_set_path(visual->raster_surface, NULL);
     817             :                 gf_path_del(outline);
     818             :         }
     819             :         gf_path_del(path);
     820             : #ifndef GPAC_DISABLE_3D
     821             :         if (!visual->offscreen && visual->compositor->hybrid_opengl)
     822             :                 ra_union_rect(&visual->hybgl_drawn, rc);
     823             : #endif
     824             : }
     825             : #endif
     826             : 

Generated by: LCOV version 1.13