This source file includes following definitions.
- visual_draw_bitmap_stub
- visual_new
- visual_del
- visual_get_size_info
- visual_clean_contexts
- visual_draw_frame
- gf_sc_get_nodes_bounds
- visual_reset_graphics
#include "visual_manager.h"
#include "nodes_stacks.h"
#include <gpac/nodes_mpeg4.h>
#ifndef GPAC_DISABLE_SVG
#include <gpac/nodes_svg.h>
#endif
static Bool visual_draw_bitmap_stub(GF_VisualManager *visual, GF_TraverseState *tr_state, struct _drawable_context *ctx)
{
return 0;
}
GF_VisualManager *visual_new(GF_Compositor *compositor)
{
GF_VisualManager *tmp;
GF_SAFEALLOC(tmp, GF_VisualManager);
if (!tmp) {
GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to allocate new visual\n"));
return NULL;
}
tmp->center_coords = 1;
tmp->compositor = compositor;
ra_init(&tmp->to_redraw);
#ifndef GPAC_DISABLE_VRML
tmp->back_stack = gf_list_new();
tmp->view_stack = gf_list_new();
#endif
tmp->raster_brush = compositor->rasterizer->stencil_new(compositor->rasterizer, GF_STENCIL_SOLID);
tmp->DrawBitmap = visual_draw_bitmap_stub;
tmp->ClearSurface = visual_2d_clear_surface;
#ifndef GPAC_DISABLE_3D
#ifndef GPAC_DISABLE_VRML
tmp->navigation_stack = gf_list_new();
tmp->fog_stack = gf_list_new();
#endif
tmp->alpha_nodes_to_draw = gf_list_new();
#endif
return tmp;
}
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
#ifndef GPAC_DISABLE_3D
visual_3d_reset_graphics(visual);
ra_del(&visual->hybgl_drawn);
#ifndef GPAC_DISABLE_VRML
if (visual->navigation_stack) BindableStackDelete(visual->navigation_stack);
if (visual->fog_stack) BindableStackDelete(visual->fog_stack);
#endif
gf_list_del(visual->alpha_nodes_to_draw);
#endif
gf_free(visual);
}
Bool visual_get_size_info(GF_TraverseState *tr_state, Fixed *surf_width, Fixed *surf_height)
{
Fixed w, h;
w = tr_state->vp_size.x;
h = tr_state->vp_size.y;
if (!w || !h) {
w = INT2FIX(tr_state->visual->compositor->vp_width);
h = INT2FIX(tr_state->visual->compositor->vp_height);
}
if (tr_state->pixel_metrics) {
*surf_width = w;
*surf_height = h;
return 1;
}
if (tr_state->min_hsize) {
*surf_width = gf_divfix(w, tr_state->min_hsize);
*surf_height = gf_divfix(h, tr_state->min_hsize);
return 0;
}
if (h > w) {
*surf_width = 2*FIX_ONE;
*surf_height = gf_divfix(2*h, w);
} else {
*surf_width = gf_divfix(2*w, h);
*surf_height = 2*FIX_ONE;
}
return 0;
}
void visual_clean_contexts(GF_VisualManager *visual)
{
u32 i, count;
Bool is_root_visual = (visual->compositor->visual==visual) ? 1 : 0;
DrawableContext *ctx = visual->context;
while (ctx && ctx->drawable) {
ctx->drawable->flags &= ~DRAWABLE_REGISTERED_WITH_VISUAL;
if (is_root_visual && (ctx->flags & CTX_HAS_APPEARANCE))
gf_node_dirty_reset(ctx->appear, 0);
#ifndef GPAC_DISABLE_3D
if (visual->type_3d) ctx->drawable=NULL;
#endif
ctx = ctx->next;
}
if (!is_root_visual) return;
count = gf_list_count(visual->compositor->visuals);
for (i=1; i<count; i++) {
GF_VisualManager *a_vis = gf_list_get(visual->compositor->visuals, i);
ctx = a_vis->context;
while (ctx && ctx->drawable) {
if (ctx->flags & CTX_HAS_APPEARANCE)
gf_node_dirty_reset(ctx->appear, 0);
ctx->drawable = NULL;
ctx = ctx->next;
}
}
}
Bool visual_draw_frame(GF_VisualManager *visual, GF_Node *root, GF_TraverseState *tr_state, Bool is_root_visual)
{
#ifndef GPAC_DISABLE_3D
if (visual->type_3d) {
Bool res = visual_3d_draw_frame(visual, root, tr_state, is_root_visual);
visual_clean_contexts(visual);
return res;
}
#endif
return visual_2d_draw_frame(visual, root, tr_state, is_root_visual);
}
void gf_sc_get_nodes_bounds(GF_Node *self, GF_ChildNodeItem *children, GF_TraverseState *tr_state, s32 *child_idx)
{
u32 i;
SFVec2f size;
GF_Rect rc;
GF_Matrix2D cur_mx;
if (tr_state->abort_bounds_traverse) {
if (self == tr_state->for_node) {
gf_mx2d_pre_multiply(&tr_state->mx_at_node, &tr_state->transform);
}
tr_state->abort_bounds_traverse=0;
gf_sc_get_nodes_bounds(self, children, tr_state, child_idx);
tr_state->abort_bounds_traverse=1;
return;
}
if (!children) return;
size.x = size.y = -FIX_ONE;
#ifndef GPAC_DISABLE_VRML
switch (gf_node_get_tag(self)) {
case TAG_MPEG4_Layer2D:
size = ((M_Layer2D *)self)->size;
break;
case TAG_MPEG4_Layer3D:
size = ((M_Layer3D *)self)->size;
break;
case TAG_MPEG4_Form:
size = ((M_Form *)self)->size;
break;
}
#endif
if ((size.x>=0) && (size.y>=0)) {
tr_state->bounds = gf_rect_center(size.x, size.y);
return;
}
gf_mx2d_copy(cur_mx, tr_state->transform);
rc = gf_rect_center(0,0);
i = 0;
while (children) {
if (child_idx && (i != (u32) *child_idx)) {
children = children->next;
continue;
}
gf_mx2d_init(tr_state->transform);
tr_state->bounds = gf_rect_center(0,0);
if (children->node == tr_state->for_node)
tr_state->abort_bounds_traverse = 1;
gf_node_traverse(children->node, tr_state);
if (tr_state->abort_bounds_traverse) {
gf_mx2d_add_matrix(&tr_state->mx_at_node, &cur_mx);
return;
}
gf_mx2d_apply_rect(&tr_state->transform, &tr_state->bounds);
gf_rect_union(&rc, &tr_state->bounds);
children = children->next;
if (child_idx)
break;
}
#ifndef GPAC_DISABLE_SVG
if (gf_node_get_tag(self)==TAG_SVG_use) {
GF_FieldInfo info;
if (gf_node_get_attribute_by_tag(self, TAG_XLINK_ATT_href, 0, 0, &info)==GF_OK) {
GF_Node *iri = ((XMLRI*)info.far_ptr)->target;
if (iri) {
gf_mx2d_init(tr_state->transform);
tr_state->bounds = gf_rect_center(0,0);
if (iri == tr_state->for_node)
tr_state->abort_bounds_traverse = 1;
gf_node_traverse(iri, tr_state);
if (tr_state->abort_bounds_traverse) {
gf_mx2d_pre_multiply(&tr_state->mx_at_node, &cur_mx);
return;
}
gf_mx2d_apply_rect(&tr_state->transform, &tr_state->bounds);
gf_rect_union(&rc, &tr_state->bounds);
}
}
}
#endif
gf_mx2d_copy(tr_state->transform, cur_mx);
if (self != tr_state->for_node) {
gf_mx2d_apply_rect(&tr_state->transform, &rc);
}
tr_state->bounds = rc;
}
void visual_reset_graphics(GF_VisualManager *visual)
{
#ifndef GPAC_DISABLE_3D
if (visual->type_3d) {
visual_3d_reset_graphics(visual);
}
compositor_2d_reset_gl_auto(visual->compositor);
#endif
}