Ejemplo n.º 1
0
static void viewport_set_bind(GF_Node *node, GF_Route *route)
{
	GF_Compositor *rend = gf_sc_get_compositor(node);
	ViewStack *st = (ViewStack *) gf_node_get_private(node);
	Bindable_OnSetBind(node, st->reg_stacks, NULL);

	gf_sc_invalidate(rend, NULL);
	/*notify change of vp stack*/
	VPCHANGED(rend);
	/*and dirty ourselves to force frustrum update*/
	gf_node_dirty_set(node, 0, 0);
}
Ejemplo n.º 2
0
static void svg_a_set_view(GF_Node *handler, GF_Compositor *compositor, const char *url)
{
	gf_scene_set_fragment_uri(handler, url);
	/*force recompute viewbox of root SVG - FIXME in full this should be the parent svg*/
	gf_node_dirty_set(gf_sg_get_root_node(gf_node_get_graph(handler)), 0, 0);

	compositor->trans_x = compositor->trans_y = 0;
	compositor->rotation = 0;
	compositor->zoom = FIX_ONE;
	compositor_2d_set_user_transform(compositor, FIX_ONE, 0, 0, 0); 				
	gf_sc_invalidate(compositor, NULL);
}
Ejemplo n.º 3
0
void gf_font_predestroy(GF_Font *font)
{
	if (font->spans) {
		while (gf_list_count(font->spans)) {
			GF_TextSpan *ts = gf_list_get(font->spans, 0);
			gf_list_rem(font->spans, 0);
			gf_node_dirty_set(ts->user, 0, 0);
			ts->user=NULL;
		}
		gf_list_del(font->spans);
		font->spans = NULL;
	}
}
Ejemplo n.º 4
0
void compositor_init_svg_animation(GF_Compositor *compositor, GF_Node *node)
{
	SVGlinkStack *stack;

	GF_SAFEALLOC(stack, SVGlinkStack);
	gf_node_set_private(node, stack);
	gf_node_set_callback_function(node, svg_traverse_animation);

	gf_smil_set_evaluation_callback(node, svg_animation_smil_evaluate);

	/*force first processing of xlink-href*/
	gf_node_dirty_set(node, GF_SG_SVG_XLINK_HREF_DIRTY, 0);
}
Ejemplo n.º 5
0
void V4StudioTree::OnEndDrag(wxTreeEvent& event)
{
    wxTreeItemId itemSrc = m_draggedItem, itemDst = event.GetItem(), dstParentItem = GetItemParent(itemDst);
    m_draggedItem = (wxTreeItemId)0l;

	V4StudioTreeItemData *srcData = (V4StudioTreeItemData *)GetItemData(itemSrc);
	GF_FieldInfo srcField;
	srcData->GetField(&srcField);
	// Removal of the src item from its parent field
	switch (srcField.fieldType) {
	case GF_SG_VRML_SFNODE:
		if (* (GF_Node **) srcField.far_ptr) {}
		break;
	case GF_SG_VRML_MFNODE:
		{
			GF_List *nodes = (* (GF_List **) srcField.far_ptr);
			gf_list_rem(nodes, srcData->GetPosition());
		}
		break;
	default:
		break;
	}

	GF_Node *srcNode = srcData->GetNode();
	GF_FieldInfo dstField;
	V4StudioTreeItemData *dstData = (V4StudioTreeItemData *)GetItemData(itemDst);
	dstData->GetField(&dstField);
	// Addition of the src item prior to the dest item
	switch (dstField.fieldType) {
	case GF_SG_VRML_SFNODE:
		if (* (GF_Node **) dstField.far_ptr) {}
		break;
	case GF_SG_VRML_MFNODE:
		{
			GF_List *nodes = (* (GF_List **) dstField.far_ptr);
			gf_list_insert(nodes, srcNode, dstData->GetPosition());
			gf_node_dirty_set(dstData->GetNode(), 0, 1);
		}
		break;
	default:
		break;
	}

	GF_Node *dstParentNode = dstData->GetNodeParent();
	
	Delete(itemSrc);
	AddNodesToItem(dstParentItem, srcNode, dstData->GetFieldIndex(), dstData->GetPosition());
	V4StudioFrame *mainFrame = (V4StudioFrame *)GetParent();
	mainFrame->UpdateSelection(srcNode,dstData->GetNodeParent());
	mainFrame->Update();
}
Ejemplo n.º 6
0
void compositor_init_svg_updates(GF_Compositor *compositor, GF_Node *node)
{
	SVG_updates_stack *stack;
	GF_SAFEALLOC(stack, SVG_updates_stack)

	/*force first processing of xlink-href*/
	gf_node_dirty_set(node, GF_SG_SVG_XLINK_HREF_DIRTY, GF_FALSE);

	gf_smil_set_evaluation_callback(node, svg_updates_smil_evaluate);

	gf_node_set_private(node, stack);
	gf_node_set_callback_function(node, svg_traverse_updates);
	stack->clipEnd = -1;
}
Ejemplo n.º 7
0
void compositor_init_plane_clipper(GF_Compositor *compositor, GF_Node *node)
{
    PlaneClipper pc;
    if (PlaneClipper_GetNode(node, &pc)) {
        PlaneClipperStack *stack;
        GF_SAFEALLOC(stack, PlaneClipperStack);
        //SetupGroupingNode(stack, compositor->compositor, node, & pc.children);
        gf_node_set_private(node, stack);
        gf_node_set_callback_function(node, TraversePlaneClipper);
        /*we're a grouping node, force bounds rebuild as soon as loaded*/
        gf_node_dirty_set(node, GF_SG_CHILD_DIRTY, 0);

        stack->pc = pc;
        gf_node_proto_set_grouping(node);
    }
}
Ejemplo n.º 8
0
void compositor_init_svg_audio(GF_Compositor *compositor, GF_Node *node, Bool slaved_timing)
{
	SVG_audio_stack *stack;
	GF_SAFEALLOC(stack, SVG_audio_stack)

	gf_sc_audio_setup(&stack->input, compositor, node);

	/*force first processing of xlink-href*/
	gf_node_dirty_set(node, GF_SG_SVG_XLINK_HREF_DIRTY, GF_FALSE);

	if (!slaved_timing) 
		gf_smil_set_evaluation_callback(node, svg_audio_smil_evaluate);

	gf_node_set_private(node, stack);
	gf_node_set_callback_function(node, svg_traverse_audio);
}
Ejemplo n.º 9
0
static Bool osd_process(GF_TermExt *termext, u32 action, void *param)
{
	const char *opt;
	GF_OSD *osd = termext->udta;

	switch (action) {
	case GF_TERM_EXT_START:
		osd->term = (GF_Terminal *) param;
		opt = gf_modules_get_option((GF_BaseInterface*)termext, "OSD", "Enabled");
		if (opt && strcmp(opt, "yes")) return 0;

		/*load scene*/
		if (! osd_load_scene(osd)) return 0;
		/*attach scene to compositor*/
		gf_sc_register_extra_graph(osd->term->compositor, osd->odm->subscene->graph, 0);


		/*we are not threaded*/
		termext->caps |= GF_TERM_EXTENSION_NOT_THREADED;

		osd->refresh_time_ms = 500;
		osd->evt_filter.on_event = osd_on_event_play;
		osd->evt_filter.udta = osd;
		gf_term_add_event_filter(osd->term, &osd->evt_filter);
		return 1;

	case GF_TERM_EXT_STOP:
		osd->text->string.vals[0] = NULL;
		/*remove scene to compositor*/
		gf_sc_register_extra_graph(osd->term->compositor, osd->odm->subscene->graph, 1);
		gf_odm_disconnect(osd->odm, 1);
		osd->odm = NULL;

		gf_term_remove_event_filter(osd->term, &osd->evt_filter);
		osd->term = NULL;
		break;

	case GF_TERM_EXT_PROCESS:
		/*flush all events until current time if reached*/
		if ((osd->visible->whichChoice==0) && gf_sys_get_rti(osd->refresh_time_ms, &osd->rti, 0)) {
			sprintf(osd->statBuffer, "CPU %02d - FPS %02.2f - MEM "LLU" KB", osd->rti.process_cpu_usage, gf_sc_get_fps(osd->term->compositor, 0), osd->rti.process_memory/1000);
			gf_node_dirty_set((GF_Node *) osd->text, GF_SG_NODE_DIRTY, 1);
		}
		break;
	}
	return 0;
}
Ejemplo n.º 10
0
void compositor_init_svg_image(GF_Compositor *compositor, GF_Node *node)
{
	SVG_video_stack *stack;
	GF_SAFEALLOC(stack, SVG_video_stack)
	stack->graph = drawable_new();
	stack->graph->flags = DRAWABLE_USE_TRAVERSE_DRAW;
	stack->graph->node = node;

	gf_sc_texture_setup(&stack->txh, compositor, node);
	stack->txh.update_texture_fcnt = SVG_Update_image;
	stack->txh.flags = GF_SR_TEXTURE_SVG;

	/*force first processing of xlink-href*/
	gf_node_dirty_set(node, GF_SG_SVG_XLINK_HREF_DIRTY, GF_FALSE);

	gf_node_set_private(node, stack);
	gf_node_set_callback_function(node, svg_traverse_image);
}
Ejemplo n.º 11
0
GF_EXPORT
void gf_sr_invalidate(GF_Renderer *sr, GF_Node *byObj)
{

    if (!byObj) {
        sr->draw_next_frame = 1;
        return;
    }
    switch (gf_node_get_tag(byObj)) {
    case TAG_MPEG4_AnimationStream:
        AnimationStreamModified(byObj);
        break;
    case TAG_MPEG4_AudioBuffer:
        AudioBufferModified(byObj);
        break;
    case TAG_MPEG4_AudioSource:
        AudioSourceModified(byObj);
        break;
    case TAG_MPEG4_AudioClip:
    case TAG_X3D_AudioClip:
        AudioClipModified(byObj);
        break;
    case TAG_MPEG4_TimeSensor:
    case TAG_X3D_TimeSensor:
        TimeSensorModified(byObj);
        break;
    case TAG_MPEG4_ImageTexture:
    case TAG_X3D_ImageTexture:
        ImageTextureModified(byObj);
        break;
    case TAG_MPEG4_MovieTexture:
    case TAG_X3D_MovieTexture:
        MovieTextureModified(byObj);
        break;
    default:
        /*for all nodes, invalidate parent graph - note we do that for sensors as well to force recomputing
        sensor list cached at grouping node level*/
        if (!sr->visual_renderer->NodeChanged(sr->visual_renderer, byObj)) {
            gf_node_dirty_set(byObj, 0, 1);
            sr->draw_next_frame = 1;
        }
        break;
    }
}
Ejemplo n.º 12
0
Archivo: bindable.c Proyecto: zsuo/gpac
void Bindable_OnSetBind(GF_Node *bindable, GF_List *stack_list, GF_List *for_stack)
{
	u32 i;
	Bool on_top, is_bound, set_bind;
	GF_Node *node;
	GF_List *stack;

	set_bind = Bindable_GetSetBind(bindable);
	is_bound = Bindable_GetIsBound(bindable);

	if (!set_bind && !is_bound) return;
	if (set_bind && is_bound) return;

	i=0;
	while ((stack = (GF_List*)gf_list_enum(stack_list, &i))) {
		if (for_stack && (for_stack!=stack)) continue;

		on_top = (gf_list_get(stack, 0)==bindable) ? GF_TRUE : GF_FALSE;

		if (!set_bind) {
			if (is_bound) Bindable_SetIsBound(bindable, GF_FALSE);
			if (on_top && (gf_list_count(stack)>1)) {
				gf_list_rem(stack, 0);
				gf_list_add(stack, bindable);
				node = (GF_Node*)gf_list_get(stack, 0);
				Bindable_SetIsBound(node, GF_TRUE);
			}
		} else {
			if (!is_bound) Bindable_SetIsBound(bindable, GF_TRUE);
			if (!on_top) {
				/*push old top one down and unbind*/
				node = (GF_Node*)gf_list_get(stack, 0);
				Bindable_SetIsBound(node, GF_FALSE);
				/*insert new top*/
				gf_list_del_item(stack, bindable);
				gf_list_insert(stack, bindable, 0);
			}
		}
	}
	/*force invalidate of the bindable stack's owner*/
	gf_node_dirty_set(bindable, 0, GF_TRUE);
	/*and redraw scene*/
	gf_sc_invalidate(gf_sc_get_compositor(bindable), NULL);
}
Ejemplo n.º 13
0
void compositor_background2d_modified(GF_Node *node)
{
	M_Background2D *bck = (M_Background2D *)node;
	Background2DStack *st = (Background2DStack *) gf_node_get_private(node);
	if (!st) return;

	/*dirty node and parents in order to trigger parent visual redraw*/
	gf_node_dirty_set(node, 0, 1);

	/*if open and changed, stop and play*/
	if (st->txh.is_open) {
		if (! gf_sc_texture_check_url_change(&st->txh, &bck->url)) return;
		gf_sc_texture_stop(&st->txh);
		gf_sc_texture_play(&st->txh, &bck->url);
		return;
	}
	/*if not open and changed play*/
	if (bck->url.count) 
		gf_sc_texture_play(&st->txh, &bck->url);
	gf_sc_invalidate(st->txh.compositor, NULL);
}
Ejemplo n.º 14
0
void compositor_svg_video_modified(GF_Compositor *compositor, GF_Node *node)
{
	/*if href has been modified, stop the video (and associated audio if any) right away - we cannot wait for next traversal to
	process this as the video could be in a hidden subtree not traversed*/
	if (gf_node_dirty_get(node) & GF_SG_SVG_XLINK_HREF_DIRTY) {
		SVG_video_stack *st = (SVG_video_stack *)gf_node_get_private(node);
		/*WARNING - stack may be NULL at this point when inserting the video from script*/
		if (st && st->txh.is_open) {
			if (st->audio) {
				svg_audio_smil_evaluate_ex(NULL, 0, SMIL_TIMING_EVAL_REMOVE, st->audio, st->txh.owner);
				gf_node_unregister(st->audio, NULL);
				st->audio = NULL;
			}
			/*reset cached URL to avoid reopening the resource in the smil timing callback*/
			gf_sg_vrml_mf_reset(&st->txurl, GF_SG_VRML_MFURL);
			gf_sc_texture_stop(&st->txh);
		}
	}
	gf_node_dirty_set(node, 0, GF_FALSE);
	/*and force a redraw of next frame*/
	gf_sc_next_frame_state(compositor, GF_SC_DRAW_FRAME);
}
Ejemplo n.º 15
0
Bool osd_on_event_play(void *udta, GF_Event *event, Bool consumed_by_compositor)
{
	GF_OSD* osd = (GF_OSD*)udta;
	switch (event->type) {
	case GF_EVENT_SCENE_SIZE:
		gf_sg_set_scene_size_info(osd->odm->subscene->graph, event->size.width, event->size.height, 1);
		break;
	case GF_EVENT_KEYUP:
		if ( (event->key.key_code == GF_KEY_I) && (event->key.flags & GF_KEY_MOD_CTRL)) {
			if (osd->visible->whichChoice==0) {
				osd->visible->whichChoice = -1;
				gf_cfg_set_key(osd->term->user->config, "OSD", "Visible", "no");
			} else {
				osd->visible->whichChoice = 0;
				gf_cfg_set_key(osd->term->user->config, "OSD", "Visible", "yes");
			}
			gf_node_dirty_set((GF_Node *) osd->visible, GF_SG_NODE_DIRTY, 1);
		}
		break;
	}
	return 0;
}
Ejemplo n.º 16
0
static void svg_traverse_tspan(GF_Node *node, void *rs, Bool is_destroy)
{
	SVGPropertiesPointers backup_props;
	u32 backup_flags;
	GF_Matrix2D backup_matrix;
	GF_Matrix mx3d;
	DrawableContext *ctx;
	SVG_TextStack *st = (SVG_TextStack *)gf_node_get_private(node);
	GF_TraverseState *tr_state = (GF_TraverseState *)rs;
	SVG_Element *tspan = (SVG_Element *)node;
	SVGAllAttributes atts;
	GF_ChildNodeItem *child;

	if (is_destroy) {
		drawable_del(st->drawable);
		svg_reset_text_stack(st);
		gf_list_del(st->spans);
		gf_free(st);
		return;
	}
	if (tr_state->traversing_mode==TRAVERSE_DRAW_2D) {
		svg_text_draw_2d(st, tr_state);
		return;
	}
	else if (tr_state->traversing_mode==TRAVERSE_GET_TEXT) {
		gf_font_spans_get_selection(node, st->spans, tr_state);
		/*and browse children*/
		child = ((GF_ParentNode *) tspan)->children;
		while (child) {
			switch  (gf_node_get_tag(child->node)) {
			case TAG_SVG_tspan:
				gf_node_traverse(child->node, tr_state);
				break;
			}
			child = child->next;
		}
		return;
	}

	if (!tr_state->in_svg_text && !tr_state->in_svg_text_area) return;

	gf_svg_flatten_attributes(tspan, &atts);
	if (!compositor_svg_traverse_base(node, &atts, tr_state, &backup_props, &backup_flags))
		return;

	if (tr_state->traversing_mode==TRAVERSE_PICK) {
		if (*tr_state->svg_props->pointer_events!=SVG_POINTEREVENTS_NONE)
			gf_font_spans_pick(node, st->spans, tr_state, &st->bounds, GF_TRUE, st->drawable);

		/*and browse children*/
		child = ((GF_ParentNode *) tspan)->children;
		while (child) {
			switch  (gf_node_get_tag(child->node)) {
			case TAG_SVG_tspan:
				gf_node_traverse(child->node, tr_state);
				break;
			}
			child = child->next;
		}
		memcpy(tr_state->svg_props, &backup_props, sizeof(SVGPropertiesPointers));
		tr_state->svg_flags = backup_flags;
		return;
	}

	compositor_svg_apply_local_transformation(tr_state, &atts, &backup_matrix, &mx3d);

	if ( (st->prev_size != tr_state->svg_props->font_size->value) ||
	        (st->prev_flags != *tr_state->svg_props->font_style) ||
	        (st->prev_anchor != *tr_state->svg_props->text_anchor) ||
	        (gf_node_dirty_get(node) & (GF_SG_SVG_GEOMETRY_DIRTY | GF_SG_CHILD_DIRTY) )
	   ) {
		u32 mode;

		/*tspan has been modified in the SORT stage, which means that an anim local to tspan has modified the node.
		The result of the parent (text, textArea) will thus be wrong if we try to update the tspan. We therefore
		keep the previous computed drawable, and invalidate the parent for next frame*/
		if (tr_state->traversing_mode==TRAVERSE_SORT) {
			gf_node_dirty_set(node, 0, GF_TRUE);
			goto skip_changes;
		}

		/*switch to bounds mode, and recompute children*/
		mode = tr_state->traversing_mode;
		tr_state->traversing_mode = TRAVERSE_GET_BOUNDS;

		svg_reset_text_stack(st);
		child = ((GF_ParentNode *) tspan)->children;

		while (child) {
			switch  (gf_node_get_tag(child->node)) {
			case TAG_DOMText:
				svg_traverse_domtext(child->node, &atts, tr_state, st->spans, NULL);
				break;
			case TAG_SVG_tspan:
				gf_node_dirty_set(child->node, 0, GF_FALSE);
				gf_node_traverse(child->node, tr_state);
				break;
			case TAG_SVG_switch:
			case TAG_SVG_a:
			case TAG_SVG_tbreak:
				gf_node_traverse(child->node, tr_state);
				break;
			default:
				break;
			}
			child = child->next;
		}
		tr_state->traversing_mode = mode;
		gf_node_dirty_clear(node, 0);
		drawable_mark_modified(st->drawable, tr_state);
		st->prev_size = tr_state->svg_props->font_size->value;
		st->prev_flags = *tr_state->svg_props->font_style;
		st->prev_anchor = *tr_state->svg_props->text_anchor;

		svg_update_bounds(st);
	}
skip_changes:

	if (tr_state->traversing_mode == TRAVERSE_GET_BOUNDS) {
		if (tr_state->refresh_children_bounds) {
			if (tr_state->base_shift)
				svg_text_area_shift_bounds(st, tr_state);
			else
				svg_update_bounds(st);
			child = ((GF_ParentNode *) tspan)->children;
			while (child) {
				switch  (gf_node_get_tag(child->node)) {
				case TAG_SVG_tspan:
				case TAG_SVG_switch:
				case TAG_SVG_a:
					gf_node_traverse(child->node, tr_state);
					break;
				default:
					break;
				}
				child = child->next;
			}
		}
		if (!compositor_svg_is_display_off(tr_state->svg_props))
			tr_state->bounds = st->bounds;

	}
	else if (
	    (tr_state->traversing_mode == TRAVERSE_SORT)
	    && !compositor_svg_is_display_off(tr_state->svg_props)
	    && ( *(tr_state->svg_props->visibility) != SVG_VISIBILITY_HIDDEN)
	) {
		child = ((GF_ParentNode *) tspan)->children;

		ctx = drawable_init_context_svg(st->drawable, tr_state);
		if (ctx) svg_finalize_sort(ctx, st, tr_state);

		while (child) {
			switch  (gf_node_get_tag(child->node)) {
			case TAG_SVG_tspan:
			case TAG_SVG_switch:
			case TAG_SVG_a:
				gf_node_traverse(child->node, tr_state);
				break;
			default:
				break;
			}
			child = child->next;
		}
	}

	compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, &mx3d);
	memcpy(tr_state->svg_props, &backup_props, sizeof(SVGPropertiesPointers));
	tr_state->svg_flags = backup_flags;
}
Ejemplo n.º 17
0
Archivo: bindable.c Proyecto: zsuo/gpac
void Bindable_SetIsBound(GF_Node *bindable, Bool val)
{
	Bool has_bind_time = GF_FALSE;
	if (!bindable) return;
	switch (gf_node_get_tag(bindable)) {
	case TAG_MPEG4_Background2D:
		if ( ((M_Background2D*)bindable)->isBound == val) return;
		((M_Background2D*)bindable)->isBound = val;
		break;
	case TAG_MPEG4_Viewport:
		if ( ((M_Viewport*)bindable)->isBound == val) return;
		((M_Viewport*)bindable)->isBound = val;
		((M_Viewport*)bindable)->bindTime = gf_node_get_scene_time(bindable);
		has_bind_time = GF_TRUE;
		break;
#ifndef GPAC_DISABLE_X3D
	case TAG_X3D_Background:
		if ( ((X_Background*)bindable)->isBound == val) return;
		((X_Background*)bindable)->isBound = val;
		((X_Background*)bindable)->bindTime = gf_node_get_scene_time(bindable);
		has_bind_time = GF_TRUE;
		break;
#endif
	case TAG_MPEG4_Background:
		if ( ((M_Background*)bindable)->isBound == val) return;
		((M_Background*)bindable)->isBound = val;
		break;
#ifndef GPAC_DISABLE_X3D
	case TAG_X3D_NavigationInfo:
		if ( ((X_NavigationInfo*)bindable)->isBound == val) return;
		((X_NavigationInfo*)bindable)->isBound = val;
		((X_NavigationInfo*)bindable)->bindTime = gf_node_get_scene_time(bindable);
		has_bind_time = GF_TRUE;
		break;
#endif
	case TAG_MPEG4_NavigationInfo:
		if ( ((M_NavigationInfo*)bindable)->isBound == val) return;
		((M_NavigationInfo*)bindable)->isBound = val;
		break;
	case TAG_MPEG4_Viewpoint:
#ifndef GPAC_DISABLE_X3D
	case TAG_X3D_Viewpoint:
#endif
		if ( ((M_Viewpoint*)bindable)->isBound == val) return;
		((M_Viewpoint*)bindable)->isBound = val;
		((M_Viewpoint*)bindable)->bindTime = gf_node_get_scene_time(bindable);
		has_bind_time = GF_TRUE;
		break;
#ifndef GPAC_DISABLE_X3D
	case TAG_X3D_Fog:
		if ( ((X_Fog*)bindable)->isBound == val) return;
		((X_Fog*)bindable)->isBound = val;
		((X_Fog*)bindable)->bindTime = gf_node_get_scene_time(bindable);
		has_bind_time = GF_TRUE;
		break;
#endif
	case TAG_MPEG4_Fog:
		if ( ((M_Fog*)bindable)->isBound == val) return;
		((M_Fog*)bindable)->isBound = val;
		break;
	default:
		return;
	}
	gf_node_event_out_str(bindable, "isBound");
	if (has_bind_time) gf_node_event_out_str(bindable, "bindTime");
	/*force invalidate of the bindable stack's owner*/
	gf_node_dirty_set(bindable, 0, GF_TRUE);
}
Ejemplo n.º 18
0
static void TraverseDepthGroup(GF_Node *node, void *rs, Bool is_destroy)
{
#ifdef GF_SR_USE_DEPTH
    Fixed depth_gain, depth_offset;
#endif

    DepthGroupStack *stack = (DepthGroupStack *)gf_node_get_private(node);
    GF_TraverseState *tr_state = (GF_TraverseState *) rs;

    if (is_destroy) {
        gf_free(stack);
        return;
    }

    if (tr_state->traversing_mode==TRAVERSE_SORT) {
        if (gf_node_dirty_get(node) & GF_SG_NODE_DIRTY) {

            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);
        }
    }
    DepthGroup_GetNode(node, &stack->dg);


#ifdef GF_SR_USE_DEPTH
    depth_gain = tr_state->depth_gain;
    depth_offset = tr_state->depth_offset;

    // new offset is multiplied by parent gain and added to parent offset
    tr_state->depth_offset = gf_mulfix(stack->dg.depth_offset, tr_state->depth_gain) + tr_state->depth_offset;

    // gain is multiplied by parent gain
    tr_state->depth_gain = gf_mulfix(tr_state->depth_gain, stack->dg.depth_gain);
#endif

#ifndef GPAC_DISABLE_3D
    if (tr_state->visual->type_3d) {
        GF_Matrix mx_bckup, mx;

        gf_mx_copy(mx_bckup, tr_state->model_matrix);
        gf_mx_init(mx);
        mx.m[14] = gf_mulfix(stack->dg.depth_offset, tr_state->visual->compositor->depth_gl_scale);
        gf_mx_add_matrix(&tr_state->model_matrix, &mx);

        if (tr_state->traversing_mode == TRAVERSE_SORT) {
            visual_3d_matrix_push(tr_state->visual);
            visual_3d_matrix_add(tr_state->visual, mx.m);

            group_2d_traverse((GF_Node *)&stack->dg, (GroupingNode2D*)stack, tr_state);

            visual_3d_matrix_pop(tr_state->visual);
        } else {
            group_2d_traverse((GF_Node *)&stack->dg, (GroupingNode2D*)stack, tr_state);
        }
        gf_mx_copy(tr_state->model_matrix, mx_bckup);

    } else
#endif
    {

        group_2d_traverse((GF_Node *)&stack->dg, (GroupingNode2D*)stack, tr_state);
    }

#ifdef GF_SR_USE_DEPTH
    tr_state->depth_gain = depth_gain;
    tr_state->depth_offset = depth_offset;
#endif
}
Ejemplo n.º 19
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);
        }
    }
}
Ejemplo n.º 20
0
GF_EXPORT
void gf_sc_invalidate(GF_Compositor *compositor, GF_Node *byObj)
{

	if (!byObj) {
		gf_sc_next_frame_state(compositor, GF_SC_DRAW_FRAME);
		return;
	}
	switch (gf_node_get_tag(byObj)) {
#ifndef GPAC_DISABLE_VRML
	case TAG_MPEG4_AnimationStream: compositor_animationstream_modified(byObj); break;
	case TAG_MPEG4_AudioBuffer: compositor_audiobuffer_modified(byObj); break;
	case TAG_MPEG4_AudioSource: compositor_audiosource_modified(byObj); break;
	case TAG_MPEG4_AudioClip:
#ifndef GPAC_DISABLE_X3D
	case TAG_X3D_AudioClip:
#endif
		compositor_audioclip_modified(byObj); break;
	case TAG_MPEG4_TimeSensor:
#ifndef GPAC_DISABLE_X3D
	case TAG_X3D_TimeSensor:
#endif
		compositor_timesensor_modified(byObj); break;
	case TAG_MPEG4_ImageTexture:
#ifndef GPAC_DISABLE_X3D
	case TAG_X3D_ImageTexture:
#endif
	case TAG_MPEG4_CacheTexture:
		compositor_imagetexture_modified(byObj); break;

	case TAG_MPEG4_MovieTexture:
#ifndef GPAC_DISABLE_X3D
	case TAG_X3D_MovieTexture:
#endif
		compositor_movietexture_modified(byObj); break;

	case TAG_MPEG4_Background2D: compositor_background2d_modified(byObj); break;
#ifndef GPAC_DISABLE_3D
	case TAG_MPEG4_Background:
#ifndef GPAC_DISABLE_X3D
	case TAG_X3D_Background:
#endif
		compositor_background_modified(byObj); break;
#endif
	case TAG_MPEG4_Layout: compositor_layout_modified(compositor, byObj); break;
	case TAG_MPEG4_EnvironmentTest: compositor_envtest_modified(byObj); break;

#endif /*GPAC_DISABLE_VRML*/

#ifndef GPAC_DISABLE_SVG
	case TAG_SVG_video: compositor_svg_video_modified(compositor, byObj); break;
#endif /*GPAC_DISABLE_SVG*/

	default:
		/*for all nodes, invalidate parent graph - note we do that for sensors as well to force recomputing
		sensor list cached at grouping node level*/
		gf_node_dirty_set(byObj, 0, 1);
		gf_sc_next_frame_state(compositor, GF_SC_DRAW_FRAME);
		break;
	}
}
Ejemplo n.º 21
0
GF_EXPORT
void gf_sc_texture_update_frame(GF_TextureHandler *txh, Bool disable_resync)
{
	Bool needs_reload = 0;
	u32 size, ts;
	s32 ms_until_pres, ms_until_next;

	/*already refreshed*/
	if (txh->needs_refresh) return;

	if (!txh->stream) {
		txh->data = NULL;
		return;
	}

	/*should never happen!!*/
	if (txh->needs_release) gf_mo_release_data(txh->stream, 0xFFFFFFFF, 0);

	/*check init flag*/
	if (!(gf_mo_get_flags(txh->stream) & GF_MO_IS_INIT)) {
		needs_reload = 1;
		txh->data = NULL;
		if (txh->tx_io) {
			gf_sc_texture_release(txh);
		}
	}
	txh->data = gf_mo_fetch_data(txh->stream, !disable_resync, &txh->stream_finished, &ts, &size, &ms_until_pres, &ms_until_next);

	if (!(gf_mo_get_flags(txh->stream) & GF_MO_IS_INIT)) {
		needs_reload = 1;
	} else if (size && txh->size && (size != txh->size)) {
		needs_reload = 1;
	}

	if (needs_reload) {
		/*if we had a texture this means the object has changed - delete texture and resetup. Do not skip
		texture update as this may lead to an empty rendering pass (blank frame for this object), especially in DASH*/
		if (txh->tx_io) {
			gf_sc_texture_release(txh);
			txh->needs_refresh = 1;
		}
		if (gf_mo_is_private_media(txh->stream)) {
			setup_texture_object(txh, 1);
			gf_node_dirty_set(txh->owner, 0, 0);
		}
	}

	/*if no frame or muted don't draw*/
	if (!txh->data || !size) {
		GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("|Visual Texture] No output frame available \n"));
		/*TODO - check if this is needed */
		if (txh->flags & GF_SR_TEXTURE_PRIVATE_MEDIA) {
			//txh->needs_refresh = 1;
			gf_sc_invalidate(txh->compositor, NULL);
		}
		return;
	}

	/*if setup and same frame return*/
	if (txh->tx_io && (txh->stream_finished || (txh->last_frame_time==ts)) ) {
		gf_mo_release_data(txh->stream, 0xFFFFFFFF, 0);
		txh->needs_release = 0;
		if (!txh->stream_finished) {
			if (ms_until_next>0 && (txh->compositor->next_frame_delay > (u32) ms_until_next))
				txh->compositor->next_frame_delay = ms_until_next;
		}
		return;
	}
	txh->needs_release = 1;
	txh->last_frame_time = ts;
	txh->size = size;
	if (txh->raw_memory) {
		gf_mo_get_raw_image_planes(txh->stream, (u8 **) &txh->data, (u8 **) &txh->pU, (u8 **) &txh->pV);
	}
	if (gf_mo_is_muted(txh->stream)) return;


	if (txh->nb_frames) {
		s32 push_delay = txh->upload_time / txh->nb_frames;
		if (push_delay > ms_until_pres) ms_until_pres = 0;
		else ms_until_pres -= push_delay;
	}

	if (txh->compositor->frame_delay < ms_until_pres)
		txh->compositor->frame_delay = ms_until_pres;

	txh->compositor->next_frame_delay = 1;

	if (!txh->tx_io) {
		setup_texture_object(txh, 0);
	}

	/*try to push texture on graphics but don't complain if failure*/
	gf_sc_texture_set_data(txh);

	txh->needs_refresh = 1;
	gf_sc_invalidate(txh->compositor, NULL);
}
Ejemplo n.º 22
0
static void gf_inline_traverse(GF_Node *n, void *rs, Bool is_destroy)
{
	MFURL *current_url;
	GF_Scene *scene = (GF_Scene *)gf_node_get_private(n);

	if (is_destroy) {
		GF_MediaObject *mo;
		if (!scene) return;
		mo = scene->root_od ? scene->root_od->mo : NULL;

		gf_scene_notify_event(scene, GF_EVENT_UNLOAD, n, NULL, GF_OK);
		if (!mo) return;
		gf_list_del_item(mo->nodes, n);

		/*disconnect current inline if we're the last one using it (same as regular OD session leave/join)*/
		if (mo->num_open) {
			mo->num_open --;
			if (!mo->num_open) {
				gf_term_lock_media_queue(scene->root_od->term, 1);

				/*this is unspecified in the spec: whenever an inline not using the 
				OD framework is destroyed, destroy the associated resource*/
				if (mo->OD_ID == GF_MEDIA_EXTERNAL_ID) {
					/*get parent scene and remove MediaObject in case the ressource
					gets re-requested later on*/
					GF_Scene *parent_scene = (GF_Scene *)gf_sg_get_private(gf_node_get_graph((GF_Node *) n) );
					if (gf_list_del_item(parent_scene->scene_objects, mo)>=0) {
						gf_sg_vrml_mf_reset(&mo->URLs, GF_SG_VRML_MFURL);
						gf_list_del(mo->nodes);
						if (mo->odm) mo->odm->mo = NULL;
						gf_free(mo);
					}
					scene->root_od->action_type = GF_ODM_ACTION_DELETE;
					gf_list_add(scene->root_od->term->media_queue, scene->root_od);
				} else {
					scene->root_od->action_type = GF_ODM_ACTION_SCENE_DISCONNECT;
					gf_list_add(scene->root_od->term->media_queue, scene->root_od);
				}
				gf_term_lock_media_queue(scene->root_od->term, 0);
			}
		}
		return;
	}


	//if no private scene is associated	get the node parent graph, retrieve the IS and find the OD
	if (!scene) {
		M_Inline *inl = (M_Inline *)n;
		gf_inline_set_scene(inl);
		scene = (GF_Scene *)gf_node_get_private(n);
		if (!scene) {
			/*just like protos, we must invalidate parent graph until attached*/
			if (inl->url.count) {
				if (!inl->url.vals[0].OD_ID && (!inl->url.vals[0].url || !strlen(inl->url.vals[0].url) ) ) {
					gf_sg_vrml_mf_reset(&inl->url, GF_SG_VRML_MFURL);
				} else {
					gf_node_dirty_set(n, 0, 1);
				}
			}
			return;
		}
	}

	gf_inline_check_restart(scene);

	/*if we need to restart, shutdown graph and do it*/
	if (scene->needs_restart) {
		/*special case: scene change*/
		if (scene->needs_restart==2) {
			scene->needs_restart = 0;
			gf_inline_on_modified(n);
			return;
		}

		scene->needs_restart = 0;
		gf_term_lock_media_queue(scene->root_od->term, 1);
		scene->root_od->action_type = GF_ODM_ACTION_SCENE_INLINE_RESTART;
		gf_list_add(scene->root_od->term->media_queue, scene->root_od);
		gf_term_lock_media_queue(scene->root_od->term, 0);

		gf_node_dirty_set(n, 0, 1);
		return;
	} 
	
	/*if not attached return (attaching the graph cannot be done in render since render is not called while unattached :) */
	if (!scene->graph_attached) {
		/*just like protos, we must invalidate parent graph until attached*/
		gf_node_dirty_set(n, 0, 1);
		return;
	}
	/*clear dirty flags for any sub-inlines, bitmaps or protos*/
	gf_node_dirty_clear(n, 0);

	current_url = scene->current_url;
	scene->current_url = & ((M_Inline*)n)->url;
	gf_sc_traverse_subscene(scene->root_od->term->compositor, n, scene->graph, rs);
	scene->current_url = current_url;
}
Ejemplo n.º 23
0
static void TraverseLayer3D(GF_Node *node, void *rs, Bool is_destroy)
{
	Bool prev_layer, changed = 0;
	GF_List *oldb, *oldv, *oldf, *oldn;
	GF_Rect rc;
	u32 cur_lights;
	GF_List *node_list_backup;
	GF_BBox bbox_backup;
	GF_Matrix model_backup;
	GF_Matrix2D mx2d_backup;
	GF_Camera *prev_cam;
	GF_VisualManager *old_visual;
	M_Layer3D *l = (M_Layer3D *)node;
	Layer3DStack *st = (Layer3DStack *) gf_node_get_private(node);
	GF_TraverseState *tr_state = (GF_TraverseState *) rs;
	
	if (is_destroy) {
		DestroyLayer3D(node);
		return;
	}
	if (st->unsupported) return;

	if (gf_node_dirty_get(node)) {

		/*main visual in pixel metrics, use output width*/
		if (tr_state->pixel_metrics && (tr_state->visual->compositor->visual==tr_state->visual)) {
			st->clip.width = INT2FIX(tr_state->visual->compositor->vp_width);
			st->clip.height = INT2FIX(tr_state->visual->compositor->vp_height);
		} else {
			visual_get_size_info(tr_state, &st->clip.width, &st->clip.height);
		}
		/*setup bounds in local coord system*/
		if (l->size.x>=0) st->clip.width = l->size.x;
		if (l->size.y>=0) st->clip.height = l->size.y;
		st->clip = gf_rect_center(st->clip.width, st->clip.height);

		changed = 1;
	}

	switch (tr_state->traversing_mode) {
	case TRAVERSE_GET_BOUNDS:
		if (!tr_state->for_node) {
			tr_state->bounds = st->clip;
			gf_bbox_from_rect(&tr_state->bbox, &st->clip);
			return;
		}
	case TRAVERSE_PICK:
	case TRAVERSE_SORT:
		/*layers can only be used in a 2D context*/
		if (tr_state->camera && tr_state->camera->is_3D) return;
		break;
	case TRAVERSE_DRAW_2D:
		layer3d_draw_2d(node, tr_state);
		return;
	case TRAVERSE_DRAW_3D:
	default:
		return;
	}

	/*layer3D maintains its own stacks*/
	oldb = tr_state->backgrounds;
	oldv = tr_state->viewpoints;
	oldf = tr_state->fogs;
	oldn = tr_state->navigations;
	tr_state->backgrounds = st->visual->back_stack;
	tr_state->viewpoints = st->visual->view_stack;
	tr_state->navigations = st->visual->navigation_stack;
	tr_state->fogs = st->visual->fog_stack;
	prev_layer = tr_state->is_layer;
	tr_state->is_layer = 1;

	prev_cam = tr_state->camera;
	tr_state->camera = &st->visual->camera;
	old_visual = tr_state->visual;

	bbox_backup = tr_state->bbox;
	gf_mx_copy(model_backup, tr_state->model_matrix);
	gf_mx2d_copy(mx2d_backup, tr_state->transform);


	/*compute viewport in visual coordinate*/
	rc = st->clip;
	if (prev_cam) {
		gf_mx_apply_rect(&tr_state->model_matrix, &rc);

		gf_mx_apply_rect(&prev_cam->modelview, &rc);
		if (tr_state->camera->flags & CAM_HAS_VIEWPORT)
			gf_mx_apply_rect(&prev_cam->viewport, &rc);
#if 0
		if (tr_state->visual->compositor->visual==tr_state->visual) {
			GF_Matrix mx;
			gf_mx_init(mx);
			gf_mx_add_scale(&mx, tr_state->visual->compositor->scale_x, tr_state->visual->compositor->scale_y, FIX_ONE);
			gf_mx_apply_rect(&mx, &rc);
		}
#endif
	} else {
		gf_mx2d_apply_rect(&tr_state->transform, &rc);

/*		if (tr_state->visual->compositor->visual==tr_state->visual) {
			gf_mx2d_init(mx2d_backup);
			gf_mx2d_add_scale(&mx2d_backup, tr_state->visual->compositor->scale_x, tr_state->visual->compositor->scale_y);
			gf_mx2d_apply_rect(&mx2d_backup, &rc);
		}
*/
		/*switch visual*/
		tr_state->visual = st->visual;
	}


	/*check bindables*/
	gf_mx_init(tr_state->model_matrix);
	l3d_CheckBindables(node, tr_state, st->first);
	if (prev_cam) gf_mx_copy(tr_state->model_matrix, model_backup);


	/*drawing a layer means drawing all subelements as a whole (no depth sorting with parents)*/
	if (tr_state->traversing_mode==TRAVERSE_SORT) {

		if (gf_node_dirty_get(node)) changed = 1;
		gf_node_dirty_clear(node, GF_SG_NODE_DIRTY|GF_SG_VRML_BINDABLE_DIRTY);

		/*!! we were in a 2D mode, setup associated texture !!*/
		if (!prev_cam) {
			switch (layer3d_setup_offscreen(node, st, tr_state, rc.width, rc.height)) {
			case 0:
				goto l3d_exit;
			case 2:
				if (!changed && !(st->visual->camera.flags & CAM_IS_DIRTY) && !st->visual->camera.anim_len) {
					GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Layer3D] No changes found , skipping 3D draw\n"));
					goto layer3d_unchanged_2d;
				}
			default:
				break;
			}
#ifdef GPAC_USE_TINYGL
			if (st->tgl_ctx) ostgl_make_current(st->tgl_ctx, 0);
#endif

			/*note that we don't backup the state as a layer3D cannot be declared in a layer3D*/
			tr_state->layer3d = node;

			rc = st->vp;
			/*setup GL*/
			visual_3d_setup(tr_state->visual);

			visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_PROJECTION);
			visual_3d_matrix_reset(tr_state->visual);
			visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_TEXTURE);
			visual_3d_matrix_reset(tr_state->visual);
			visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_MODELVIEW);
			visual_3d_matrix_reset(tr_state->visual);
		} else {
			visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_PROJECTION);
			visual_3d_matrix_push(tr_state->visual);
			visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_TEXTURE);
			visual_3d_matrix_push(tr_state->visual);
			visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_MODELVIEW);
			visual_3d_matrix_push(tr_state->visual);
		}
		GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Layer3D] Redrawing\n"));

		layer3d_setup_clip(st, tr_state, prev_cam ? 1 : 0, rc);

		cur_lights = tr_state->visual->num_lights;
		/*this will init projection. Note that we're binding the viewpoint in the current pixelMetrics context
		even if the viewpoint was declared in an inline below
		if no previous camera, we're using offscreen rendering, force clear */
		visual_3d_init_draw(tr_state, prev_cam ? 1 : 2);

		visual_3d_check_collisions(tr_state, l->children);
		tr_state->traversing_mode = TRAVERSE_SORT;

		/*shortcut node list*/
		node_list_backup = tr_state->visual->alpha_nodes_to_draw;
		tr_state->visual->alpha_nodes_to_draw = gf_list_new();

		/*reset cull flag*/
		tr_state->cull_flag = 0;
		group_3d_traverse(node, (GroupingNode *)st, tr_state);

		visual_3d_flush_contexts(tr_state->visual, tr_state);

		gf_list_del(tr_state->visual->alpha_nodes_to_draw);
		tr_state->visual->alpha_nodes_to_draw = node_list_backup;

		while (cur_lights < tr_state->visual->num_lights) {
			visual_3d_remove_last_light(tr_state->visual);
		}

		tr_state->traversing_mode = TRAVERSE_SORT;

		if (prev_cam) {
			visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_PROJECTION);
			visual_3d_matrix_pop(tr_state->visual);
			visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_TEXTURE);
			visual_3d_matrix_pop(tr_state->visual);
			visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_MODELVIEW);
			visual_3d_matrix_pop(tr_state->visual);
		}


		/*!! we were in a 2D mode, create drawable context!!*/
		if (!prev_cam) {
			DrawableContext *ctx;
			
			/*with TinyGL we draw directly to the offscreen buffer*/
#ifndef GPAC_USE_TINYGL
			gf_sc_copy_to_stencil(&st->txh);
#else
			if (st->txh.pixelformat==GF_PIXEL_RGBDS) 
				gf_get_tinygl_depth(&st->txh); 
#endif

			if (tr_state->visual->compositor->rasterizer->stencil_texture_modified) 
				tr_state->visual->compositor->rasterizer->stencil_texture_modified(gf_sc_texture_get_stencil(&st->txh) ); 
			gf_sc_texture_set_stencil(&st->txh, gf_sc_texture_get_stencil(&st->txh) );
			changed = 1;

layer3d_unchanged_2d:

			/*restore visual*/
			tr_state->visual = old_visual;
			tr_state->layer3d = NULL;
			tr_state->appear = NULL;
		//	tr_state->camera = prev_cam;

			ctx = drawable_init_context_mpeg4(st->drawable, tr_state);
			if (!ctx) return;
			ctx->aspect.fill_texture = &st->txh;
			ctx->flags |= CTX_NO_ANTIALIAS;
			if (changed) ctx->flags |= CTX_APP_DIRTY;
			if (st->txh.transparent) ctx->flags |= CTX_IS_TRANSPARENT;
			drawable_finalize_sort(ctx, tr_state, NULL);
		}
	}
	/*check picking - we must fall in our 2D clipper except when mvt is grabbed on layer*/
	else if (!gf_node_dirty_get(node)  && (tr_state->traversing_mode==TRAVERSE_PICK)) {
		GF_Ray prev_r;
		SFVec3f start, end;
		SFVec4f res;
		Fixed in_x, in_y;
		Bool do_pick = 0;

		if (!prev_cam) rc = st->vp;

		layer3d_setup_clip(st, tr_state, prev_cam ? 1 : 0, rc);

		if (tr_state->visual->compositor->active_layer==node) {
			do_pick = (tr_state->visual->compositor->grabbed_sensor || tr_state->visual->compositor->navigation_state) ? 1 : 0;
		}

		if (!prev_cam) gf_mx_from_mx2d(&tr_state->model_matrix, &tr_state->transform);
		
		if (!do_pick && !gf_list_count(tr_state->visual->compositor->sensors)) 
			do_pick = gf_sc_pick_in_clipper(tr_state, &st->clip);

		if (!do_pick) goto l3d_exit;

		prev_r = tr_state->ray;

		compositor_get_2d_plane_intersection(&tr_state->ray, &start);

		gf_mx_inverse(&tr_state->model_matrix);
		gf_mx_apply_vec(&tr_state->model_matrix, &start);


		if (tr_state->visual->compositor->visual==tr_state->visual) {
			start.x = gf_mulfix(start.x, tr_state->visual->compositor->scale_x);
			start.y = gf_mulfix(start.y, tr_state->visual->compositor->scale_y);
		} else if (!prev_cam) {
			start.x = gf_muldiv(start.x, st->visual->camera.width, st->clip.width);
			start.y = gf_muldiv(start.y, st->visual->camera.height, st->clip.height);
		}

		visual_3d_setup_projection(tr_state, 1);
		in_x = 2 * gf_divfix(start.x, st->visual->camera.width);
		in_y = 2 * gf_divfix(start.y, st->visual->camera.height);
					
		res.x = in_x; res.y = in_y; res.z = -FIX_ONE; res.q = FIX_ONE;
		gf_mx_apply_vec_4x4(&st->visual->camera.unprojection, &res);
		if (!res.q) goto l3d_exit;
		start.x = gf_divfix(res.x, res.q);
		start.y = gf_divfix(res.y, res.q);
		start.z = gf_divfix(res.z, res.q);

		res.x = in_x; res.y = in_y; res.z = FIX_ONE; res.q = FIX_ONE;
		gf_mx_apply_vec_4x4(&st->visual->camera.unprojection, &res);
		if (!res.q) goto l3d_exit;
		end.x = gf_divfix(res.x, res.q);
		end.y = gf_divfix(res.y, res.q);
		end.z = gf_divfix(res.z, res.q);
		tr_state->ray = gf_ray(start, end);

		GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Layer3D] Picking: cast ray\n\tOrigin %.4f %.4f %.4f - End %.4f %.4f %.4f\n\tDir %.4f %.4f %.4f\n", 
			FIX2FLT(tr_state->ray.orig.x), FIX2FLT(tr_state->ray.orig.y), FIX2FLT(tr_state->ray.orig.z),
			FIX2FLT(end.x), FIX2FLT(end.y), FIX2FLT(end.z),
			FIX2FLT(tr_state->ray.dir.x), FIX2FLT(tr_state->ray.dir.y), FIX2FLT(tr_state->ray.dir.z)));

		group_3d_traverse(node, (GroupingNode *)st, tr_state);
		tr_state->ray = prev_r;

		/*store info if navigation allowed - we just override any layer3D picked first since we are picking 2D
		objects*/
		if (tr_state->camera->navigate_mode || (tr_state->camera->navigation_flags & NAV_ANY))
			tr_state->layer3d = node;

		tr_state->traversing_mode = TRAVERSE_PICK;
	}

l3d_exit:
	/*restore camera*/
	tr_state->camera = prev_cam;
	if (prev_cam) visual_3d_set_viewport(tr_state->visual, tr_state->camera->vp);
	tr_state->visual = old_visual;

	/*restore traversing state*/
	tr_state->backgrounds = oldb;
	tr_state->viewpoints = oldv;
	tr_state->fogs = oldf;
	tr_state->navigations = oldn;
	tr_state->bbox = bbox_backup;
	tr_state->is_layer = prev_layer;
	gf_mx_copy(tr_state->model_matrix, model_backup);
	gf_mx2d_copy(tr_state->transform, mx2d_backup);

	/*in case we missed bindables*/
	if (st->first) {
		st->first = 0;
		gf_node_dirty_set(node, 0, 0);
		gf_sc_invalidate(tr_state->visual->compositor, NULL);
	}
}
Ejemplo n.º 24
0
GF_EXPORT
void gf_sc_texture_update_frame(GF_TextureHandler *txh, Bool disable_resync)
{
	u32 size, ts;

	/*already refreshed*/
	if (txh->needs_refresh) return;

	if (!txh->stream) {
		txh->data = NULL;
		return;
	}

	/*should never happen!!*/
	if (txh->needs_release) gf_mo_release_data(txh->stream, 0xFFFFFFFF, 0);

	/*check init flag*/
	if (!(gf_mo_get_flags(txh->stream) & GF_MO_IS_INIT)) {
		/*if we had a texture this means the object has changed - delete texture and force next frame 
		composition (this will take care of OD reuse)*/
		if (txh->tx_io) {
			gf_sc_texture_release(txh);
			txh->data = NULL;
			txh->needs_refresh = 1;
			gf_sc_invalidate(txh->compositor, NULL);
			return;
		}
		if (gf_mo_is_private_media(txh->stream)) {
			setup_texture_object(txh, 1);
			gf_node_dirty_set(txh->owner, 0, 0);
		}
	}
	txh->data = gf_mo_fetch_data(txh->stream, !disable_resync, &txh->stream_finished, &ts, &size);

	/*if no frame or muted don't draw*/
	if (!txh->data || !size) {
		/*TODO - check if this is needed */
		if (txh->flags & GF_SR_TEXTURE_PRIVATE_MEDIA) {
			//txh->needs_refresh = 1;
			gf_sc_invalidate(txh->compositor, NULL);
		}
		return;
	}

	/*if setup and same frame return*/
	if (txh->tx_io && (txh->stream_finished || (txh->last_frame_time==ts)) ) {
		gf_mo_release_data(txh->stream, 0xFFFFFFFF, 0);
		txh->needs_release = 0;
		return;
	}
	txh->needs_release = 1; 
	txh->last_frame_time = ts;
	if (gf_mo_is_muted(txh->stream)) return;

	if (!txh->tx_io) {
		setup_texture_object(txh, 0);
	}

	/*try to push texture on graphics but don't complain if failure*/
	gf_sc_texture_set_data(txh);

	txh->needs_refresh = 1;
	gf_sc_invalidate(txh->compositor, NULL);
}
Ejemplo n.º 25
0
static void camera_changed(GF_Compositor *compositor, GF_Camera *cam)
{
	cam->flags |= CAM_IS_DIRTY;
	gf_sc_invalidate(compositor, NULL);
	if (compositor->active_layer) gf_node_dirty_set(compositor->active_layer, 0, 1);
}
Ejemplo n.º 26
0
static void TraverseViewpoint(GF_Node *node, void *rs, Bool is_destroy)
{
	SFVec3f pos, v1, v2;
	SFRotation ori;
	GF_Matrix mx;
	GF_TraverseState *tr_state = (GF_TraverseState *)rs;
	M_Viewpoint *vp = (M_Viewpoint*) node;
	ViewStack *st = (ViewStack *) gf_node_get_private(node);

	if (is_destroy) {
		DestroyViewStack(node);
		return;
	}
	/*may happen in get_bounds*/
	if (!tr_state->viewpoints) return;
//	if (!tr_state->camera->is_3D) return;

	/*first traverse, bound if needed*/
	if (gf_list_find(tr_state->viewpoints, node) < 0) {
		gf_list_add(tr_state->viewpoints, node);
		assert(gf_list_find(st->reg_stacks, tr_state->viewpoints)==-1);
		gf_list_add(st->reg_stacks, tr_state->viewpoints);

		if (gf_list_get(tr_state->viewpoints, 0) == vp) {
			if (!vp->isBound) Bindable_SetIsBound(node, 1);
		} else {
			if (gf_inline_is_default_viewpoint(node)) Bindable_SetSetBind(node, 1);
		}
		VPCHANGED(tr_state->visual->compositor);
		/*in any case don't draw the first time (since the viewport could have been declared last)*/
		if (tr_state->layer3d) gf_node_dirty_set(tr_state->layer3d, GF_SG_VRML_BINDABLE_DIRTY, 0);
		gf_sc_invalidate(tr_state->visual->compositor, NULL);
	}
	/*not evaluating vp, return*/
	if (tr_state->traversing_mode != TRAVERSE_BINDABLE) {
		/*store model matrix if changed - NOTE: we always have a 1-frame delay between VP used and real world...
		we could remove this by pre-traversing the scene before applying vp, but that would mean 2 scene
		traversals*/
		if ((tr_state->traversing_mode==TRAVERSE_SORT) || (tr_state->traversing_mode==TRAVERSE_GET_BOUNDS) ) {
			if (!gf_mx_equal(&st->world_view_mx, &tr_state->model_matrix)) {
				gf_mx_copy(st->world_view_mx, tr_state->model_matrix);
				gf_node_dirty_set(node, 0, 0);
			}
		}
		return;
	}

	/*not bound or in 2D visual*/
	if (!vp->isBound || !tr_state->navigations) return;

	if (!gf_node_dirty_get(node)) return;
	gf_node_dirty_clear(node, 0);

	/*move to local system*/
	gf_mx_copy(mx, st->world_view_mx);
	gf_mx_add_translation(&mx, vp->position.x, vp->position.y, vp->position.z);
	gf_mx_add_rotation(&mx, vp->orientation.q, vp->orientation.x, vp->orientation.y, vp->orientation.z);
	gf_mx_decompose(&mx, &pos, &v1, &ori, &v2);
	/*get center*/
	v1.x = v1.y = v1.z = 0;
#ifndef GPAC_DISABLE_X3D
	/*X3D specifies examine center*/
	if (gf_node_get_tag(node)==TAG_X3D_Viewpoint) v1 = ((X_Viewpoint *)node)->centerOfRotation;
#endif
	gf_mx_apply_vec(&st->world_view_mx, &v1);
	/*set frustrum param - animate only if not bound last frame and jump false*/
	visual_3d_viewpoint_change(tr_state, node, (!st->prev_was_bound && !vp->jump) ? 1 : 0, vp->fieldOfView, pos, ori, v1);
	st->prev_was_bound = 1;
}
Ejemplo n.º 27
0
GF_EXPORT
Bool gf_mo_get_visual_info(GF_MediaObject *mo, u32 *width, u32 *height, u32 *stride, u32 *pixel_ar, u32 *pixelFormat, Bool *is_flipped)
{
	GF_CodecCapability cap;
	if ((mo->type != GF_MEDIA_OBJECT_VIDEO) && (mo->type!=GF_MEDIA_OBJECT_TEXT)) return GF_FALSE;

	if (width) {
		cap.CapCode = GF_CODEC_WIDTH;
		gf_codec_get_capability(mo->odm->codec, &cap);
		*width = cap.cap.valueInt;
	}
	if (height) {
		cap.CapCode = GF_CODEC_HEIGHT;
		gf_codec_get_capability(mo->odm->codec, &cap);
		*height = cap.cap.valueInt;
	}
	if (mo->type==GF_MEDIA_OBJECT_TEXT) return GF_TRUE;

	if (is_flipped) {
		cap.CapCode = GF_CODEC_FLIP;
		cap.cap.valueInt = 0;
		gf_codec_get_capability(mo->odm->codec, &cap);
		*is_flipped = cap.cap.valueInt ? GF_TRUE : GF_FALSE;
	}

	if (stride) {
		cap.CapCode = GF_CODEC_STRIDE;
		gf_codec_get_capability(mo->odm->codec, &cap);
		*stride = cap.cap.valueInt;
	}
	if (pixelFormat) {
		cap.CapCode = GF_CODEC_PIXEL_FORMAT;
		gf_codec_get_capability(mo->odm->codec, &cap);
		*pixelFormat = cap.cap.valueInt;

		if (mo->odm && mo->odm->parentscene->is_dynamic_scene) {
#ifndef GPAC_DISABLE_VRML
			const char *name = gf_node_get_name(gf_event_target_get_node(gf_mo_event_target_get(mo, 0)));
			if (name && !strcmp(name, "DYN_VIDEO")) {
				const char *opt;
				u32 r, g, b, a;
				M_Background2D *back = (M_Background2D *) gf_sg_find_node_by_name(mo->odm->parentscene->graph, "DYN_BACK");
				if (back) {
					switch (cap.cap.valueInt) {
					case GF_PIXEL_ARGB:
					case GF_PIXEL_RGBA:
					case GF_PIXEL_YUVA:
						opt = gf_cfg_get_key(mo->odm->term->user->config, "Compositor", "BackColor");
						if (!opt) {
							gf_cfg_set_key(mo->odm->term->user->config, "Compositor", "BackColor", "FF999999");
							opt = "FF999999";
						}
						sscanf(opt, "%02X%02X%02X%02X", &a, &r, &g, &b);
						back->backColor.red = INT2FIX(r)/255;
						back->backColor.green = INT2FIX(g)/255;
						back->backColor.blue = INT2FIX(b)/255;
						break;
					default:
						back->backColor.red = back->backColor.green = back->backColor.blue = 0;
						break;
					}
					gf_node_dirty_set((GF_Node *)back, 0, GF_TRUE);
				}
			}
#endif
		}
	}
	/*get PAR settings*/
	if (pixel_ar) {
		cap.CapCode = GF_CODEC_PAR;
		gf_codec_get_capability(mo->odm->codec, &cap);
		*pixel_ar = cap.cap.valueInt;
		if (! (*pixel_ar & 0x0000FFFF)) *pixel_ar = 0;
		if (! (*pixel_ar & 0xFFFF0000)) *pixel_ar = 0;

		/**/
		if (! *pixel_ar) {
			GF_Channel *ch;
			GF_NetworkCommand com;
			com.base.command_type = GF_NET_CHAN_GET_PIXEL_AR;
			ch = (GF_Channel *)gf_list_get(mo->odm->channels, 0);
			if (!ch) return GF_FALSE;

			com.base.on_channel = ch;
			com.par.hSpacing = com.par.vSpacing = 0;
			if (gf_term_service_command(ch->service, &com) == GF_OK) {
				if ((com.par.hSpacing>65535) || (com.par.vSpacing>65535)) {
					com.par.hSpacing>>=16;
					com.par.vSpacing>>=16;
				}
				if (com.par.hSpacing|| com.par.vSpacing)
					*pixel_ar = (com.par.hSpacing<<16) | com.par.vSpacing;
			}
		}
Ejemplo n.º 28
0
static void svg_traverse_textArea(GF_Node *node, void *rs, Bool is_destroy)
{
	SVGPropertiesPointers backup_props;
	u32 backup_flags;
	GF_Matrix mx3d;
	GF_Matrix2D backup_matrix;
	DrawableContext *ctx = NULL;
	GF_ChildNodeItem *child;
	SVG_TextStack *st = (SVG_TextStack *)gf_node_get_private(node);
	GF_TraverseState *tr_state = (GF_TraverseState *)rs;
	SVG_Element *text = (SVG_Element *)node;
	SVGAllAttributes atts;

	if (is_destroy) {
		drawable_del(st->drawable);
		svg_reset_text_stack(st);
		gf_list_del(st->spans);
		gf_free(st);
		return;
	}

	if (tr_state->traversing_mode==TRAVERSE_DRAW_2D) {
		svg_text_draw_2d(st, tr_state);
		return;
	}
	else if (tr_state->traversing_mode==TRAVERSE_GET_TEXT) {
		tr_state->text_parent = node;
		gf_font_spans_get_selection(node, st->spans, tr_state);
		/*and browse children*/
		child = ((GF_ParentNode *) text)->children;
		while (child) {
			switch  (gf_node_get_tag(child->node)) {
			case TAG_SVG_tspan:
			case TAG_SVG_a:
				gf_node_traverse(child->node, tr_state);
				break;
			}
			child = child->next;
		}
		tr_state->text_parent = NULL;
		return;
	}


	gf_svg_flatten_attributes(text, &atts);
	if (!compositor_svg_traverse_base(node, &atts, tr_state, &backup_props, &backup_flags))
		return;

	tr_state->text_parent = node;
	tr_state->in_svg_text_area++;

	if (tr_state->traversing_mode==TRAVERSE_PICK) {
		if (*tr_state->svg_props->pointer_events!=SVG_POINTEREVENTS_NONE) {
			compositor_svg_apply_local_transformation(tr_state, &atts, &backup_matrix, &mx3d);
			gf_font_spans_pick(node, st->spans, tr_state, &st->bounds, GF_TRUE, st->drawable);

			/*and browse children*/
			child = ((GF_ParentNode *) node)->children;
			while (child) {
				gf_node_traverse(child->node, tr_state);
				child = child->next;
			}
			compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, &mx3d);
			memcpy(tr_state->svg_props, &backup_props, sizeof(SVGPropertiesPointers));
			tr_state->svg_flags = backup_flags;
		}
		tr_state->in_svg_text_area--;
		tr_state->text_parent = NULL;
		return;
	}

	compositor_svg_apply_local_transformation(tr_state, &atts, &backup_matrix, &mx3d);

	if ( (st->prev_size != tr_state->svg_props->font_size->value) ||
	        (st->prev_flags != *tr_state->svg_props->font_style) ||
	        (st->prev_anchor != *tr_state->svg_props->text_anchor) ||
	        (gf_node_dirty_get(node) & (GF_SG_SVG_GEOMETRY_DIRTY | GF_SG_CHILD_DIRTY) )
	        || tr_state->visual->compositor->reset_fonts
	   ) {
		u32 mode;

		child = ((GF_ParentNode *) text)->children;

		svg_reset_text_stack(st);
		gf_node_dirty_clear(node, 0);
		drawable_mark_modified(st->drawable, tr_state);
		drawable_reset_path(st->drawable);

		tr_state->max_length = (atts.width ? (atts.width->type == SVG_NUMBER_AUTO ? FIX_MAX : atts.width->value) : FIX_MAX);
		tr_state->max_height = (atts.height ? (atts.height->type == SVG_NUMBER_AUTO ? FIX_MAX : atts.height->value) : FIX_MAX);
		tr_state->base_x = (atts.x ? atts.x->value : 0);
		tr_state->base_y = (atts.y ? atts.y->value : 0);
		/*init the xml:space algo*/
		tr_state->last_char_type = 0;
		/*let it initialize from first font*/
		tr_state->line_spacing = 0;
		tr_state->text_end_x = 0;
		tr_state->text_end_y = (tr_state->svg_props->line_increment->type == SVG_NUMBER_AUTO ? 0 : tr_state->svg_props->line_increment->value);

		tr_state->x_anchors = gf_list_new();

		if (tr_state->svg_props->font_size && (tr_state->svg_props->font_size->value <= tr_state->max_height)) {
			Fixed remain;
			u32 c, refresh_to_idx, prev_refresh;
			/*switch to bounds mode, and recompute children*/
			mode = tr_state->traversing_mode;
			tr_state->traversing_mode = TRAVERSE_GET_BOUNDS;

			prev_refresh = tr_state->refresh_children_bounds;
			tr_state->refresh_children_bounds = 0;
			c = refresh_to_idx = 0;
			child = ((GF_ParentNode *) text)->children;
			while (child) {
				c++;
				switch  (gf_node_get_tag(child->node)) {
				case TAG_DOMText:
					svg_traverse_dom_text_area(child->node, &atts, tr_state, st->spans);
					break;
				case TAG_SVG_tspan:
					/*mark tspan as dirty to force rebuild*/
					gf_node_dirty_set(child->node, 0, GF_FALSE);
					gf_node_traverse(child->node, tr_state);
					break;
				case TAG_SVG_switch:
				case TAG_SVG_a:
				case TAG_SVG_tbreak:
					gf_node_traverse(child->node, tr_state);
					break;
				default:
					break;
				}
				if (tr_state->refresh_children_bounds) {
					tr_state->refresh_children_bounds=0;
					refresh_to_idx=c;
				}

				child=child->next;
			}
			st->prev_size = tr_state->svg_props->font_size->value;
			st->prev_flags = *tr_state->svg_props->font_style;
			st->prev_anchor = *tr_state->svg_props->text_anchor;

			svg_text_area_reset_state(tr_state);
			gf_list_del(tr_state->x_anchors);
			tr_state->x_anchors = NULL;

			remain = 0;
			if (tr_state->refresh_children_bounds) {
				refresh_to_idx = (u32) -1;
				tr_state->base_shift = 0;
			}
			if (tr_state->svg_props->display_align) {
				switch (*tr_state->svg_props->display_align) {
				case SVG_DISPLAYALIGN_CENTER:
					remain = (tr_state->max_height-tr_state->text_end_y) / 2;
					break;
				case SVG_DISPLAYALIGN_AFTER:
					remain = tr_state->max_height - tr_state->text_end_y;
					break;
				default:
					remain = 0;
					break;
				}
				if (remain<0) remain=0;
				if (remain) {
					refresh_to_idx = (u32) -1;
					tr_state->base_shift = remain;
					svg_text_area_shift_bounds(st, tr_state);
				}
			}

			if (refresh_to_idx) {
				tr_state->refresh_children_bounds=1;
				/*and retraverse in case of bounds adjustements*/
				child = ((GF_ParentNode *) text)->children;
				while (child) {
					switch (gf_node_get_tag(child->node)) {
					case TAG_DOMText:
						break;
					case TAG_SVG_tspan:
					case TAG_SVG_switch:
					case TAG_SVG_a:
						gf_node_traverse(child->node, tr_state);
						break;
					default:
						break;
					}
					child=child->next;
					refresh_to_idx--;
					if (!refresh_to_idx) break;
				}
				tr_state->base_shift = 0;
			}
			tr_state->traversing_mode = mode;
			tr_state->refresh_children_bounds = prev_refresh;
		}
		svg_update_bounds(st);
	}

	if (tr_state->traversing_mode == TRAVERSE_GET_BOUNDS) {
		if (!compositor_svg_is_display_off(tr_state->svg_props))
			tr_state->bounds = st->bounds;
	} else if ( (tr_state->traversing_mode == TRAVERSE_SORT)
	            && !compositor_svg_is_display_off(tr_state->svg_props)
	            && (*(tr_state->svg_props->visibility) != SVG_VISIBILITY_HIDDEN)
	          ) {

		ctx = drawable_init_context_svg(st->drawable, tr_state);
		if (ctx) svg_finalize_sort(ctx, st, tr_state);

		child = ((GF_ParentNode *) text)->children;
		while (child) {
			switch  (gf_node_get_tag(child->node)) {
			case TAG_DOMText:
				break;
			case TAG_SVG_tspan:
			case TAG_SVG_switch:
			case TAG_SVG_a:
				gf_node_traverse(child->node, tr_state);
				break;
			default:
				break;
			}
			child = child->next;
		}
	}
	tr_state->in_svg_text_area--;
	tr_state->text_parent = NULL;


	compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, &mx3d);
	memcpy(tr_state->svg_props, &backup_props, sizeof(SVGPropertiesPointers));
	tr_state->svg_flags = backup_flags;
}
Ejemplo n.º 29
0
static void TraverseNavigationInfo(GF_Node *node, void *rs, Bool is_destroy)
{
	u32 i;
#ifndef GPAC_DISABLE_3D
	u32 nb_select_mode;
	SFVec3f start, end;
	Fixed scale;
	ViewStack *st = (ViewStack *) gf_node_get_private(node);
#endif
	GF_TraverseState *tr_state = (GF_TraverseState *)rs;
	M_NavigationInfo *ni = (M_NavigationInfo *) node;

	if (is_destroy) {
		DestroyViewStack(node);
		return;
	}
#ifdef GPAC_DISABLE_3D

	/*FIXME, we only deal with one node, no bind stack for the current time*/
	for (i=0; i<ni->type.count; i++) {
		if (ni->type.vals[i] && !stricmp(ni->type.vals[i], "NONE")) {
			tr_state->visual->compositor->navigation_disabled = 1;
		}
	}
#else

	if (!tr_state->navigations) return;

	/*first traverse, bound if needed*/
	if (gf_list_find(tr_state->navigations, node) < 0) {
		gf_list_add(tr_state->navigations, node);
		if (gf_list_get(tr_state->navigations, 0) == ni) {
			if (!ni->isBound) Bindable_SetIsBound(node, 1);
		}
		assert(gf_list_find(st->reg_stacks, tr_state->navigations)==-1);
		gf_list_add(st->reg_stacks, tr_state->navigations);
		gf_mx_copy(st->world_view_mx, tr_state->model_matrix);
		/*in any case don't draw the first time*/
		gf_sc_invalidate(tr_state->visual->compositor, NULL);
		return;
	}
	/*not bound*/
	if (!ni->isBound) return;
	/*not evaluating, return*/
	if (tr_state->traversing_mode != TRAVERSE_BINDABLE) {
		if ((tr_state->traversing_mode==TRAVERSE_SORT) || (tr_state->traversing_mode==TRAVERSE_GET_BOUNDS) ) {
			if (!gf_mx_equal(&st->world_view_mx, &tr_state->model_matrix)) {
				gf_mx_copy(st->world_view_mx, tr_state->model_matrix);
				gf_node_dirty_set(node, 0, 0);
			}
		}
		return;
	}

	if (!gf_node_dirty_get(node)) return;
	gf_node_dirty_clear(node, 0);

	nb_select_mode = 0;
	tr_state->camera->navigation_flags = 0;
	tr_state->camera->navigate_mode = 0;
	for (i=0; i<ni->type.count; i++) {
		if (ni->type.vals[i] && !stricmp(ni->type.vals[i], "ANY")) tr_state->camera->navigation_flags |= NAV_ANY;
		else {
			nb_select_mode++;
		}

		if (!tr_state->camera->navigate_mode) {
			if (ni->type.vals[i] && !stricmp(ni->type.vals[i], "NONE")) tr_state->camera->navigate_mode = GF_NAVIGATE_NONE;
			else if (ni->type.vals[i] && !stricmp(ni->type.vals[i], "WALK")) tr_state->camera->navigate_mode = GF_NAVIGATE_WALK;
			else if (ni->type.vals[i] && !stricmp(ni->type.vals[i], "EXAMINE")) tr_state->camera->navigate_mode = GF_NAVIGATE_EXAMINE;
			else if (ni->type.vals[i] && !stricmp(ni->type.vals[i], "FLY")) tr_state->camera->navigate_mode = GF_NAVIGATE_FLY;
			else if (ni->type.vals[i] && !stricmp(ni->type.vals[i], "VR")) tr_state->camera->navigate_mode = GF_NAVIGATE_VR;
		}
	}
	if (nb_select_mode>1) tr_state->camera->navigation_flags |= NAV_SELECTABLE;

	if (ni->headlight) tr_state->camera->navigation_flags |= NAV_HEADLIGHT;

	start.x = start.y = start.z = 0;
	end.x = end.y = 0;
	end.z = FIX_ONE;
	gf_mx_apply_vec(&st->world_view_mx, &start);
	gf_mx_apply_vec(&st->world_view_mx, &end);
	gf_vec_diff(end, end, start);
	scale = gf_vec_len(end);

	tr_state->camera->speed = gf_mulfix(scale, ni->speed);
	tr_state->camera->visibility = gf_mulfix(scale, ni->visibilityLimit);
	if (ni->avatarSize.count) tr_state->camera->avatar_size.x = gf_mulfix(scale, ni->avatarSize.vals[0]);
	if (ni->avatarSize.count>1) tr_state->camera->avatar_size.y = gf_mulfix(scale, ni->avatarSize.vals[1]);
	if (ni->avatarSize.count>2) tr_state->camera->avatar_size.z = gf_mulfix(scale, ni->avatarSize.vals[2]);

	if (0 && tr_state->pixel_metrics) {
		u32 s = MAX(tr_state->visual->width, tr_state->visual->height);
		s /= 2;
//		tr_state->camera->speed = ni->speed;
		tr_state->camera->visibility *= s;
		tr_state->camera->avatar_size.x *= s;
		tr_state->camera->avatar_size.y *= s;
		tr_state->camera->avatar_size.z *= s;
	}
#endif

}
Ejemplo n.º 30
0
GF_EXPORT
void gf_sc_texture_update_frame(GF_TextureHandler *txh, Bool disable_resync)
{
	u32 size, ts;

	/*already refreshed*/
	if (txh->needs_refresh) return;

	if (!txh->stream) {
		txh->data = NULL;
		return;
	}

	/*should never happen!!*/
	if (txh->needs_release) gf_mo_release_data(txh->stream, 0xFFFFFFFF, 0);

	/*check init flag*/
	if (!(gf_mo_get_flags(txh->stream) & GF_MO_IS_INIT)) {
		/*if we had a texture this means the object has changed - delete texture and resetup. Do not skip
		texture update as this may lead to an empty rendering pass (blank frame for this object), especially in DASH*/
		if (txh->tx_io) {
			gf_sc_texture_release(txh);
			txh->data = NULL;
			txh->needs_refresh = 1;
		}
		if (gf_mo_is_private_media(txh->stream)) {
			setup_texture_object(txh, 1);
			gf_node_dirty_set(txh->owner, 0, 0);
		}
	}
	txh->data = gf_mo_fetch_data(txh->stream, !disable_resync, &txh->stream_finished, &ts, &size);

	/*if no frame or muted don't draw*/
	if (!txh->data || !size) {
		GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("No output frame available\n"));
		/*TODO - check if this is needed */
		if (txh->flags & GF_SR_TEXTURE_PRIVATE_MEDIA) {
			//txh->needs_refresh = 1;
			gf_sc_invalidate(txh->compositor, NULL);
		}
		return;
	}

	/*if setup and same frame return*/
	if (txh->tx_io && (txh->stream_finished || (txh->last_frame_time==ts)) ) {
		gf_mo_release_data(txh->stream, 0xFFFFFFFF, 0);
		txh->needs_release = 0;
		return;
	}
	txh->needs_release = 1;
	txh->last_frame_time = ts;
	if (gf_mo_is_muted(txh->stream)) return;

	if (!txh->tx_io) {
		setup_texture_object(txh, 0);
	}

	/*try to push texture on graphics but don't complain if failure*/
	gf_sc_texture_set_data(txh);

	txh->needs_refresh = 1;
	gf_sc_invalidate(txh->compositor, NULL);
}