void DeleteVisualSurface2D(VisualSurface2D *surf) { u32 i; ra_del(&surf->to_redraw); VS2D_ResetGraphics(surf); for (i=0; i<surf->alloc_contexts; i++) DeleteDrawableContext(surf->contexts[i]); free(surf->contexts); free(surf->nodes_to_draw); DeleteChain(surf->back_stack); DeleteChain(surf->view_stack); DeleteChain(surf->prev_nodes_drawn); VS2D_ResetSensors(surf); DeleteChain(surf->sensors); free(surf); }
void visual_del(GF_VisualManager *visual) { ra_del(&visual->to_redraw); if (visual->raster_surface) visual->compositor->rasterizer->surface_delete(visual->raster_surface); visual->raster_surface = NULL; if (visual->raster_brush) visual->compositor->rasterizer->stencil_delete(visual->raster_brush); visual->raster_brush = NULL; while (visual->context) { DrawableContext *ctx = visual->context; visual->context = ctx->next; DeleteDrawableContext(ctx); } while (visual->prev_nodes) { struct _drawable_store *cur = visual->prev_nodes; visual->prev_nodes = cur->next; gf_free(cur); } #ifndef GPAC_DISABLE_VRML if (visual->back_stack) BindableStackDelete(visual->back_stack); if (visual->view_stack) BindableStackDelete(visual->view_stack); #endif /*GPAC_DISABLE_VRML*/ #ifndef GPAC_DISABLE_3D visual_3d_reset_graphics(visual); #ifndef GPAC_DISABLE_VRML if (visual->navigation_stack) BindableStackDelete(visual->navigation_stack); if (visual->fog_stack) BindableStackDelete(visual->fog_stack); #endif /*GPAC_DISABLE_VRML*/ gf_list_del(visual->alpha_nodes_to_draw); #endif gf_free(visual); }
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; }