Пример #1
0
static void visual_2d_fill_path(GF_VisualManager *visual, DrawableContext *ctx, GF_STENCIL stencil, GF_TraverseState *tr_state, Bool is_erase)
{
	Bool has_modif = GF_FALSE;
	GF_IRect clip;
	GF_Raster2D *raster = visual->compositor->rasterizer;

	/*background & direct drawing : use ctx clip*/
	if ((ctx->flags & CTX_IS_BACKGROUND) || tr_state->immediate_draw) {
		if (ctx->bi->clip.width && ctx->bi->clip.height) {
			GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Visual2D] Redrawing node %s[%s] (direct draw)\n", gf_node_get_log_name(ctx->drawable->node), gf_node_get_class_name(ctx->drawable->node) ));

			if (stencil) {
				raster->surface_set_clipper(visual->raster_surface, &ctx->bi->clip);
				raster->surface_fill(visual->raster_surface, stencil);
			} else {
				raster->surface_clear(visual->raster_surface, &ctx->bi->clip, 0);
			}

			has_modif = GF_TRUE;
		}
	}
	/*indirect drawing, draw path in all dirty areas*/
	else {
		u32 i;
		for (i=0; i<visual->to_redraw.count; i++) {
			/*there's an opaque region above, don't draw*/
#ifdef TRACK_OPAQUE_REGIONS
			if (!is_erase && (visual->draw_node_index<visual->to_redraw.list[i].opaque_node_index)) continue;
#endif
			clip = ctx->bi->clip;
			gf_irect_intersect(&clip, &visual->to_redraw.list[i].rect);
			if (clip.width && clip.height) {
				GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Visual2D] Redrawing node %s[%s] (indirect draw @ dirty rect idx %d)\n", gf_node_get_log_name(ctx->drawable->node), gf_node_get_class_name(ctx->drawable->node), i));
				if (stencil) {
					raster->surface_set_clipper(visual->raster_surface, &clip);
					raster->surface_fill(visual->raster_surface, stencil);
				} else {
					raster->surface_clear(visual->raster_surface, &clip, 0);
				}
				has_modif = 1;
			}
		}
	}
#ifndef GPAC_DISABLE_3D
	if (!is_erase)
		visual->nb_objects_on_canvas_since_last_ogl_flush++;
#endif
	if (has_modif) {
		visual->has_modif = 1;
#ifndef GPAC_DISABLE_3D
		if (!visual->offscreen && visual->compositor->hybrid_opengl && !is_erase)
			ra_union_rect(&visual->hybgl_drawn, &ctx->bi->clip);
#endif
	}
}
Пример #2
0
Bool group_cache_compute_stats(GF_Node *node, GroupingNode2D *group, GF_TraverseState *tr_state, DrawableContext *first_child, Bool skip_first_child)
{
	GF_Rect group_bounds;
	DrawableContext *ctx;
	u32 nb_segments, nb_objects;
	u32 alpha_pixels, opaque_pixels, area_world;
	u32 video_cache_max_size, cache_size, prev_cache_size;
	u32 i;
	GF_RectArray ra;

	/*compute stats*/
	nb_objects = 0;
	nb_segments = 0;
	alpha_pixels = opaque_pixels = 0;
	prev_cache_size = group->cached_size;
	/*reset bounds*/
	group_bounds.width = group_bounds.height = 0;
	video_cache_max_size = tr_state->visual->compositor->video_cache_max_size;

	/*never cache root node - this should be refined*/
	if (gf_node_get_parent(node, 0) == NULL) goto group_reject;
	if (!group->traverse_time) goto group_reject;

	ra_init(&ra);

	ctx = first_child;
	if (!first_child) ctx = tr_state->visual->context;
	if (skip_first_child) ctx = ctx->next;
	/*compute properties for the sub display list*/
	while (ctx && ctx->drawable) {
		//Fixed area;
		u32 alpha_comp;

		/*get area and compute alpha/opaque coverage*/
		alpha_comp = GF_COL_A(ctx->aspect.fill_color);

		/*add to group area*/
		gf_rect_union(&group_bounds, &ctx->bi->unclip);
		nb_objects++;

		/*no alpha*/
		if ((alpha_comp==0xFF)
			/*no transparent texture*/
			&& (!ctx->aspect.fill_texture || !ctx->aspect.fill_texture->transparent)
		) {

			ra_union_rect(&ra, &ctx->bi->clip);
		}
		nb_segments += ctx->drawable->path->n_points;

		ctx = ctx->next;
	}

	if (
		/*TEST 1: discard visually empty groups*/
		(!group_bounds.width || !group_bounds.height)
		||
		/*TEST 2: discard small groups*/
		(nb_objects<MIN_OBJECTS_IN_CACHE)
		||
		/*TEST 3: low complexity group*/
		(nb_segments && (nb_segments<10))
	) {
		ra_del(&ra);
		goto group_reject;
	}

	ra_refresh(&ra);
	opaque_pixels = 0;
	for (i=0; i<ra.count; i++) {
		opaque_pixels += ra.list[i].width * ra.list[i].height;
	}
	ra_del(&ra);

	/*get coverage in world coords*/
	area_world = FIX2INT(group_bounds.width) * FIX2INT(group_bounds.height);

	/*TEST 4: discard low coverage groups in world coords (plenty of space wasted)
		we consider that this % of the area is actually drawn - this is of course wrong,
		we would need to compute each path coverage in local coords then get the ratio
	*/
	if (10*opaque_pixels < 7*area_world) goto group_reject;

	/*the memory size allocated for the cache - cache is drawn in final coordinate system !!*/
	group_bounds.width = tr_state->visual->compositor->cache_scale * group_bounds.width / 100;
	group_bounds.height = tr_state->visual->compositor->cache_scale * group_bounds.height / 100;
	cache_size = FIX2INT(group_bounds.width) * FIX2INT(group_bounds.height) * 4 /* pixelFormat is ARGB*/;

	/*TEST 5: cache is less than 10x10 pixels: discard*/
	if (cache_size < 400) goto group_reject;
	/*TEST 6: cache is larger than our allowed memory: discard*/
	if (cache_size>=video_cache_max_size) {
		tr_state->cache_too_small = 1;
		goto group_reject;
	}

	/*compute the delta value for measuring the group importance for later discard
		(avg_time - Tcache) / (size_cache - drawable_gain)
	*/
	group->priority = INT2FIX(nb_objects*1024*group->traverse_time) / cache_size / group->nb_stats_frame;
	/*OK, group is a good candidate for caching*/
	group->nb_objects = nb_objects;
	group->cached_size = cache_size;


	/*we're moving from non-cached to cached*/
	if (!(group->flags & GROUP_IS_CACHABLE)) {
		group->flags |= GROUP_IS_CACHABLE;
		tr_state->visual->compositor->draw_next_frame = 1;

		/*insert the candidate and then update the list in order*/
		group_cache_insert_entry(node, group, tr_state);
		/*keep track of this cache object for later removal*/
		gf_list_add(tr_state->visual->compositor->cached_groups_queue, group);

		GF_LOG(GF_LOG_DEBUG, GF_LOG_CACHE, ("[CACHE] Turning cache on during stat pass for node %s - %d kb used in all caches\n", gf_node_get_log_name(node), tr_state->visual->compositor->video_cache_current_size ));
	}
	/*update memory occupation*/
	else {
		tr_state->visual->compositor->video_cache_current_size -= prev_cache_size;
		tr_state->visual->compositor->video_cache_current_size += group->cached_size;

		if (group->cache)
			group->cache->force_recompute = 1;
	}
	return 1;


group_reject:
	group->nb_objects = nb_objects;

	if ((group->flags & GROUP_IS_CACHABLE) || group->cache) {
		group->flags &= ~GROUP_IS_CACHABLE;

		if (group->cache) {
			group_cache_del(group->cache);
			group->cache = NULL;
			group->flags &= ~GROUP_IS_CACHED;
		}
		gf_list_del_item(tr_state->visual->compositor->cached_groups, group);
		tr_state->visual->compositor->video_cache_current_size -= cache_size;
	}

#if 0
	GF_LOG(GF_LOG_DEBUG, GF_LOG_CACHE, ("[CACHE] REJECT %s\tObjects: %d\tSlope: %g\tBytes: %d\tTime: %d\n",
										gf_node_get_log_name(node),
										group->nb_objects,
										FIX2FLT(group->priority),
										group->cached_size,
										group->traverse_time
										));

	GF_LOG(GF_LOG_DEBUG, GF_LOG_CACHE, ("[CACHE] Status (B): Max: %d\tUsed: %d\tNb Groups: %d\n",
								tr_state->visual->compositor->video_cache_max_size,
								tr_state->visual->compositor->video_cache_current_size,
								gf_list_count(tr_state->visual->compositor->cached_groups)
								));
#endif
	return 0;
}
Пример #3
0
void visual_2d_fill_irect(GF_VisualManager *visual, GF_IRect *rc, u32 fill, u32 strike)
{
	GF_Path *path;
	GF_Path *outline;
	GF_PenSettings pen;
	GF_Raster2D *raster = visual->compositor->rasterizer;
#ifdef SKIP_DRAW
	return;
#endif

	if (!rc) return;
	
	if (! visual->CheckAttached(visual) ) return;

	if (!fill && !strike ) return;

	/*no aa*/
	visual_2d_set_options(visual->compositor, visual->raster_surface, 0, 1);
	raster->surface_set_matrix(visual->raster_surface, NULL);

	raster->surface_set_raster_level(visual->raster_surface, GF_RASTER_HIGH_SPEED);
	raster->surface_set_matrix(visual->raster_surface, NULL);

	path = gf_path_new();
	gf_path_add_move_to(path, INT2FIX(rc->x-1), INT2FIX(rc->y+2-rc->height));
	gf_path_add_line_to(path, INT2FIX(rc->x+rc->width-2), INT2FIX(rc->y+2-rc->height));
	gf_path_add_line_to(path, INT2FIX(rc->x+rc->width), INT2FIX(rc->y));
	gf_path_add_line_to(path, INT2FIX(rc->x), INT2FIX(rc->y));
	gf_path_close(path);

	if (fill) {
		raster->surface_set_path(visual->raster_surface, path);
		raster->stencil_set_brush_color(visual->raster_brush, fill);

		raster->surface_set_clipper(visual->raster_surface, rc);
		raster->surface_fill(visual->raster_surface, visual->raster_brush);

		raster->surface_set_path(visual->raster_surface, NULL);
	}

	if (strike) {
		memset(&pen, 0, sizeof(GF_PenSettings));
		pen.width = 2;
		pen.align = GF_PATH_LINE_INSIDE;
		pen.join = GF_LINE_JOIN_BEVEL;
		outline = gf_path_get_outline(path, pen);
		outline->flags &= ~GF_PATH_FILL_ZERO_NONZERO;

		raster->surface_set_path(visual->raster_surface, outline);
		raster->stencil_set_brush_color(visual->raster_brush, strike);

		raster->surface_set_clipper(visual->raster_surface, rc);
		raster->surface_fill(visual->raster_surface, visual->raster_brush);

		raster->surface_set_path(visual->raster_surface, NULL);
		gf_path_del(outline);
	}
	gf_path_del(path);
#ifndef GPAC_DISABLE_3D
	if (!visual->offscreen && visual->compositor->hybrid_opengl)
		ra_union_rect(&visual->hybgl_drawn, rc);
#endif
}
Пример #4
0
Bool VS2D_TerminateDraw(VisualSurface2D *surf, RenderEffect2D *eff)
{
    u32 j, k, i, num_to_draw, num_empty, count, max_nodes_allowed;
    M4IRect refreshRect;
    Bool redraw_all, is_empty;
    M_Background2D *bck;
    DrawableContext *bck_ctx;
    DrawableContext *ctx;
    Bool use_direct_render = 0;
    Bool has_changed = 0;

    /*in direct mode the surface is always redrawn*/
    if (eff->trav_flags & TF_RENDER_DIRECT) {
        has_changed = 1;
        use_direct_render = 1;
    }

    VS2D_ResetSensors(surf);
    num_to_draw = 0;

    /*if the aspect ratio has changed redraw everything*/
    redraw_all = eff->invalidate_all;

    /*check for background changes for transparent nodes*/
    bck = NULL;
    bck_ctx = NULL;

    if (! use_direct_render) {
        bck = NULL;
        if (ChainGetCount(surf->back_stack)) bck = ChainGetEntry(surf->back_stack, 0);
        if (bck) {
            if (!bck->isBound) redraw_all = 1;
            surf->last_had_back = 1;
            bck_ctx = b2D_GetContext(bck, surf->back_stack);
            if (bck_ctx->redraw_flags) redraw_all = 1;
        } else if (surf->last_had_back) {
            surf->last_had_back = 0;
            redraw_all = 1;
        }
        surf->last_had_back = 0;
    }

    max_nodes_allowed = (u32) ((surf->top_clipper.width / MIN_BBOX_SIZE) * (surf->top_clipper.height / MIN_BBOX_SIZE));
    num_empty = 0;
    count = surf->num_contexts;
    for (i=0; i<count; i++) {
        ctx = surf->contexts[i];
        m4_irect_intersect(&ctx->clip, &surf->top_clipper);
        is_empty = m4_rect_is_empty(ctx->clip);

        /*store bounds even in direct render*/
        if (!is_empty) {
            drawable_store_bounds(ctx);
            register_sensor(surf, ctx);
        } else if (!use_direct_render) {
            num_empty++;
            continue;
        }
        //register node to draw
        surf->nodes_to_draw[num_to_draw] = i;
        num_to_draw++;

        if (use_direct_render) {
            drawable_reset_previous_bounds(ctx->node);
            continue;
        }

        drawctx_update_info(ctx);

        /*node has changed, add to redraw area*/
        if (!redraw_all && ctx->redraw_flags) {
            ra_union_rect(&surf->to_redraw, ctx->clip);
            CHECK_MAX_NODE
        }
        /*otherwise try to remove any sensor hidden below*/
        if (!ctx->transparent) remove_hidden_sensors(surf, num_to_draw, ctx);
    }