Пример #1
0
Bool group_2d_cache_traverse(GF_Node *node, GroupingNode2D *group, GF_TraverseState *tr_state)
{
	Bool is_dirty = gf_node_dirty_get(node) & GF_SG_CHILD_DIRTY;
	Bool zoom_changed = tr_state->visual->compositor->zoom_changed;
	Bool needs_recompute = 0;

	/*we are currently in a group cache, regular traversing*/
	if (tr_state->in_group_cache) return 0;

	/*draw mode*/
	if (tr_state->traversing_mode == TRAVERSE_DRAW_2D) {
		/*shall never happen*/
		assert(group->cache);
		/*draw it*/
		group_cache_draw(group->cache, tr_state);
		return 1;
	}
	/*other modes than sorting, use regular traversing*/
	if (tr_state->traversing_mode != TRAVERSE_SORT) return 0;

	/*this is not an offscreen group*/
	if (!(group->flags & GROUP_IS_CACHED) ) {
		Bool cache_on = 0;

		/*group cache has been turned on in the previous frame*/
		if (!is_dirty && (group->flags & GROUP_IS_CACHABLE)) {
			group->flags |= GROUP_IS_CACHED;
			group->flags &= ~GROUP_IS_CACHABLE;
			GF_LOG(GF_LOG_DEBUG, GF_LOG_CACHE, ("[CACHE] Turning group %s cache on - size %d\n", gf_node_get_log_name(node), group->cached_size ));
			cache_on = 1;
		}
		/*group cache has been turned off in the previous frame*/
		else if (group->cache) {
			group_cache_del(group->cache);
			group->cache = NULL;
			group->changed = is_dirty;
			group->nb_stats_frame = 0;
			group->traverse_time = 0;
			GF_LOG(GF_LOG_DEBUG, GF_LOG_CACHE, ("[CACHE] Turning group %s cache off\n", gf_node_get_log_name(node) ));
			return 0;
		}

		if (!cache_on) {
			if (is_dirty) {
				group->changed = 1;
			}
			/*ask for stats again*/
			else if (group->changed) {
				group->changed = 0;
				group->nb_stats_frame = 0;
				group->traverse_time = 0;
			} else if (zoom_changed) {
				group->nb_stats_frame = 0;
				group->traverse_time = 0;
			}
			if (is_dirty || (group->nb_stats_frame < NUM_STATS_FRAMES)) {
				/*force direct draw mode*/
				if (!is_dirty)
					tr_state->visual->compositor->traverse_state->invalidate_all = 1;
				/*force redraw*/
				tr_state->visual->compositor->draw_next_frame = 1;
			}
			return 0;
		}
	}
	/*cache is dirty*/
	else if (is_dirty) {
		/*permanent cache, just recompute*/
		if (group->flags & GROUP_PERMANENT_CACHE) {
			group->changed = 1;
			group->cache->force_recompute = 1;
		}
		/*otherwise destroy the cache*/
		else if (group->cache) {
			gf_cache_remove_entry(tr_state->visual->compositor, node, group);
			group_cache_del(group->cache);
			group->cache = NULL;
			group->flags &= ~GROUP_IS_CACHED;
			group->changed = 0;
			group->nb_stats_frame = 0;
			group->traverse_time = 0;
			GF_LOG(GF_LOG_DEBUG, GF_LOG_CACHE, ("[CACHE] Turning group %s cache off due to sub-tree modifications\n", gf_node_get_log_name(node) ));
			return 0;
		}
	}
	/*zoom has changed*/
	else if (zoom_changed) {
		/*permanent cache, just recompute*/
		if (group->flags & GROUP_PERMANENT_CACHE) {
			group->changed = 1;
			group->cache->force_recompute = 1;
		}
		/*otherwise check if we accept this scale ratio or if we must recompute*/
		else if (group->cache) {
			Fixed scale = MAX(tr_state->transform.m[0], tr_state->transform.m[4]);

			if (100*scale >= group->cache->scale*(100 + tr_state->visual->compositor->cache_tolerance))
				zoom_changed = 1;
			else if ((100+tr_state->visual->compositor->cache_tolerance)*scale <= 100*group->cache->scale)
				zoom_changed = 1;
			else
				zoom_changed = 0;

			if (zoom_changed) {
				gf_cache_remove_entry(tr_state->visual->compositor, node, group);
				group_cache_del(group->cache);
				group->cache = NULL;
				group->flags &= ~GROUP_IS_CACHED;
				group->changed = 0;
				group->nb_stats_frame = 0;
				group->traverse_time = 0;
				GF_LOG(GF_LOG_DEBUG, GF_LOG_CACHE, ("[CACHE] Turning group %s cache off due to zoom changes\n", gf_node_get_log_name(node) ));
				return 0;
			}
		}
	}

	/*keep track of this cache object for later removal*/
	if (!(group->flags & GROUP_PERMANENT_CACHE))
		gf_list_add(tr_state->visual->compositor->cached_groups_queue, group);

	if (!group->cache) {
		/*ALLOCATE THE CACHE*/
		group->cache = group_cache_new(tr_state->visual->compositor, node);
		needs_recompute = 1;
	}

	/*cache has been modified due to node changes, reset stats*/
	group_cache_traverse(node, group->cache, tr_state, needs_recompute, 1, 0);
	return 1;
}
Пример #2
0
static void TraverseOffscreenGroup(GF_Node *node, void *rs, Bool is_destroy)
{
    OffscreenGroupStack *stack = (OffscreenGroupStack *)gf_node_get_private(node);
    GF_TraverseState *tr_state = (GF_TraverseState *) rs;

    if (is_destroy) {
        if (stack->cache) group_cache_del(stack->cache);
        gf_free(stack);
        return;
    }

    if (tr_state->traversing_mode==TRAVERSE_SORT) {
        if (!stack->detached && (gf_node_dirty_get(node) & GF_SG_NODE_DIRTY)) {
            OffscreenGroup_GetNode(node, &stack->og);

            if (stack->og.offscreen) {
                stack->flags |= GROUP_IS_CACHED | GROUP_PERMANENT_CACHE;
                if (!stack->cache) {
                    stack->cache = group_cache_new(tr_state->visual->compositor, (GF_Node*)&stack->og);
                }
                stack->cache->opacity = stack->og.opacity;
                stack->cache->drawable->flags |= DRAWABLE_HAS_CHANGED;
            } else {
                if (stack->cache) group_cache_del(stack->cache);
                stack->cache = NULL;
                stack->flags &= ~(GROUP_IS_CACHED|GROUP_PERMANENT_CACHE);
            }
            gf_node_dirty_clear(node, GF_SG_NODE_DIRTY);
            /*flag is not set for PROTO*/
            gf_node_dirty_set(node, GF_SG_CHILD_DIRTY, 0);
        }
        if (stack->cache) {
            if (stack->detached)
                gf_node_dirty_clear(node, GF_SG_CHILD_DIRTY);

            tr_state->subscene_not_over = 0;
            group_cache_traverse((GF_Node *)&stack->og, stack->cache, tr_state, stack->cache->force_recompute, 1, stack->detached ? 1 : 0);

            if (gf_node_dirty_get(node)) {
                gf_node_dirty_clear(node, GF_SG_CHILD_DIRTY);
            } else if ((stack->og.offscreen==2) && !stack->detached && !tr_state->subscene_not_over && stack->cache->txh.width && stack->cache->txh.height) {
                GF_FieldInfo field;
                if (gf_node_get_field(node, 0, &field) == GF_OK) {
                    gf_node_unregister_children(node, *(GF_ChildNodeItem **) field.far_ptr);
                    *(GF_ChildNodeItem **) field.far_ptr = NULL;
                    stack->detached = 1;
                }
                if (gf_node_get_field(node, 3, &field) == GF_OK) {
                    *(SFBool *) field.far_ptr = 1;
                    //gf_node_event_out(node, 3);
                }
            }
        } else {
            group_2d_traverse((GF_Node *)&stack->og, (GroupingNode2D*)stack, tr_state);
        }
    }
    /*draw mode*/
    else if (stack->cache && (tr_state->traversing_mode == TRAVERSE_DRAW_2D)) {
        /*draw it*/
        group_cache_draw(stack->cache, tr_state);
        gf_node_dirty_clear(node, GF_SG_CHILD_DIRTY);
    } else if (!stack->detached) {
        group_2d_traverse((GF_Node *)&stack->og, (GroupingNode2D*)stack, tr_state);
    } else {
        if (tr_state->traversing_mode == TRAVERSE_GET_BOUNDS) {
            tr_state->bounds = stack->bounds;
        }
        else if (tr_state->traversing_mode == TRAVERSE_PICK) {
            vrml_drawable_pick(stack->cache->drawable, tr_state);
        }
    }
}
Пример #3
0
static void svg_traverse_g(GF_Node *node, void *rs, Bool is_destroy)
{
	GF_Matrix2D backup_matrix;
	GF_Matrix mx_3d;
	SVGPropertiesPointers backup_props;
	u32 backup_flags;
	u32 styling_size = sizeof(SVGPropertiesPointers);

	GF_TraverseState *tr_state = (GF_TraverseState *) rs;

	SVGAllAttributes all_atts;

	if (is_destroy) {
		SVGgStack *group = gf_node_get_private(node);
#ifdef GF_SR_USE_VIDEO_CACHE
		group_2d_destroy_svg(node, group);
#else
		if (group->cache) group_cache_del(group->cache);
#endif
		gf_free(group);
		gf_sc_check_focus_upon_destroy(node);
		return;
	}
	/*group cache traverse routine*/
	else if (tr_state->traversing_mode == TRAVERSE_DRAW_2D) {
		SVGgStack *group = gf_node_get_private(node);
		group_cache_draw(group->cache, tr_state);
		return;
	}

	gf_svg_flatten_attributes((SVG_Element *)node, &all_atts);

	if (!compositor_svg_traverse_base(node, &all_atts, tr_state, &backup_props, &backup_flags))
		return;

	if (compositor_svg_is_display_off(tr_state->svg_props)) {
/*		u32 prev_flags = tr_state->switched_off;
		tr_state->switched_off = 1;
		compositor_svg_traverse_children(((SVG_Element *)node)->children, tr_state);
		tr_state->switched_off = prev_flags;*/

		memcpy(tr_state->svg_props, &backup_props, styling_size);
		tr_state->svg_flags = backup_flags;
		return;
	}	
	
	compositor_svg_apply_local_transformation(tr_state, &all_atts, &backup_matrix, &mx_3d);
	if (tr_state->traversing_mode == TRAVERSE_GET_BOUNDS) {
		gf_sc_get_nodes_bounds(node, ((SVG_Element *)node)->children, tr_state, NULL);
	} else if (tr_state->traversing_mode == TRAVERSE_SORT) {
#ifdef GF_SR_USE_DEPTH
		Fixed scale, offset, dscale, doffset;
#endif
		Fixed opacity = FIX_ONE;
		Bool clear = 0;
		SVGgStack *group;
		
		if (!tr_state->in_svg_filter && all_atts.filter && all_atts.filter->iri.target) {
			svg_draw_filter(all_atts.filter->iri.target, node, tr_state);
			return;
		}
		group = gf_node_get_private(node);

		if (tr_state->parent_use_opacity) {
			opacity = tr_state->parent_use_opacity->value;
			tr_state->parent_use_opacity = NULL;
		}
		if (all_atts.opacity) {
			opacity = gf_mulfix(opacity, all_atts.opacity->value);
		}
		if (gf_node_dirty_get(node)&GF_SG_CHILD_DIRTY) {
			drawable_reset_group_highlight(tr_state, node);
			clear=1;
		}

#ifdef GF_SR_USE_DEPTH
		dscale = FIX_ONE;
		doffset=0;
		if (all_atts.gpac_depthGain && all_atts.gpac_depthGain->type==SVG_NUMBER_VALUE) dscale = all_atts.gpac_depthGain->value;
		if (all_atts.gpac_depthOffset && all_atts.gpac_depthOffset->type==SVG_NUMBER_VALUE) doffset = all_atts.gpac_depthOffset->value;
		scale = tr_state->depth_gain;
		offset = tr_state->depth_offset;
		// new offset is multiplied by parent gain and added to parent offset
		tr_state->depth_offset = gf_mulfix(doffset, scale) + offset;
		// gain is multiplied by parent gain
		tr_state->depth_gain = gf_mulfix(scale, dscale);
#endif

		if (opacity < FIX_ONE) {
			if (!group->cache) {
				group->cache = group_cache_new(tr_state->visual->compositor, node);
				group->cache->force_recompute = 1;
			}
			group->cache->opacity = opacity;
			if (tr_state->visual->compositor->zoom_changed)
				group->cache->force_recompute = 1;
			group->flags |= GROUP_IS_CACHED | GROUP_PERMANENT_CACHE;
#ifdef GF_SR_USE_VIDEO_CACHE
			group_2d_cache_traverse(node, group, tr_state);
#else
			group_cache_traverse(node, group->cache, tr_state, group->cache->force_recompute, 0, 0);
#endif
		} else {
#ifdef GF_SR_USE_VIDEO_CACHE
			Bool group_cached;

			group_cached = group_2d_cache_traverse(node, group, tr_state);
			gf_node_dirty_clear(node, GF_SG_CHILD_DIRTY);
			/*group is not cached, traverse the children*/
			if (!group_cached) {
				GF_ChildNodeItem *child;
				DrawableContext *first_ctx = tr_state->visual->cur_context;
				u32 cache_too_small = 0;
				Bool skip_first_ctx = (first_ctx && first_ctx->drawable) ? 1 : 0;
				u32 traverse_time = gf_sys_clock();
				u32 last_cache_idx = gf_list_count(tr_state->visual->compositor->cached_groups_queue);
				tr_state->cache_too_small = 0;

				child = ((GF_ParentNode *)node)->children;
				while (child) {
					gf_node_traverse(child->node, tr_state);
					child = child->next;
					if (tr_state->cache_too_small) 
						cache_too_small++;
				}

				if (cache_too_small) {
					tr_state->cache_too_small = 1;
				} else {
					/*get the traversal time for each group*/	
					traverse_time = gf_sys_clock() - traverse_time;
					group->traverse_time += traverse_time;
					/*record the traversal information and turn cache on if possible*/
					group_2d_cache_evaluate(node, group, tr_state, first_ctx, skip_first_ctx, last_cache_idx);
				}
			}
#else
			compositor_svg_traverse_children(((SVG_Element *)node)->children, tr_state);
#endif
		}
		if (clear) gf_node_dirty_clear(node, 0);

		drawable_check_focus_highlight(node, tr_state, NULL);

#ifdef GF_SR_USE_DEPTH
		tr_state->depth_gain = scale;
		tr_state->depth_offset = offset;
#endif
	} else {
			compositor_svg_traverse_children(((SVG_Element *)node)->children, tr_state);
	}
	compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, &mx_3d);
	memcpy(tr_state->svg_props, &backup_props, styling_size);
	tr_state->svg_flags = backup_flags;
}