📄 visualsurface2d.c
字号:
/* * GPAC - Multimedia Framework C SDK * * Copyright (c) Jean Le Feuvre 2000-2005 * All rights reserved * * This file is part of GPAC / 2D rendering module * * GPAC is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * GPAC is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * */#include "stacks2d.h"#include "visualsurface2d.h"VisualSurface2D *NewVisualSurface2D(){ VisualSurface2D *tmp; GF_SAFEALLOC(tmp, VisualSurface2D); tmp->center_coords = 1; ra_init(&tmp->to_redraw); tmp->back_stack = gf_list_new(); tmp->view_stack = gf_list_new(); return tmp;}void DeleteVisualSurface2D(VisualSurface2D *surf){ ra_del(&surf->to_redraw); VS2D_ResetGraphics(surf); while (surf->context) { DrawableContext *ctx = surf->context; surf->context = ctx->next; DeleteDrawableContext(ctx); } while (surf->prev_nodes) { struct _drawable_store *cur = surf->prev_nodes; surf->prev_nodes = cur->next; free(cur); } gf_list_del(surf->back_stack); gf_list_del(surf->view_stack); free(surf);}DrawableContext *VS2D_GetDrawableContext(VisualSurface2D *surf){ if (!surf->context) { surf->context = NewDrawableContext(); surf->cur_context = surf->context; drawctx_reset(surf->context); return surf->context; } assert(surf->cur_context); /*current context is OK*/ if (!surf->cur_context->drawable) { /*reset next context in display list for next call*/ if (surf->cur_context->next) surf->cur_context->next->drawable = NULL; drawctx_reset(surf->cur_context); return surf->cur_context; } /*need a new context and next one is OK*/ if (surf->cur_context->next) { surf->cur_context = surf->cur_context->next; assert(surf->cur_context->drawable == NULL); /*reset next context in display list for next call*/ if (surf->cur_context->next) surf->cur_context->next->drawable = NULL; drawctx_reset(surf->cur_context); return surf->cur_context; } /*need to create a new context*/ surf->cur_context->next = NewDrawableContext(); surf->cur_context = surf->cur_context->next; drawctx_reset(surf->cur_context); return surf->cur_context;}void VS2D_RemoveLastContext(VisualSurface2D *surf){ assert(surf->cur_context); surf->cur_context->drawable = NULL;}void VS2D_DrawableDeleted(struct _visual_surface_2D *surf, struct _drawable *node){ /*remove drawable from surface list*/ struct _drawable_store *it = surf->prev_nodes; struct _drawable_store *prev = NULL; while (it) { if (it->drawable != node) { prev = it; it = prev->next; continue; } if (prev) prev->next = it->next; else surf->prev_nodes = it->next; if (!it->next) surf->last_prev_entry = prev; free(it); break; } /*check node isn't being tracked*/ if (surf->render->grab_node==node) { surf->render->grab_ctx = NULL; surf->render->grab_node = NULL; surf->render->is_tracking = 0; } if (surf->render->focus_node==node->node) surf->render->focus_node = NULL;}GF_Err VS2D_InitDraw(VisualSurface2D *surf, RenderEffect2D *eff){ GF_Err e; u32 rem, count; GF_Rect rc; struct _drawable_store *it, *prev; DrawableContext *ctx; M_Background2D *bck; u32 render_mode; u32 time; /*reset display list*/ surf->cur_context = surf->context; if (surf->context) surf->context->drawable = NULL; eff->surface = surf; eff->draw_background = 0; gf_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) { if (!surf->composite) { if (surf->render->scalable_zoom) rc = gf_rect_center(INT2FIX(surf->render->compositor->width), INT2FIX(surf->render->compositor->height)); else rc = gf_rect_center(INT2FIX(surf->render->cur_width + 2*surf->render->offset_x), INT2FIX(surf->render->cur_height + 2*surf->render->offset_y)); } else { rc = gf_rect_center(INT2FIX(surf->width), INT2FIX(surf->height)); } } else { rc.x = 0; rc.width = INT2FIX(surf->width); rc.y = rc.height = INT2FIX(surf->height); } /*set top-transform to pixelMetrics*/ if (!eff->is_pixel_metrics) gf_mx2d_add_scale(&eff->transform, eff->min_hsize, eff->min_hsize); surf->surf_rect = gf_rect_pixelize(&rc); GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render 2D] Top surface rectangle setup - width %d height %d\n", surf->surf_rect.width, surf->surf_rect.height)); /*setup surface, brush and pen */ e = VS2D_InitSurface(surf); if (e) return e; /*setup top clipper*/ if (surf->center_coords) { rc = gf_rect_center(INT2FIX(surf->width), INT2FIX(surf->height)); } else { rc.width = INT2FIX(surf->width); rc.height = INT2FIX(surf->height); rc.x = 0; rc.y = rc.height; if (surf->render->surface==surf) { rc.x += INT2FIX(surf->render->offset_x); rc.y += INT2FIX(surf->render->offset_y); } } /*setup viewport*/ if (gf_list_count(surf->view_stack)) { M_Viewport *vp = (M_Viewport *) gf_list_get(surf->view_stack, 0); vp_setup((GF_Node *) vp, eff, &rc); } surf->top_clipper = gf_rect_pixelize(&rc); GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render 2D] Top surface cliper setup - %d:%d@%dx%d\n", surf->top_clipper.x, surf->top_clipper.y, surf->top_clipper.width, surf->top_clipper.height)); /*reset sensors*/ surf->has_sensors = 0; render_mode = 0; if (eff->trav_flags & TF_RENDER_DIRECT) render_mode = 1; /*if we're requested to invalidate everything, switch to direct render but don't reset bounds*/ else if (eff->invalidate_all) { eff->trav_flags |= TF_RENDER_DIRECT; render_mode = 2; } time = gf_sys_clock(); /*reset prev nodes if any (previous render was indirect)*/ rem = count = 0; prev = NULL; it = surf->prev_nodes; while (it) { /*node was not drawn on this surface*/ if (!drawable_flush_bounds(it->drawable, surf, render_mode)) { GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render 2D] Unregistering previously drawn node %s from surface\n", gf_node_get_class_name(it->drawable->node))); /*remove all bounds info related to this surface and unreg node */ drawable_reset_bounds(it->drawable, surf); if (prev) prev->next = it->next; else surf->prev_nodes = it->next; if (!it->next) surf->last_prev_entry = prev; rem++; free(it); it = prev ? prev->next : surf->prev_nodes; } else { /*mark drawable as already registered with surface*/ it->drawable->flags |= DRAWABLE_REGISTERED_WITH_SURFACE; prev = it; it = it->next; count++; } } GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render 2D] Top surface initialized - %d nodes registered and %d removed - using %s rendering\n", count, rem, render_mode ? "direct" : "dirty-rect")); if (!render_mode) return GF_OK; /*direct mode, draw background*/ bck = (M_Background2D*) gf_list_get(surf->back_stack, 0); if (bck && bck->isBound) { ctx = b2D_GetContext(bck, surf->back_stack); if (ctx) { ctx->bi->clip = surf->surf_rect; ctx->bi->unclip = gf_rect_ft(&surf->surf_rect); eff->draw_background = 1; gf_node_render((GF_Node *) bck, eff); eff->draw_background = 0; } else { VS2D_Clear(surf, NULL, 0); } } else { VS2D_Clear(surf, NULL, 0); } return GF_OK;}void VS2D_RegisterSensor(VisualSurface2D *surf, DrawableContext *ctx){ SensorContext *sc; sc = ctx->sensor; while (sc) { /*if any of the attached sensor is active, register*/ if (sc->h_node->IsEnabled(sc->h_node)) { surf->has_sensors = 1; return; } } /*disable all sensors*/ drawctx_reset_sensors(ctx); /*check for composite texture*/ if (!ctx->h_texture || !(ctx->h_texture->flags & GF_SR_TEXTURE_COMPOSITE) ) return; surf->has_sensors = 1;}static void VS2D_ReverseContexts(VisualSurface2D *surf){ u32 i, depth; Bool is_root_surf = (surf->render->surface==surf) ? 1 : 0; DrawableContext *ctx, *prev, *tmp; i = depth = 0; /*reverse all contexts used to front->back order for picking*/ prev = NULL; ctx = surf->context; if (surf->render->grab_ctx) { while (ctx && ctx->drawable) { /*remove surface registration flag - this is required in case the node is drawn on several surfaces*/ ctx->drawable->flags &= ~DRAWABLE_REGISTERED_WITH_SURFACE; if (is_root_surf) { if (ctx->flags & CTX_HAS_APPEARANCE) gf_node_dirty_reset(ctx->appear); } tmp = ctx->next; ctx->next = prev; prev = ctx; i++; if (surf->render->grab_ctx == ctx) depth = i; ctx = tmp; } } else { while (ctx && ctx->drawable) { /*remove surface registration flag*/ ctx->drawable->flags &= ~DRAWABLE_REGISTERED_WITH_SURFACE; if (is_root_surf) { if (ctx->flags & CTX_HAS_APPEARANCE) gf_node_dirty_reset(ctx->appear); } tmp = ctx->next; ctx->next = prev; prev = ctx; ctx = tmp; } } if (prev) { surf->context->next = ctx; surf->context = surf->cur_context = prev; if (surf->render->grab_ctx) { surf->render->grab_ctx = surf->context; while (depth>1) { surf->render->grab_ctx = surf->render->grab_ctx->next; depth--; } } }}#ifdef TRACK_OPAQUE_REGIONS#define CHECK_UNCHANGED 0static void mark_opaque_areas(VisualSurface2D *surf){ u32 i, k;#if CHECK_UNCHANGED Bool remove;#endif GF_RectArray *ra = &surf->to_redraw; if (!ra->count) return; ra->opaque_node_index = (u32*)realloc(ra->opaque_node_index, sizeof(u32) * ra->count); for (k=0; k<ra->count; k++) {#if CHECK_UNCHANGED remove = 1;#endif ra->opaque_node_index[k] = 0; for (i=surf->num_contexts; i>0; i--) { DrawableContext *ctx = surf->contexts[i-1]; if (!gf_irect_inside(&ctx->bi->clip, &ra->list[k]) ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -