LCOV - code coverage report
Current view: top level - compositor - mpeg4_background2d.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 223 235 94.9 %
Date: 2021-04-29 23:48:07 Functions: 12 12 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             : 
      27             : #include "mpeg4_grouping.h"
      28             : #include "visual_manager.h"
      29             : #include "texturing.h"
      30             : #include "nodes_stacks.h"
      31             : 
      32             : #ifndef GPAC_DISABLE_VRML
      33             : 
      34             : 
      35             : #define B2D_PLANE_HSIZE         FLT2FIX(0.5025f)
      36             : 
      37             : typedef struct
      38             : {
      39             :         DrawableContext ctx;
      40             :         BoundInfo bi;
      41             : } BackgroundStatus;
      42             : 
      43         622 : static void DestroyBackground2D(GF_Node *node)
      44             : {
      45         622 :         Background2DStack *stack = (Background2DStack *) gf_node_get_private(node);
      46             : 
      47         622 :         PreDestroyBindable(node, stack->reg_stacks);
      48         622 :         gf_list_del(stack->reg_stacks);
      49             : 
      50        1819 :         while (gf_list_count(stack->status_stack)) {
      51         575 :                 BackgroundStatus *status = (BackgroundStatus *)gf_list_get(stack->status_stack, 0);
      52         575 :                 gf_list_rem(stack->status_stack, 0);
      53         575 :                 gf_free(status);
      54             :         }
      55         622 :         gf_list_del(stack->status_stack);
      56             : 
      57         622 :         drawable_del(stack->drawable);
      58         622 :         gf_sc_texture_destroy(&stack->txh);
      59             : #ifndef GPAC_DISABLE_3D
      60         622 :         if (stack->mesh) mesh_free(stack->mesh);
      61             : #endif
      62         622 :         gf_free(stack);
      63         622 : }
      64             : 
      65         575 : static void b2D_new_status(Background2DStack *bck, M_Background2D*back)
      66             : {
      67             :         BackgroundStatus *status;
      68             : 
      69         575 :         GF_SAFEALLOC(status, BackgroundStatus);
      70         575 :         if (!status) {
      71           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to allocate background2D status\n"));
      72             :                 return;
      73             :         }
      74        1150 :         gf_mx2d_init(status->ctx.transform);
      75         575 :         status->ctx.drawable = bck->drawable;
      76         575 :         status->ctx.flags = CTX_IS_BACKGROUND;
      77         575 :         status->ctx.bi = &status->bi;
      78         575 :         status->ctx.aspect.fill_color = GF_COL_ARGB_FIXED(FIX_ONE, back->backColor.red, back->backColor.green, back->backColor.blue);
      79         575 :         status->ctx.aspect.fill_texture = &bck->txh;
      80         575 :         gf_list_add(bck->status_stack, status);
      81             : }
      82             : 
      83       49655 : static BackgroundStatus *b2d_get_status(Background2DStack *stack, GF_List *background_stack)
      84             : {
      85             :         u32 i, count;
      86       49655 :         if (!background_stack) return NULL;
      87             : 
      88       49655 :         count = gf_list_count(stack->reg_stacks);
      89           0 :         for (i=0; i<count; i++) {
      90       49655 :                 GF_List *bind_stack = (GF_List *)gf_list_get(stack->reg_stacks, i);
      91       49655 :                 if (bind_stack == background_stack) {
      92       49655 :                         return gf_list_get(stack->status_stack, i);
      93             :                 }
      94             :         }
      95             :         return NULL;
      96             : }
      97             : 
      98             : 
      99             : static Bool back_use_texture(M_Background2D *bck)
     100             : {
     101       50198 :         if (!bck->url.count) return 0;
     102        5796 :         if (bck->url.vals[0].OD_ID > 0) return 1;
     103        2351 :         if (bck->url.vals[0].url && strlen(bck->url.vals[0].url)) return 1;
     104             :         return 0;
     105             : }
     106             : 
     107       14166 : static void DrawBackground2D_2D(DrawableContext *ctx, GF_TraverseState *tr_state)
     108             : {
     109             :         Bool clear_all = GF_TRUE;
     110             :         u32 color;
     111             :         Bool use_texture;
     112             :         Bool is_offscreen = GF_FALSE;
     113             :         Background2DStack *stack;
     114       14166 :         if (!ctx || !ctx->drawable || !ctx->drawable->node) return;
     115       14166 :         stack = (Background2DStack *) gf_node_get_private(ctx->drawable->node);
     116             : 
     117       14166 :         if (!ctx->bi->clip.width || !ctx->bi->clip.height) return;
     118             : 
     119       14166 :         stack->flags &= ~CTX_PATH_FILLED;
     120       14166 :         color = ctx->aspect.fill_color;
     121             : 
     122       14166 :         use_texture = back_use_texture((M_Background2D *)ctx->drawable->node);
     123       12750 :         if (!use_texture && !tr_state->visual->is_attached) {
     124             :                 use_texture = 1;
     125       11891 :                 stack->txh.data = stack->col_tx;
     126       11891 :                 stack->txh.width = 2;
     127       11891 :                 stack->txh.height = 2;
     128       11891 :                 stack->txh.stride = 6;
     129       11891 :                 stack->txh.pixelformat = GF_PIXEL_RGB;
     130             :         }
     131             : 
     132        2275 :         if (use_texture) {
     133             : 
     134       13307 :                 if (!tr_state->visual->DrawBitmap(tr_state->visual, tr_state, ctx)) {
     135             :                         /*set target rect*/
     136         207 :                         gf_path_reset(stack->drawable->path);
     137         621 :                         gf_path_add_rect_center(stack->drawable->path,
     138         207 :                                                 ctx->bi->unclip.x + ctx->bi->unclip.width/2,
     139         207 :                                                 ctx->bi->unclip.y - ctx->bi->unclip.height/2,
     140         207 :                                                 ctx->bi->unclip.width, ctx->bi->unclip.height);
     141             : 
     142             :                         /*draw texture*/
     143         207 :                         visual_2d_texture_path(tr_state->visual, stack->drawable->path, ctx, tr_state);
     144             :                 }
     145             :                 //a quick hack, if texture not ready return (we don't have direct notification of this through the above functions
     146             : #ifndef GPAC_DISABLE_3D
     147       13307 :                 if (tr_state->visual->compositor->hybrid_opengl && !stack->txh.tx_io)
     148             :                         return;
     149             : #endif
     150             : 
     151       13285 :                 stack->flags &= ~(CTX_APP_DIRTY | CTX_TEXTURE_DIRTY);
     152       13285 :                 tr_state->visual->has_modif = 1;
     153             : #ifndef GPAC_DISABLE_3D
     154             :                 //in opengl auto mode we still have to clear the canvas
     155       13285 :                 if (!tr_state->immediate_draw && !tr_state->visual->offscreen && tr_state->visual->compositor->hybrid_opengl) {
     156             :                         clear_all = GF_FALSE;
     157             :                         is_offscreen = GF_TRUE;
     158         442 :                         color &= 0x00FFFFFF;
     159             :                 } else
     160             : #endif
     161             :                         return;
     162             :         }
     163             : 
     164             : 
     165             : #ifndef GPAC_DISABLE_3D
     166        1301 :         if (ctx->flags & CTX_BACKROUND_NOT_LAYER) {
     167        1055 :                 if (clear_all && !tr_state->visual->offscreen && tr_state->visual->compositor->hybrid_opengl) {
     168         151 :                         compositor_2d_hybgl_clear_surface(tr_state->visual, NULL, color, GF_FALSE);
     169             :                         is_offscreen = GF_TRUE;
     170         151 :                         color &= 0x00FFFFFF;
     171             :                         //we may need to clear the canvas for immediate mode
     172             :                 }
     173             :         } else {
     174             :                 is_offscreen = GF_TRUE;
     175             :         }
     176        1301 :         if (ctx->flags & CTX_BACKROUND_NO_CLEAR) {
     177           0 :                 stack->flags &= ~(CTX_APP_DIRTY | CTX_TEXTURE_DIRTY);
     178           0 :                 tr_state->visual->has_modif = 1;
     179           0 :                 return;
     180             :         }
     181             : #endif
     182             : 
     183             :         /*direct drawing, draw without clippers */
     184        1301 :         if (tr_state->immediate_draw
     185             :            ) {
     186             :                 /*directly clear with specified color*/
     187          11 :                 if (clear_all)
     188          11 :                         tr_state->visual->ClearSurface(tr_state->visual, &ctx->bi->clip, color, is_offscreen);
     189             :         } else {
     190             :                 u32 i;
     191             :                 GF_IRect clip;
     192        1289 :                 for (i=0; i<tr_state->visual->to_redraw.count; i++) {
     193             :                         /*there's an opaque region above, don't draw*/
     194             : #ifdef TRACK_OPAQUE_REGIONS
     195             :                         if (tr_state->visual->draw_node_index < tr_state->visual->to_redraw.list[i].opaque_node_index) continue;
     196             : #endif
     197        1289 :                         clip = ctx->bi->clip;
     198        1289 :                         gf_irect_intersect(&clip, &tr_state->visual->to_redraw.list[i].rect);
     199        1289 :                         if (clip.width && clip.height) {
     200        1289 :                                 tr_state->visual->ClearSurface(tr_state->visual, &clip, color, is_offscreen ? 2 : 0);
     201             :                         }
     202             :                 }
     203             :         }
     204        1301 :         stack->flags &= ~(CTX_APP_DIRTY | CTX_TEXTURE_DIRTY);
     205        1301 :         tr_state->visual->has_modif = 1;
     206             : }
     207             : 
     208             : #ifndef GPAC_DISABLE_3D
     209        4665 : static Bool back_texture_enabled(M_Background2D *bck, GF_TextureHandler *txh)
     210             : {
     211        4665 :         Bool use_texture = back_use_texture(bck);
     212             :         if (use_texture) {
     213             :                 /*texture not ready*/
     214         972 :                 if (!txh->tx_io) {
     215             :                         use_texture = 0;
     216         112 :                         gf_sc_invalidate(txh->compositor, NULL);
     217             :                 }
     218         972 :                 gf_sc_texture_set_blend_mode(txh, gf_sc_texture_is_transparent(txh) ? TX_REPLACE : TX_DECAL);
     219             :         }
     220        4665 :         return use_texture;
     221             : }
     222             : 
     223        4665 : static void DrawBackground2D_3D(M_Background2D *bck, Background2DStack *st, GF_TraverseState *tr_state)
     224             : {
     225             :         GF_Matrix mx, bck_mx, bck_mx_cam;
     226             :         Bool use_texture;
     227             : 
     228        4665 :         use_texture = back_texture_enabled(bck, &st->txh);
     229             : 
     230        4665 :         visual_3d_set_background_state(tr_state->visual, 1);
     231             : 
     232        4665 :         gf_mx_copy(bck_mx_cam, tr_state->camera->modelview);
     233        4665 :         gf_mx_copy(bck_mx, tr_state->model_matrix);
     234             : 
     235             :         /*little opt: if we clear the main visual clear it entirely */
     236        4665 :         if (! tr_state->is_layer) {
     237        3572 :                 visual_3d_clear(tr_state->visual, bck->backColor, FIX_ONE);
     238        3572 :                 if (!use_texture) {
     239        3144 :                         visual_3d_set_background_state(tr_state->visual, 0);
     240        3144 :                         return;
     241             :                 }
     242             :                 /*we need a hack here because main vp is always traversed before main background, and in the case of a
     243             :                 2D viewport it modifies the modelview matrix, which we don't want ...*/
     244         856 :                 gf_mx_init(tr_state->model_matrix);
     245         856 :                 gf_mx_init(tr_state->camera->modelview);
     246             :         }
     247        1521 :         if (!use_texture || (!tr_state->is_layer && st->txh.transparent) ) visual_3d_set_material_2d(tr_state->visual, bck->backColor, FIX_ONE);
     248        1521 :         if (use_texture) {
     249         860 :                 visual_3d_set_state(tr_state->visual, V3D_STATE_COLOR, ! tr_state->is_layer);
     250         860 :                 tr_state->mesh_num_textures = gf_sc_texture_enable(&st->txh, NULL);
     251         860 :                 if (!tr_state->mesh_num_textures) visual_3d_set_material_2d(tr_state->visual, bck->backColor, FIX_ONE);
     252             :         }
     253             : 
     254             :         /*create mesh object if needed*/
     255        1521 :         if (!st->mesh) {
     256          19 :                 st->mesh = new_mesh();
     257          19 :                 mesh_set_vertex(st->mesh, -B2D_PLANE_HSIZE, -B2D_PLANE_HSIZE, 0,  0,  0,  FIX_ONE, 0, 0);
     258          19 :                 mesh_set_vertex(st->mesh,  B2D_PLANE_HSIZE, -B2D_PLANE_HSIZE, 0,  0,  0,  FIX_ONE, FIX_ONE, 0);
     259          19 :                 mesh_set_vertex(st->mesh,  B2D_PLANE_HSIZE,  B2D_PLANE_HSIZE, 0,  0,  0,  FIX_ONE, FIX_ONE, FIX_ONE);
     260          19 :                 mesh_set_vertex(st->mesh, -B2D_PLANE_HSIZE,  B2D_PLANE_HSIZE, 0,  0,  0,  FIX_ONE, 0, FIX_ONE);
     261          19 :                 mesh_set_triangle(st->mesh, 0, 1, 2);
     262          19 :                 mesh_set_triangle(st->mesh, 0, 2, 3);
     263          19 :                 st->mesh->flags |= MESH_IS_2D;
     264             :         }
     265             : 
     266        1521 :         gf_mx_init(mx);
     267        1521 :         if (tr_state->camera->is_3D) {
     268             :                 Fixed sx, sy;
     269             :                 /*reset matrix*/
     270        1542 :                 gf_mx_init(tr_state->model_matrix);
     271         771 :                 sx = sy = 2 * gf_mulfix(gf_tan(tr_state->camera->fieldOfView/2), tr_state->camera->z_far);
     272         771 :                 if (tr_state->camera->width > tr_state->camera->height) {
     273         454 :                         sx = gf_muldiv(sx, tr_state->camera->width, tr_state->camera->height);
     274             :                 } else {
     275         317 :                         sy = gf_muldiv(sy, tr_state->camera->height, tr_state->camera->width);
     276             :                 }
     277         771 :                 gf_mx_add_scale(&mx, sx, sy, FIX_ONE);
     278             : #ifdef GPAC_FIXED_POINT
     279             :                 gf_mx_add_translation(&mx, 0, 0, - (tr_state->camera->z_far/100)*99);
     280             : #else
     281         771 :                 gf_mx_add_translation(&mx, 0, 0, -0.995f*tr_state->camera->z_far);
     282             : #endif
     283             :         } else {
     284         750 :                 gf_mx_add_scale(&mx, tr_state->bbox.max_edge.x - tr_state->bbox.min_edge.x,
     285         750 :                                 tr_state->bbox.max_edge.y - tr_state->bbox.min_edge.y,
     286             :                                 FIX_ONE);
     287             :                 /*when in layer2D, DON'T MOVE BACKGROUND TO ZFAR*/
     288         750 :                 if (!tr_state->is_layer) {
     289             :                         Fixed tr;
     290             : #ifdef GPAC_FIXED_POINT
     291             :                         tr = -(tr_state->camera->z_far/100)*99;
     292             : #else
     293         279 :                         tr = -0.999f*tr_state->camera->z_far;
     294             : #endif
     295         279 :                         if (!tr_state->camera->is_3D) tr = -tr;
     296         279 :                         gf_mx_add_translation(&mx, 0, 0, tr);
     297             :                 }
     298             :         }
     299        1521 :         gf_mx_add_matrix(&tr_state->model_matrix, &mx);
     300        1521 :         visual_3d_mesh_paint(tr_state, st->mesh);
     301        1521 :         if (tr_state->mesh_num_textures) {
     302         860 :                 gf_sc_texture_disable(&st->txh);
     303         860 :                 tr_state->mesh_num_textures = 0;
     304             :         }
     305             : 
     306             :         gf_mx_copy(tr_state->model_matrix, bck_mx);
     307        1521 :         gf_mx_copy(tr_state->camera->modelview, bck_mx_cam);
     308             : 
     309        1521 :         visual_3d_set_background_state(tr_state->visual, 0);
     310             : }
     311             : #endif
     312             : 
     313       53074 : static void TraverseBackground2D(GF_Node *node, void *rs, Bool is_destroy)
     314             : {
     315             :         u32 col;
     316             :         BackgroundStatus *status;
     317             :         M_Background2D *bck;
     318       53074 :         Background2DStack *stack = (Background2DStack *) gf_node_get_private(node);
     319             :         GF_TraverseState *tr_state = (GF_TraverseState *)rs;
     320             : 
     321       53074 :         if (is_destroy) {
     322         622 :                 DestroyBackground2D(node);
     323         622 :                 return;
     324             :         }
     325       52452 :         if (tr_state->visual->compositor->noback)
     326             :                 return;
     327             : 
     328             :         bck = (M_Background2D *)node;
     329             : 
     330             :         /*special case for background in Layer2D: the background is seen as a regular drawable, so
     331             :         RENDER_BINDABLE is not used*/
     332       52407 :         switch (tr_state->traversing_mode) {
     333       14070 :         case TRAVERSE_DRAW_2D:
     334       14070 :                 DrawBackground2D_2D(tr_state->ctx, tr_state);
     335       14070 :                 return;
     336             :         case  TRAVERSE_PICK:
     337             :         case TRAVERSE_GET_BOUNDS:
     338             :                 return;
     339             :         }
     340             : 
     341             :         /*first traverse, bound if needed*/
     342       32163 :         if (gf_list_find(tr_state->backgrounds, node) < 0) {
     343             :                 M_Background2D *top_bck;
     344             : 
     345         575 :                 gf_list_add(tr_state->backgrounds, node);
     346             :                 assert(gf_list_find(stack->reg_stacks, tr_state->backgrounds)==-1);
     347         575 :                 gf_list_add(stack->reg_stacks, tr_state->backgrounds);
     348         575 :                 b2D_new_status(stack, bck);
     349             : 
     350             :                 /*only bound if we're on top*/
     351         575 :                 top_bck = gf_list_get(tr_state->backgrounds, 0);
     352         575 :                 if (!bck->isBound) {
     353         575 :                         if (top_bck== bck) {
     354         543 :                                 Bindable_SetIsBound(node, 1);
     355          32 :                         } else if (!top_bck->isBound) {
     356           0 :                                 bck->set_bind = 1;
     357           0 :                                 bck->on_set_bind(node, NULL);
     358             :                         }
     359             :                 }
     360             :                 /*open the stream if any*/
     361         640 :                 if (back_use_texture(bck) && !stack->txh.is_open) gf_sc_texture_play(&stack->txh, &bck->url);
     362             :                 /*in any case don't draw the first time (since the background could have been declared last)*/
     363         575 :                 gf_sc_invalidate(stack->txh.compositor, NULL);
     364         575 :                 return;
     365             :         }
     366       31588 :         if (!bck->isBound) return;
     367             : 
     368       30792 :         status = b2d_get_status(stack, tr_state->backgrounds);
     369       30792 :         if (!status) return;
     370             : 
     371       30792 :         if (gf_node_dirty_get(node)) {
     372             :                 u32 i;
     373             : 
     374         869 :                 stack->flags |= CTX_APP_DIRTY;
     375         869 :                 gf_node_dirty_clear(node, 0);
     376             : 
     377             : 
     378         869 :                 col = GF_COL_ARGB_FIXED(FIX_ONE, bck->backColor.red, bck->backColor.green, bck->backColor.blue);
     379         869 :                 if (col != status->ctx.aspect.fill_color) {
     380         277 :                         status->ctx.aspect.fill_color = col;
     381         277 :                         stack->flags |= CTX_APP_DIRTY;
     382             :                 }
     383        3476 :                 for (i=0; i<4; i++) {
     384        3476 :                         stack->col_tx[3*i] = FIX2INT(255 * bck->backColor.red);
     385        3476 :                         stack->col_tx[3*i+1] = FIX2INT(255 * bck->backColor.green);
     386        3476 :                         stack->col_tx[3*i+2] = FIX2INT(255 * bck->backColor.blue);
     387             :                 }
     388             :         }
     389             : 
     390       30792 :         if (back_use_texture(bck) ) {
     391             : #ifndef GPAC_DISABLE_3D
     392        3343 :                 if (stack->txh.compositor->hybrid_opengl && !tr_state->visual->offscreen && stack->hybgl_init) {
     393        1010 :                         stack->flags |= CTX_HYBOGL_NO_CLEAR;
     394             :                 }
     395        3343 :                 stack->hybgl_init = 1;
     396             : #endif
     397        3343 :                 if (stack->txh.tx_io && !(status->ctx.flags & CTX_APP_DIRTY) && stack->txh.needs_refresh) {
     398         368 :                         stack->flags |= CTX_TEXTURE_DIRTY;
     399             :                 }
     400             :         }
     401       30792 :         if (status->ctx.flags & CTX_BACKROUND_NOT_LAYER) {
     402          96 :                 status->ctx.flags = stack->flags | CTX_BACKROUND_NOT_LAYER;
     403             :         } else {
     404       30696 :                 status->ctx.flags = stack->flags;
     405       30696 :                 if (tr_state->is_layer)
     406        2653 :                         status->ctx.flags &= ~CTX_BACKROUND_NOT_LAYER;
     407             :         }
     408             : 
     409             : 
     410       30792 :         if (tr_state->traversing_mode != TRAVERSE_BINDABLE) return;
     411             : 
     412             :         /*3D mode*/
     413             : #ifndef GPAC_DISABLE_3D
     414        4761 :         if (tr_state->visual->type_3d) {
     415        4665 :                 DrawBackground2D_3D(bck, stack, tr_state);
     416             :         } else
     417             : #endif
     418          96 :                 DrawBackground2D_2D(&status->ctx, tr_state);
     419             : }
     420             : 
     421             : 
     422          52 : static void b2D_set_bind(GF_Node *node, GF_Route *route)
     423             : {
     424          52 :         Background2DStack *stack = (Background2DStack *)gf_node_get_private(node);
     425          52 :         Bindable_OnSetBind(node, stack->reg_stacks, NULL);
     426             : 
     427          52 :         if (stack->drawable->flags & DRAWABLE_IS_OVERLAY) {
     428           0 :                 stack->txh.compositor->video_out->Blit(stack->txh.compositor->video_out, NULL, NULL, NULL, 1);
     429             :         }
     430          52 :         stack->flags |= CTX_APP_DIRTY;
     431             : 
     432          52 : }
     433             : 
     434       18863 : DrawableContext *b2d_get_context(M_Background2D *node, GF_List *from_stack)
     435             : {
     436       18863 :         Background2DStack *stack = (Background2DStack *)gf_node_get_private((GF_Node *)node);
     437       18863 :         BackgroundStatus *status = b2d_get_status(stack, from_stack);
     438       18863 :         if (status) {
     439       18863 :                 status->ctx.bi = &status->bi;
     440       18863 :                 return &status->ctx;
     441             :         }
     442             :         return NULL;
     443             : }
     444             : 
     445             : 
     446             : 
     447       41079 : static void UpdateBackgroundTexture(GF_TextureHandler *txh)
     448             : {
     449       41079 :         gf_sc_texture_update_frame(txh, 0);
     450             : 
     451       41079 :         if (!txh->compositor->player && !txh->compositor->passthrough_txh && txh->stream && txh->stream->odm && (txh->stream->odm->flags & GF_ODM_PASSTHROUGH)) {
     452         290 :                 if (!txh->width || ((txh->width==txh->compositor->display_width) && (txh->height==txh->compositor->display_height)))
     453         290 :                         txh->compositor->passthrough_txh = txh;
     454             :                 else
     455           0 :                         txh->compositor->passthrough_txh = NULL;
     456             :         }
     457             : 
     458             :         /*restart texture if needed (movie background controled by MediaControl)*/
     459       41079 :         if (txh->stream_finished && gf_mo_get_loop(txh->stream, 0))
     460           0 :                 gf_sc_texture_restart(txh);
     461       41079 : }
     462             : 
     463         622 : void compositor_init_background2d(GF_Compositor *compositor, GF_Node *node)
     464             : {
     465             :         Background2DStack *ptr;
     466         622 :         GF_SAFEALLOC(ptr, Background2DStack);
     467         622 :         if (!ptr) {
     468           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to allocate background2D stack\n"));
     469             :                 return;
     470             :         }
     471             : 
     472         622 :         ptr->status_stack = gf_list_new();
     473         622 :         ptr->reg_stacks = gf_list_new();
     474             :         /*setup drawable object for background*/
     475         622 :         ptr->drawable = drawable_stack_new(compositor, node);
     476         622 :         ptr->drawable->flags = DRAWABLE_USE_TRAVERSE_DRAW;
     477         622 :         ((M_Background2D *)node)->on_set_bind = b2D_set_bind;
     478             : 
     479             : 
     480         622 :         gf_sc_texture_setup(&ptr->txh, compositor, node);
     481         622 :         ptr->txh.update_texture_fcnt = UpdateBackgroundTexture;
     482         622 :         ptr->txh.flags = GF_SR_TEXTURE_REPEAT_S | GF_SR_TEXTURE_REPEAT_T;
     483         622 :         ptr->flags = CTX_IS_BACKGROUND;
     484             : 
     485         622 :         gf_node_set_private(node, ptr);
     486         622 :         gf_node_set_callback_function(node, TraverseBackground2D);
     487             : }
     488             : 
     489         319 : void compositor_background2d_modified(GF_Node *node)
     490             : {
     491             :         M_Background2D *bck = (M_Background2D *)node;
     492         319 :         Background2DStack *st = (Background2DStack *) gf_node_get_private(node);
     493         319 :         if (!st) return;
     494             : 
     495             :         /*dirty node and parents in order to trigger parent visual redraw*/
     496         319 :         gf_node_dirty_set(node, 0, 1);
     497             : 
     498             :         /*if open and changed, stop and play*/
     499         319 :         if (st->txh.is_open) {
     500           9 :                 if (! gf_sc_texture_check_url_change(&st->txh, &bck->url)) return;
     501           1 :                 gf_sc_texture_stop(&st->txh);
     502           1 :                 gf_sc_texture_play(&st->txh, &bck->url);
     503           1 :                 return;
     504             :         }
     505             :         /*if not open and changed play*/
     506         310 :         if (bck->url.count)
     507           0 :                 gf_sc_texture_play(&st->txh, &bck->url);
     508         310 :         gf_sc_invalidate(st->txh.compositor, NULL);
     509             : }
     510             : 
     511             : #if 0 //unused
     512             : Bool compositor_background_transparent(GF_Node *node)
     513             : {
     514             :         if (node && (gf_node_get_tag(node) == TAG_MPEG4_Background2D)) {
     515             :                 Background2DStack *st;
     516             :                 if (!((M_Background2D *)node)->isBound) return 1;
     517             : 
     518             :                 st = (Background2DStack *) gf_node_get_private(node);
     519             :                 if (st->txh.transparent) return 1;
     520             :                 return 0;
     521             :         }
     522             :         /*consider all other background nodes transparent*/
     523             :         return 1;
     524             : }
     525             : #endif
     526             : 
     527             : 
     528             : #endif /*GPAC_DISABLE_VRML*/

Generated by: LCOV version 1.13