GF_Err visual_2d_init_draw(GF_VisualManager *visual, GF_TraverseState *tr_state) { GF_Err e; u32 rem, count; struct _drawable_store *it, *prev; #ifndef GPAC_DISABLE_VRML DrawableContext *ctx; M_Background2D *bck; #endif u32 draw_mode; /*reset display list*/ visual->cur_context = visual->context; if (visual->context) visual->context->drawable = NULL; visual->has_modif = 0; visual->has_overlays = 0; visual_2d_setup_projection(visual, tr_state); if (!visual->top_clipper.width || !visual->top_clipper.height) return GF_OK; tr_state->traversing_mode = TRAVERSE_SORT; visual->num_nodes_current_frame = 0; /*setup raster surface, brush and pen */ e = visual_2d_init_raster(visual); if (e) return e; draw_mode = 0; if (tr_state->immediate_draw) draw_mode = 1; /*if we're requested to invalidate everything, switch to direct drawing but don't reset bounds*/ else if (tr_state->invalidate_all) { tr_state->immediate_draw = 1; draw_mode = 2; } tr_state->invalidate_all = 0; /*reset prev nodes if any (previous traverse was indirect)*/ rem = count = 0; prev = NULL; it = visual->prev_nodes; while (it) { /*node was not drawn on this visual*/ if (!drawable_flush_bounds(it->drawable, visual, draw_mode)) { GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Visual2D] Unregistering previously drawn node %s from visual\n", gf_node_get_class_name(it->drawable->node))); /*remove all bounds info related to this visual and unreg node */ drawable_reset_bounds(it->drawable, visual); if (prev) prev->next = it->next; else visual->prev_nodes = it->next; if (!it->next) visual->last_prev_entry = prev; rem++; gf_free(it); it = prev ? prev->next : visual->prev_nodes; } else { /*mark drawable as already registered with visual*/ it->drawable->flags |= DRAWABLE_REGISTERED_WITH_VISUAL; prev = it; it = it->next; count++; } } GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Visual2D] Top visual initialized - %d nodes registered and %d removed - using %s rendering\n", count, rem, draw_mode ? "direct" : "dirty-rect")); if (!draw_mode) return GF_OK; #ifndef GPAC_DISABLE_VRML /*direct mode, draw background*/ bck = (M_Background2D*) gf_list_get(visual->back_stack, 0); if (bck && bck->isBound) { ctx = b2d_get_context(bck, visual->back_stack); if (ctx) { /*force clearing entire zone, not just viewport, when using color. If texture, we MUST use the VP clipper in order to compute offsets when blitting bitmaps*/ if (ctx->aspect.fill_texture &&ctx->aspect.fill_texture->stream) { ctx->bi->clip = visual->top_clipper; } else { ctx->bi->clip = visual->surf_rect; } ctx->bi->unclip = gf_rect_ft(&ctx->bi->clip); tr_state->traversing_mode = TRAVERSE_BINDABLE; ctx->flags |= CTX_BACKROUND_NOT_LAYER; gf_node_traverse((GF_Node *) bck, tr_state); tr_state->traversing_mode = TRAVERSE_SORT; ctx->flags &= ~CTX_BACKROUND_NOT_LAYER; } else { visual->ClearSurface(visual, NULL, 0); } } else #endif { visual->ClearSurface(visual, NULL, 0); } return GF_OK; }
void VS2D_InitDraw(VisualSurface2D *surf, RenderEffect2D *eff) { u32 i, count; M4Rect rc; DrawableContext *ctx; M_Background2D *bck; surf->num_contexts = 0; eff->surface = surf; eff->draw_background = 0; mx2d_copy(surf->top_transform, eff->transform); eff->back_stack = surf->back_stack; eff->view_stack = surf->view_stack; /*setup clipper*/ if (surf->center_coords) { m4_rect_center(&rc, (Float) surf->width, (Float) surf->height); } else { rc.x = 0; rc.width = (Float) surf->width; rc.y = rc.height = (Float) surf->height; } /*set top-transform to pixelMetrics*/ if (!eff->is_pixel_metrics) mx2d_add_scale(&eff->transform, eff->min_hsize, eff->min_hsize); surf->surf_rect = m4_rect_pixelize(&rc); /*setup surface, brush and pen */ VS2D_InitSurface(surf); /*setup viewport*/ if (ChainGetCount(surf->view_stack)) { M_Viewport *vp = (M_Viewport *) ChainGetEntry(surf->view_stack, 0); vp_setup((SFNode *) vp, eff, &rc); } surf->top_clipper = m4_rect_pixelize(&rc); /*reset prev nodes*/ count = ChainGetCount(surf->prev_nodes_drawn); for (i=0; i<count; i++) { Drawable *dr = ChainGetEntry(surf->prev_nodes_drawn, i); if (surf->last_was_direct_render != (Bool) (eff->trav_flags & TF_RENDER_DIRECT) ) drawable_reset_previous_bounds(dr); drawable_flush_bounds(dr); } surf->last_was_direct_render = (Bool) (eff->trav_flags & TF_RENDER_DIRECT); if (!surf->last_was_direct_render) return; /*direct mode, draw background*/ bck = NULL; if (ChainGetCount(surf->back_stack)) bck = ChainGetEntry(surf->back_stack, 0); if (bck && bck->isBound) { ctx = b2D_GetContext(bck, surf->back_stack); ctx->clip = surf->surf_rect; ctx->unclip = m4_rect_ft(&ctx->clip); eff->draw_background = 1; Node_Render((SFNode *) bck, eff); eff->draw_background = 0; } else { VS2D_Clear(surf, NULL, 0); } }