static void RenderOrderedGroup(GF_Node *node, void *rs, Bool is_destroy) { u32 i, count; GF_Node *child; Bool split_text_backup, invalidate_backup; M_OrderedGroup *og; u32 count2; GF_List *sensor_backup; SensorHandler *hsens; OrderedGroupStack *ogs = (OrderedGroupStack *) gf_node_get_private(node); RenderEffect2D *eff = (RenderEffect2D *)rs; if (is_destroy) { DeleteGroupingNode2D((GroupingNode2D *)ogs); if (ogs->priorities) free(ogs->priorities); free(ogs); return; } og = (M_OrderedGroup *) ogs->owner; if (!og->order.count) { group2d_traverse((GroupingNode2D*)ogs, og->children, eff); return; } count = gf_node_list_get_count(og->children); invalidate_backup = eff->invalidate_all; /*check whether the OrderedGroup node has changed*/ if (gf_node_dirty_get(node) & GF_SG_NODE_DIRTY) { if (ogs->priorities) free(ogs->priorities); ogs->priorities = (struct og_pos*)malloc(sizeof(struct og_pos)*count); for (i=0; i<count; i++) { ogs->priorities[i].position = i; ogs->priorities[i].priority = (i<og->order.count) ? og->order.vals[i] : 0; } qsort(ogs->priorities, count, sizeof(struct og_pos), compare_priority); eff->invalidate_all = 1; } sensor_backup = NULL; if (gf_node_dirty_get(node) & GF_SG_CHILD_DIRTY) { /*rebuild sensor list*/ if (gf_list_count(ogs->sensors)) { gf_list_del(ogs->sensors); ogs->sensors = gf_list_new(); } for (i=0; i<count; i++) { child = (GF_Node*)gf_node_list_get_child(og->children, ogs->priorities[i].position); if (!child || !is_sensor_node(child) ) continue; hsens = get_sensor_handler(child); if (hsens) gf_list_add(ogs->sensors, hsens); } } /*if we have an active sensor at this level discard all sensors in current render context (cf VRML)*/ count2 = gf_list_count(ogs->sensors); if (count2) { sensor_backup = eff->sensors; eff->sensors = gf_list_new(); /*add sensor to effects*/ for (i=0; i <count2; i++) { SensorHandler *hsens = (SensorHandler *)gf_list_get(ogs->sensors, i); effect_add_sensor(eff, hsens, &eff->transform); } } gf_node_dirty_clear(node, 0); if (eff->parent == (GroupingNode2D *) ogs) { for (i=0; i<count; i++) { group2d_start_child((GroupingNode2D *) ogs); child = (GF_Node*)gf_node_list_get_child(og->children, ogs->priorities[i].position); gf_node_render(child, eff); group2d_end_child((GroupingNode2D *) ogs); } } else { split_text_backup = eff->text_split_mode; if (count>1) eff->text_split_mode = 0; for (i=0; i<count; i++) { child = (GF_Node*)gf_node_list_get_child(og->children, ogs->priorities[i].position); gf_node_render(child, eff); } eff->text_split_mode = split_text_backup; } /*restore effect*/ invalidate_backup = eff->invalidate_all; if (count2) { /*destroy current effect list and restore previous*/ effect_reset_sensors(eff); gf_list_del(eff->sensors); eff->sensors = sensor_backup; } }
static void UpdateComposite2D(GF_TextureHandler *txh) { GF_Err e; u32 i; SensorHandler *hsens; RenderEffect2D *eff; M_CompositeTexture2D *ct2D = (M_CompositeTexture2D *)txh->owner; Composite2DStack *st = (Composite2DStack *) gf_node_get_private(txh->owner); GF_Raster2D *r2d = st->surf->render->compositor->r2d; if (!gf_node_dirty_get(txh->owner)) { txh->needs_refresh = 0; return; } /*rebuild stencil*/ if (!st->surf->the_surface || !txh->hwtx || ((s32) st->width != ct2D->pixelWidth) || ( (s32) st->height != ct2D->pixelHeight) ) { if (txh->hwtx) r2d->stencil_delete(txh->hwtx); txh->hwtx = NULL; if (ct2D->pixelWidth<=0) return; if (ct2D->pixelHeight<=0) return; st->width = ct2D->pixelWidth; st->height = ct2D->pixelHeight; txh->hwtx = r2d->stencil_new(r2d, GF_STENCIL_TEXTURE); e = r2d->stencil_create_texture(txh->hwtx, st->width, st->height, GF_PIXEL_ARGB); if (e) { if (txh->hwtx) r2d->stencil_delete(txh->hwtx); txh->hwtx = NULL; } } if (!txh->hwtx) return; GF_SAFEALLOC(eff, RenderEffect2D); eff->sensors = gf_list_new(); eff->surface = st->surf; if (st->surf->render->top_effect->trav_flags & TF_RENDER_DIRECT) { eff->trav_flags = TF_RENDER_DIRECT; } gf_mx2d_init(eff->transform); gf_cmx_init(&eff->color_mat); st->surf->width = st->width; st->surf->height = st->height; eff->back_stack = st->surf->back_stack; eff->view_stack = st->surf->view_stack; eff->is_pixel_metrics = gf_sg_use_pixel_metrics(gf_node_get_graph(st->txh.owner)); eff->min_hsize = INT2FIX( MIN(st->width, st->height) ) / 2; Composite_CheckBindables(st->txh.owner, eff, st->first); st->first = 0; GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render 2D] Entering CompositeTexture2D Render Cycle\n")); e = VS2D_InitDraw(st->surf, eff); if (e) { effect_delete(eff); return; } /*render children*/ if (gf_node_dirty_get(st->txh.owner) & GF_SG_NODE_DIRTY) { GF_ChildNodeItem *l = ct2D->children; /*rebuild sensor list */ if (gf_list_count(st->sensors)) { gf_list_del(st->sensors); st->sensors = gf_list_new(); } while (l) { if (l->node && is_sensor_node(l->node) ) { hsens = get_sensor_handler(l->node); if (hsens) gf_list_add(st->sensors, hsens); } l = l->next; } /*if we have an active sensor at this level discard all sensors in current render context (cf VRML)*/ if (gf_list_count(st->sensors)) { effect_reset_sensors(eff); } } /*add sensor to effects*/ i=0; while ((hsens = (SensorHandler*)gf_list_enum(st->sensors, &i))) { effect_add_sensor(eff, hsens, &eff->transform); } gf_node_dirty_clear(st->txh.owner, 0); /*render*/ gf_node_render_children(st->txh.owner, eff); /*finalize draw*/ txh->needs_refresh = VS2D_TerminateDraw(st->surf, eff); st->txh.transparent = st->surf->last_had_back ? 0 : 1; /* st->txh.active_window.x = 0; st->txh.active_window.y = 0; st->txh.active_window.width = st->width; st->txh.active_window.height = st->height; */ st->txh.width = st->width; st->txh.height = st->height; /*set active viewport in image coordinates top-left=(0, 0), not in BIFS*/ if (gf_list_count(st->surf->view_stack)) { M_Viewport *vp = (M_Viewport *)gf_list_get(st->surf->view_stack, 0); if (vp->isBound) { SFVec2f size = vp->size; if (size.x >=0 && size.y>=0) { /* st->txh.active_window.width = size.x; st->txh.active_window.height = size.y; st->txh.active_window.x = (st->width - size.x) / 2; st->txh.active_window.y = (st->height - size.y) / 2; */ /*FIXME - we need tracking of VP changes*/ txh->needs_refresh = 1; } } } if (txh->needs_refresh) { if (r2d->stencil_texture_modified) r2d->stencil_texture_modified(st->txh.hwtx); gf_sr_invalidate(st->txh.compositor, NULL); } effect_delete(eff); GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render 2D] Leaving CompositeTexture2D Render Cycle\n")); }