示例#1
0
void compositor_3d_draw_bitmap(Drawable *stack, DrawAspect2D *asp, GF_TraverseState *tr_state, Fixed width, Fixed height, Fixed bmp_scale_x, Fixed bmp_scale_y)
{
	u8 alpha;
	GF_TextureHandler *txh;
	GF_Compositor *compositor = tr_state->visual->compositor;

	if (!asp->fill_texture)
		return;
	txh = asp->fill_texture;
	if (!txh || !txh->tx_io || !txh->width || !txh->height)
		return;

	if (((txh->pixelformat==GF_PIXEL_RGBD) || (txh->pixelformat==GF_PIXEL_YUVD))) {
		if (compositor->depth_gl_type) {
			if (txh->data && gf_sc_texture_convert(txh) )
				visual_3d_point_sprite(tr_state->visual, stack, txh, tr_state);
			return;
		}
	}

	alpha = GF_COL_A(asp->fill_color);
	/*THIS IS A HACK, will not work when setting filled=0, transparency and XLineProps*/
	if (!alpha) alpha = GF_COL_A(asp->line_color);

	visual_3d_set_state(tr_state->visual, V3D_STATE_LIGHT, GF_FALSE);
	visual_3d_enable_antialias(tr_state->visual, GF_FALSE);
	if (alpha && (alpha != 0xFF)) {
		visual_3d_set_material_2d_argb(tr_state->visual, GF_COL_ARGB(alpha, 0xFF, 0xFF, 0xFF));
		gf_sc_texture_set_blend_mode(txh, TX_MODULATE);
	} else if (gf_sc_texture_is_transparent(txh)) {
		gf_sc_texture_set_blend_mode(txh, TX_REPLACE);
	} else {
		visual_3d_set_state(tr_state->visual, V3D_STATE_BLEND, GF_FALSE);
	}
	/*ignore texture transform for bitmap*/
	tr_state->mesh_num_textures = gf_sc_texture_enable(txh, NULL);
	if (tr_state->mesh_num_textures) {
		/*we must check the w & h passed are correct because of bitmap node initialization*/
		if (width && height) {
			if (!stack->mesh) {
				SFVec2f size;
				size.x = width;
				size.y = height;

				stack->mesh = new_mesh();
				mesh_new_rectangle(stack->mesh, size, NULL, GF_FALSE);
			}
		}
		if (stack->mesh) {
#ifdef GF_SR_USE_DEPTH
			if (tr_state->depth_offset) {
				GF_Matrix mx;
				Fixed offset;
				Fixed disp_depth = (compositor->display_depth<0) ? INT2FIX(tr_state->visual->height) : INT2FIX(compositor->display_depth);
				if (disp_depth) {
					GF_Matrix bck_mx;
					if (!tr_state->pixel_metrics) disp_depth = gf_divfix(disp_depth, tr_state->min_hsize);
					gf_mx_init(mx);
					/*add recalibration by the scene*/
					offset = tr_state->depth_offset;
					if (tr_state->visual->depth_vp_range) {
						offset = gf_divfix(offset, tr_state->visual->depth_vp_range/2);
					}
					gf_mx_add_translation(&mx, 0, 0, gf_mulfix(offset, disp_depth/2) );

					gf_mx_copy(bck_mx, tr_state->model_matrix);
					gf_mx_add_matrix(&tr_state->model_matrix, &mx);
					visual_3d_mesh_paint(tr_state, stack->mesh);
					gf_mx_copy(tr_state->model_matrix, bck_mx);
				} else {
					visual_3d_mesh_paint(tr_state, stack->mesh);
				}
			} else
#endif
				visual_3d_mesh_paint(tr_state, stack->mesh);
		}
		gf_sc_texture_disable(txh);
		tr_state->mesh_num_textures = 0;
	}
}
示例#2
0
void compositor_3d_draw_bitmap(Drawable *stack, DrawAspect2D *asp, GF_TraverseState *tr_state, Fixed width, Fixed height, Fixed bmp_scale_x, Fixed bmp_scale_y)
{
	u8 alpha;
#if !defined(GPAC_USE_OGL_ES) && !defined(GPAC_USE_TINYGL)
	Fixed x, y;
	Fixed sx, sy;
	char *data;
	u32 format;
#endif
	GF_TextureHandler *txh;
	GF_Compositor *compositor = tr_state->visual->compositor;
	Bool use_texture = !compositor->bitmap_use_pixels;

	if (!asp->fill_texture)
		return;
	txh = asp->fill_texture;
	if (!txh || !txh->tx_io || !txh->width || !txh->height)
		return;

	if (((txh->pixelformat==GF_PIXEL_RGBD) || (txh->pixelformat==GF_PIXEL_YUVD))) {
		if (compositor->depth_gl_type) {
			if (txh->data && gf_sc_texture_convert(txh) )
				visual_3d_point_sprite(tr_state->visual, stack, txh, tr_state);
			return;
		} else {
			use_texture = 1;
		}
	}

	alpha = GF_COL_A(asp->fill_color);
	/*THIS IS A HACK, will not work when setting filled=0, transparency and XLineProps*/
	if (!alpha) alpha = GF_COL_A(asp->line_color);

	/*texture is available in hw, use it - if blending, force using texture*/
	if (!gf_sc_texture_needs_reload(txh) || (alpha != 0xFF) || use_texture
#ifdef GF_SR_USE_DEPTH
		|| tr_state->depth_offset
#endif
		) {
		visual_3d_set_state(tr_state->visual, V3D_STATE_LIGHT, 0);
		visual_3d_enable_antialias(tr_state->visual, 0);
		if (alpha && (alpha != 0xFF)) {
			visual_3d_set_material_2d_argb(tr_state->visual, GF_COL_ARGB(alpha, 0xFF, 0xFF, 0xFF));
			gf_sc_texture_set_blend_mode(txh, TX_MODULATE);
		} else if (gf_sc_texture_is_transparent(txh)) {
			gf_sc_texture_set_blend_mode(txh, TX_REPLACE);
		} else {
			visual_3d_set_state(tr_state->visual, V3D_STATE_BLEND, 0);
		}
		/*ignore texture transform for bitmap*/
 		tr_state->mesh_num_textures = gf_sc_texture_enable(txh, NULL);
		if (tr_state->mesh_num_textures) {
			/*we must check the w & h passed are correct because of bitmap node initialization*/
			if (width && height) {
				if (!stack->mesh) {
					SFVec2f size;
					size.x = width;
					size.y = height;

					stack->mesh = new_mesh();
					mesh_new_rectangle(stack->mesh, size, NULL, 0);
				}
			}
			if (stack->mesh) {
#ifdef GF_SR_USE_DEPTH
				if (tr_state->depth_offset) {
					GF_Matrix mx;
					Fixed offset;
					Fixed disp_depth = (compositor->display_depth<0) ? INT2FIX(tr_state->visual->height) : INT2FIX(compositor->display_depth);
					if (disp_depth) {
						if (!tr_state->pixel_metrics) disp_depth = gf_divfix(disp_depth, tr_state->min_hsize);
						gf_mx_init(mx);
						/*add recalibration by the scene*/
						offset = tr_state->depth_offset;
						if (tr_state->visual->depth_vp_range) {
							offset = gf_divfix(offset, tr_state->visual->depth_vp_range/2);
						}
						gf_mx_add_translation(&mx, 0, 0, gf_mulfix(offset, disp_depth/2) );

						visual_3d_matrix_push(tr_state->visual);
						visual_3d_matrix_add(tr_state->visual, mx.m);
						visual_3d_mesh_paint(tr_state, stack->mesh);
						visual_3d_matrix_pop(tr_state->visual);
					} else {
						visual_3d_mesh_paint(tr_state, stack->mesh);
					}
				} else
#endif
					visual_3d_mesh_paint(tr_state, stack->mesh);
			}
 			gf_sc_texture_disable(txh);
			tr_state->mesh_num_textures = 0;
			return;
		}
	}

	/*otherwise use glDrawPixels*/
#if !defined(GPAC_USE_OGL_ES) && !defined(GPAC_USE_TINYGL)
	data = gf_sc_texture_get_data(txh, &format);
	if (!data) return;

	x = INT2FIX(txh->width) / -2;
	y = INT2FIX(txh->height) / 2;

	{
	Fixed g[16];

	sx = bmp_scale_x; if (sx<0) sx = FIX_ONE;
	sy = bmp_scale_y; if (sy<0) sy = FIX_ONE;
#ifndef GPAC_DISABLE_VRML
	compositor_adjust_scale(txh->owner, &sx, &sy);
#endif

	/*add top level scale if any*/
	sx = gf_mulfix(sx, compositor->scale_x);
	sy = gf_mulfix(sy, compositor->scale_y);

	/*get & apply current transform scale*/
	visual_3d_matrix_get(tr_state->visual, V3D_MATRIX_MODELVIEW, g);

	if (g[0]<0) g[0] *= -FIX_ONE;
	if (g[5]<0) g[5] *= -FIX_ONE;
	sx = gf_mulfix(sx, g[0]);
	sy = gf_mulfix(sy, g[5]);
	x = gf_mulfix(x, sx);
	y = gf_mulfix(y, sy);

	}
	visual_3d_draw_image(tr_state->visual, x, y, txh->width, txh->height, format, data, sx, sy);
#endif
}
示例#3
0
static void svg_traverse_bitmap(GF_Node *node, void *rs, Bool is_destroy)
{
	Fixed cx, cy, angle;
	/*video stack is just an extension of image stack, type-casting is OK*/
	SVG_video_stack *stack = (SVG_video_stack*)gf_node_get_private(node);
	GF_TraverseState *tr_state = (GF_TraverseState *)rs;
	SVGPropertiesPointers backup_props;
	u32 backup_flags;
	GF_Matrix2D backup_matrix;
	GF_Matrix mx_3d;
	DrawableContext *ctx;
	SVGAllAttributes all_atts;


	if (is_destroy) {
		gf_sc_texture_destroy(&stack->txh);
		gf_sg_mfurl_del(stack->txurl);

		drawable_del(stack->graph);
		if (stack->audio) {
			gf_node_unregister(stack->audio, NULL);
		}
		gf_free(stack);
		return;
	} 


	/*TRAVERSE_DRAW is NEVER called in 3D mode*/
	if (tr_state->traversing_mode==TRAVERSE_DRAW_2D) {
		SVG_Draw_bitmap(tr_state);
		return;
	}
	else if (tr_state->traversing_mode==TRAVERSE_PICK) {
		svg_drawable_pick(node, stack->graph, tr_state);
		return;
	}

	/*flatten attributes and apply animations + inheritance*/
	gf_svg_flatten_attributes((SVG_Element *)node, &all_atts);
	if (!compositor_svg_traverse_base(node, &all_atts, (GF_TraverseState *)rs, &backup_props, &backup_flags))
		return;

	if (gf_node_dirty_get(node) & GF_SG_SVG_XLINK_HREF_DIRTY) {
		gf_term_get_mfurl_from_xlink(node, &stack->txurl);
		stack->txh.width = stack->txh.height = 0;
		
		/*remove associated audio if any*/
		if (stack->audio) {
			svg_audio_smil_evaluate_ex(NULL, 0, SMIL_TIMING_EVAL_REMOVE, stack->audio, stack->txh.owner);
			gf_node_unregister(stack->audio, NULL);
			stack->audio = NULL;
		}
		stack->audio_dirty = GF_TRUE;
		
		if (stack->txurl.count) svg_play_texture(stack, &all_atts);
		gf_node_dirty_clear(node, GF_SG_SVG_XLINK_HREF_DIRTY);
	}

	if (gf_node_dirty_get(node)) {
		/*do not clear dirty state until the image is loaded*/
		if (stack->txh.width) {
			gf_node_dirty_clear(node, 0);
			SVG_Build_Bitmap_Graph((SVG_video_stack*)gf_node_get_private(node), tr_state);
		}
		
	} 

	if (tr_state->traversing_mode == TRAVERSE_GET_BOUNDS) {
		if (!compositor_svg_is_display_off(tr_state->svg_props)) {
			gf_path_get_bounds(stack->graph->path, &tr_state->bounds);
			compositor_svg_apply_local_transformation(tr_state, &all_atts, &backup_matrix, &mx_3d);

			if (svg_video_get_transform_behavior(tr_state, &all_atts, &cx, &cy, &angle)) {
				GF_Matrix2D mx;
				tr_state->bounds.width = INT2FIX(stack->txh.width);
				tr_state->bounds.height = INT2FIX(stack->txh.height);
				tr_state->bounds.x = cx - tr_state->bounds.width/2;
				tr_state->bounds.y = cy + tr_state->bounds.height/2;
				gf_mx2d_init(mx);
				gf_mx2d_add_rotation(&mx, 0, 0, angle);
				gf_mx2d_apply_rect(&mx, &tr_state->bounds);
			} else {
				gf_mx2d_apply_rect(&tr_state->transform, &tr_state->bounds);
			}

			compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, &mx_3d);
		}
	} else if (tr_state->traversing_mode == TRAVERSE_SORT) {
		if (!compositor_svg_is_display_off(tr_state->svg_props) && ( *(tr_state->svg_props->visibility) != SVG_VISIBILITY_HIDDEN) ) {
			GF_Matrix mx_bck;
			Bool restore_mx = GF_FALSE;

			compositor_svg_apply_local_transformation(tr_state, &all_atts, &backup_matrix, &mx_3d);

			ctx = drawable_init_context_svg(stack->graph, tr_state);
			if (!ctx || !ctx->aspect.fill_texture ) return;

			if (svg_video_get_transform_behavior(tr_state, &all_atts, &cx, &cy, &angle)) {
				drawable_reset_path(stack->graph);
				gf_path_add_rect_center(stack->graph->path, cx, cy, INT2FIX(stack->txh.width), INT2FIX(stack->txh.height));

				gf_mx2d_copy(mx_bck, tr_state->transform);
				restore_mx = GF_TRUE;
				
				gf_mx2d_init(tr_state->transform);
				gf_mx2d_add_rotation(&tr_state->transform, cx, cy, angle);
			}

			/*even if set this is not true*/
			ctx->aspect.pen_props.width = 0;
			ctx->flags |= CTX_NO_ANTIALIAS;

			/*if rotation, transparent*/
			ctx->flags &= ~CTX_IS_TRANSPARENT;
			if (ctx->transform.m[1] || ctx->transform.m[3]) {
				ctx->flags |= CTX_IS_TRANSPARENT;
				ctx->flags &= ~CTX_NO_ANTIALIAS;
			}
			else if (ctx->aspect.fill_texture->transparent) 
				ctx->flags |= CTX_IS_TRANSPARENT;
			else if (tr_state->svg_props->opacity && (tr_state->svg_props->opacity->type==SVG_NUMBER_VALUE) && (tr_state->svg_props->opacity->value!=FIX_ONE)) {
				ctx->flags = CTX_IS_TRANSPARENT;
				ctx->aspect.fill_color = GF_COL_ARGB(FIX2INT(0xFF * tr_state->svg_props->opacity->value), 0, 0, 0);
			}

#ifndef GPAC_DISABLE_3D
			if (tr_state->visual->type_3d) {
				if (!stack->graph->mesh) {
					stack->graph->mesh = new_mesh();
					mesh_from_path(stack->graph->mesh, stack->graph->path);
				}
				compositor_3d_draw_bitmap(stack->graph, &ctx->aspect, tr_state, 0, 0, FIX_ONE, FIX_ONE);
				ctx->drawable = NULL;
			} else 
#endif
			{
				drawable_finalize_sort(ctx, tr_state, NULL);
			}

			if (restore_mx) gf_mx2d_copy(tr_state->transform, mx_bck);
			compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, &mx_3d);
		}
	}
	if (stack->audio) svg_traverse_audio_ex(stack->audio, rs, GF_FALSE, tr_state->svg_props);

	memcpy(tr_state->svg_props, &backup_props, sizeof(SVGPropertiesPointers));
	tr_state->svg_flags = backup_flags;
}
示例#4
0
GF_Err gf_sr_set_scene(GF_Renderer *sr, GF_SceneGraph *scene_graph)
{
	u32 width, height;
	Bool do_notif;

	if (!sr) return GF_BAD_PARAM;

	gf_sr_lock(sr, 1);
	GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, (scene_graph ? "[Render] Attaching new scene\n" : "[Render] Detaching scene\n"));

	if (sr->audio_renderer && (sr->scene != scene_graph)) {
		GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render] Reseting audio render\n"));
		gf_sr_ar_reset(sr->audio_renderer);
	}

#ifdef GF_SR_EVENT_QUEUE
	GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render] Reseting event queue\n"));
	gf_mx_p(sr->ev_mx);
	while (gf_list_count(sr->events)) {
		GF_Event *ev = (GF_Event*)gf_list_get(sr->events, 0);
		gf_list_rem(sr->events, 0);
		free(ev);
	}
#endif
	
	GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render] Reseting render module\n"));
	/*reset main surface*/
	sr->visual_renderer->SceneReset(sr->visual_renderer);

	/*set current graph*/
	sr->scene = scene_graph;
	do_notif = 0;
	if (scene_graph) {
#ifndef GPAC_DISABLE_SVG
		SVG_Length *w, *h;
#endif
		const char *opt;
		Bool is_svg = 0;
		u32 tag;
		GF_Node *top_node;
		Bool had_size_info = sr->has_size_info;
		/*get pixel size if any*/
		gf_sg_get_scene_size_info(sr->scene, &width, &height);
		sr->has_size_info = (width && height) ? 1 : 0;
		if (sr->has_size_info != had_size_info) sr->scene_width = sr->scene_height = 0;

		/*default back color is black*/
		if (! (sr->user->init_flags & GF_TERM_WINDOWLESS)) sr->back_color = 0xFF000000;

		top_node = gf_sg_get_root_node(sr->scene);
		tag = 0;
		if (top_node) tag = gf_node_get_tag(top_node);

#ifndef GPAC_DISABLE_SVG
		w = h = NULL;
		if ((tag>=GF_NODE_RANGE_FIRST_SVG) && (tag<=GF_NODE_RANGE_LAST_SVG)) {
			GF_FieldInfo info;
			is_svg = 1;
			if (gf_svg_get_attribute_by_tag(top_node, TAG_SVG_ATT_width, 0, 0, &info)==GF_OK) 
				w = info.far_ptr;
			if (gf_svg_get_attribute_by_tag(top_node, TAG_SVG_ATT_height, 0, 0, &info)==GF_OK) 
				h = info.far_ptr;
		}
#ifdef GPAC_ENABLE_SVG_SA
		else if ((tag>=GF_NODE_RANGE_FIRST_SVG_SA) && (tag<=GF_NODE_RANGE_LAST_SVG_SA)) {
			SVG_SA_svgElement *root = (SVG_SA_svgElement *) top_node;
			is_svg = 1;
			w = &root->width;
			h = &root->height;
		}
#endif
#ifdef GPAC_ENABLE_SVG_SANI
		else if ((tag>=GF_NODE_RANGE_FIRST_SVG_SANI) && (tag<=GF_NODE_RANGE_LAST_SVG_SANI)) {
			SVG_SANI_svgElement *root = (SVG_SANI_svgElement*) top_node;
			is_svg = 1;
			w = &root->width;
			h = &root->height;
		}
#endif
		/*default back color is white*/
		if (is_svg && ! (sr->user->init_flags & GF_TERM_WINDOWLESS)) sr->back_color = 0xFFFFFFFF;

		/*hack for SVG where size is set in %*/
		if (!sr->has_size_info && w && h) {
			sr->has_size_info = 1;
			sr->aspect_ratio = GF_ASPECT_RATIO_FILL_SCREEN;
			if (w->type!=SVG_NUMBER_PERCENTAGE) {
				width = FIX2INT(convert_svg_length_to_user(sr, w) );
			} else {
				width = 320; //FIX2INT(root->viewBox.width);
			}
			if (h->type!=SVG_NUMBER_PERCENTAGE) {
				height = FIX2INT(convert_svg_length_to_user(sr, h) );
			} else {
				height = 240; //FIX2INT(root->viewBox.height);
			}
		}
#endif
		/*default back color is key color*/
		if (sr->user->init_flags & GF_TERM_WINDOWLESS) {
			opt = gf_cfg_get_key(sr->user->config, "Rendering", "ColorKey");
			if (opt) {
				u32 r, g, b, a;
				sscanf(opt, "%02X%02X%02X%02X", &a, &r, &g, &b);
				sr->back_color = GF_COL_ARGB(0xFF, r, g, b);
			}
		}

		/*set scene size only if different, otherwise keep scaling/FS*/
		if ( !width || (sr->scene_width!=width) || !height || (sr->scene_height!=height)) {
			do_notif = sr->has_size_info || (!sr->scene_width && !sr->scene_height);
			SR_SetSceneSize(sr, width, height);

			/*get actual size in pixels*/
			width = sr->scene_width;
			height = sr->scene_height;

			if (!sr->user->os_window_handler) {
				/*only notify user if we are attached to a window*/
				do_notif = 0;
				if (sr->video_out->max_screen_width && (width > sr->video_out->max_screen_width))
					width = sr->video_out->max_screen_width;
				if (sr->video_out->max_screen_height && (height > sr->video_out->max_screen_height))
					height = sr->video_out->max_screen_height;

				gf_sr_set_size(sr,width, height);
			}
		}
	}

	SR_ResetFrameRate(sr);	
#ifdef GF_SR_EVENT_QUEUE
	gf_mx_v(sr->ev_mx);
#endif
	
	gf_sr_lock(sr, 0);
	/*here's a nasty trick: the app may respond to this by calling a gf_sr_set_size from a different
	thread, but in an atomic way (typically happen on Win32 when changing the window size). WE MUST
	NOTIFY THE SIZE CHANGE AFTER RELEASING THE RENDERER MUTEX*/
	if (do_notif && sr->user->EventProc) {
		GF_Event evt;
		evt.type = GF_EVENT_SCENE_SIZE;
		evt.size.width = width;
		evt.size.height = height;
		sr->user->EventProc(sr->user->opaque, &evt);
	}
	if (scene_graph)
		sr->draw_next_frame = 1;
	return GF_OK;
}