Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2000-2012
6 : * All rights reserved
7 : *
8 : * This file is part of GPAC / Scene Compositor sub-project
9 : *
10 : * GPAC is free software; you can redistribute it and/or modify
11 : * it under the terms of the GNU Lesser General Public License as published by
12 : * the Free Software Foundation; either version 2, or (at your option)
13 : * any later version.
14 : *
15 : * GPAC is distributed in the hope that it will be useful,
16 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : * GNU Lesser General Public License for more details.
19 : *
20 : * You should have received a copy of the GNU Lesser General Public
21 : * License along with this library; see the file COPYING. If not, write to
22 : * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23 : *
24 : */
25 :
26 : #include "visual_manager.h"
27 : #include "nodes_stacks.h"
28 : #include <gpac/nodes_mpeg4.h>
29 : #ifndef GPAC_DISABLE_SVG
30 : #include <gpac/nodes_svg.h>
31 : #endif
32 :
33 0 : static Bool visual_draw_bitmap_stub(GF_VisualManager *visual, GF_TraverseState *tr_state, struct _drawable_context *ctx)
34 : {
35 0 : return 0;
36 : }
37 :
38 :
39 652 : GF_VisualManager *visual_new(GF_Compositor *compositor)
40 : {
41 : GF_VisualManager *tmp;
42 652 : GF_SAFEALLOC(tmp, GF_VisualManager);
43 652 : if (!tmp) {
44 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to allocate new visual\n"));
45 : return NULL;
46 : }
47 :
48 652 : tmp->center_coords = 1;
49 652 : tmp->compositor = compositor;
50 652 : ra_init(&tmp->to_redraw);
51 : #ifndef GPAC_DISABLE_VRML
52 652 : tmp->back_stack = gf_list_new();
53 652 : tmp->view_stack = gf_list_new();
54 : #endif
55 :
56 652 : tmp->raster_brush = gf_evg_stencil_new(GF_STENCIL_SOLID);
57 :
58 652 : tmp->DrawBitmap = visual_draw_bitmap_stub;
59 652 : tmp->ClearSurface = visual_2d_clear_surface;
60 :
61 : #ifdef GPAC_ENABLE_COVERAGE
62 652 : if (gf_sys_is_cov_mode()) {
63 : visual_draw_bitmap_stub(tmp, NULL, NULL);
64 : visual_reset_graphics(NULL);
65 : }
66 : #endif
67 :
68 : #ifndef GPAC_DISABLE_3D
69 :
70 : #ifndef GPAC_DISABLE_VRML
71 652 : tmp->navigation_stack = gf_list_new();
72 652 : tmp->fog_stack = gf_list_new();
73 : #endif /*GPAC_DISABLE_VRML*/
74 652 : tmp->alpha_nodes_to_draw = gf_list_new();
75 652 : tmp->compiled_programs = gf_list_new();
76 : #endif
77 :
78 652 : return tmp;
79 : }
80 :
81 651 : void visual_del(GF_VisualManager *visual)
82 : {
83 651 : ra_del(&visual->to_redraw);
84 :
85 651 : if (visual->raster_surface) gf_evg_surface_delete(visual->raster_surface);
86 651 : visual->raster_surface = NULL;
87 651 : if (visual->raster_brush) gf_evg_stencil_delete(visual->raster_brush);
88 651 : visual->raster_brush = NULL;
89 :
90 6841 : while (visual->context) {
91 : DrawableContext *ctx = visual->context;
92 5539 : visual->context = ctx->next;
93 5539 : DeleteDrawableContext(ctx);
94 : }
95 651 : while (visual->prev_nodes) {
96 : struct _drawable_store *cur = visual->prev_nodes;
97 0 : visual->prev_nodes = cur->next;
98 0 : gf_free(cur);
99 : }
100 :
101 : #ifndef GPAC_DISABLE_VRML
102 651 : if (visual->back_stack) BindableStackDelete(visual->back_stack);
103 651 : if (visual->view_stack) BindableStackDelete(visual->view_stack);
104 : #endif /*GPAC_DISABLE_VRML*/
105 :
106 : #ifndef GPAC_DISABLE_3D
107 651 : visual_3d_reset_graphics(visual);
108 651 : ra_del(&visual->hybgl_drawn);
109 :
110 : #ifndef GPAC_DISABLE_VRML
111 651 : if (visual->navigation_stack) BindableStackDelete(visual->navigation_stack);
112 651 : if (visual->fog_stack) BindableStackDelete(visual->fog_stack);
113 : #endif /*GPAC_DISABLE_VRML*/
114 :
115 651 : gf_list_del(visual->alpha_nodes_to_draw);
116 651 : gf_list_del(visual->compiled_programs);
117 : #endif
118 651 : gf_free(visual);
119 651 : }
120 :
121 5422 : Bool visual_get_size_info(GF_TraverseState *tr_state, Fixed *surf_width, Fixed *surf_height)
122 : {
123 : Fixed w, h;
124 : // w = tr_state->visual->width;
125 : // h = tr_state->visual->height;
126 5422 : w = tr_state->vp_size.x;
127 5422 : h = tr_state->vp_size.y;
128 : /*no size info, use main compositor output size*/
129 5422 : if (!w || !h) {
130 6 : w = INT2FIX(tr_state->visual->compositor->vp_width);
131 6 : h = INT2FIX(tr_state->visual->compositor->vp_height);
132 : }
133 5422 : if (tr_state->pixel_metrics) {
134 5422 : *surf_width = w;
135 5422 : *surf_height = h;
136 5422 : return 1;
137 : }
138 0 : if (tr_state->min_hsize) {
139 0 : *surf_width = gf_divfix(w, tr_state->min_hsize);
140 0 : *surf_height = gf_divfix(h, tr_state->min_hsize);
141 0 : return 0;
142 : }
143 0 : if (h > w) {
144 0 : *surf_width = 2*FIX_ONE;
145 0 : *surf_height = gf_divfix(2*h, w);
146 : } else {
147 0 : *surf_width = gf_divfix(2*w, h);
148 0 : *surf_height = 2*FIX_ONE;
149 : }
150 : return 0;
151 : }
152 :
153 28429 : void visual_clean_contexts(GF_VisualManager *visual)
154 : {
155 : u32 i, count;
156 28429 : Bool is_root_visual = (visual->compositor->visual==visual) ? 1 : 0;
157 28429 : DrawableContext *ctx = visual->context;
158 193060 : while (ctx && ctx->drawable) {
159 : /*remove visual registration flag*/
160 136202 : ctx->drawable->flags &= ~DRAWABLE_REGISTERED_WITH_VISUAL;
161 136202 : if (is_root_visual && (ctx->flags & CTX_HAS_APPEARANCE))
162 110803 : gf_node_dirty_reset(ctx->appear, 0);
163 :
164 : #ifndef GPAC_DISABLE_3D
165 : /*this may happen when switching a visual from 2D to 3D - discard context*/
166 136202 : if (visual->type_3d) ctx->drawable=NULL;
167 : #endif
168 136202 : ctx = ctx->next;
169 : }
170 :
171 : /*composite visual, cannot reset flags until root is done*/
172 28429 : if (!is_root_visual) return;
173 :
174 : /*reset all flags of all appearance nodes registered on all visuals but main one (done above)
175 : this must be done once all visuals have been drawn, otherwise we won't detect the changes
176 : for nodes drawn on several visuals*/
177 26361 : count = gf_list_count(visual->compositor->visuals);
178 28690 : for (i=1; i<count; i++) {
179 2329 : GF_VisualManager *a_vis = gf_list_get(visual->compositor->visuals, i);
180 2329 : ctx = a_vis->context;
181 7247 : while (ctx && ctx->drawable) {
182 2589 : if (ctx->flags & CTX_HAS_APPEARANCE)
183 2542 : gf_node_dirty_reset(ctx->appear, 0);
184 :
185 2589 : ctx->drawable = NULL;
186 2589 : ctx = ctx->next;
187 : }
188 : }
189 : }
190 :
191 28429 : Bool visual_draw_frame(GF_VisualManager *visual, GF_Node *root, GF_TraverseState *tr_state, Bool is_root_visual)
192 : {
193 : #ifndef GPAC_DISABLE_3D
194 28429 : if (visual->type_3d) {
195 6963 : Bool res = visual_3d_draw_frame(visual, root, tr_state, is_root_visual);
196 6963 : visual_clean_contexts(visual);
197 6963 : return res;
198 : }
199 21466 : if (visual->compositor->hybrid_opengl)
200 1907 : visual_3d_clean_state(visual);
201 : #endif
202 21466 : return visual_2d_draw_frame(visual, root, tr_state, is_root_visual);
203 : }
204 :
205 102 : void gf_sc_get_nodes_bounds(GF_Node *self, GF_ChildNodeItem *children, GF_TraverseState *tr_state, s32 *child_idx)
206 : {
207 : u32 i;
208 : SFVec2f size;
209 : GF_Rect rc;
210 : GF_Matrix2D cur_mx;
211 :
212 102 : if (tr_state->abort_bounds_traverse) {
213 0 : if (self == tr_state->for_node) {
214 0 : gf_mx2d_pre_multiply(&tr_state->mx_at_node, &tr_state->transform);
215 : }
216 0 : tr_state->abort_bounds_traverse=0;
217 0 : gf_sc_get_nodes_bounds(self, children, tr_state, child_idx);
218 0 : tr_state->abort_bounds_traverse=1;
219 19 : return;
220 : }
221 102 : if (!children) return;
222 :
223 : size.x = size.y = -FIX_ONE;
224 : #ifndef GPAC_DISABLE_VRML
225 83 : switch (gf_node_get_tag(self)) {
226 0 : case TAG_MPEG4_Layer2D:
227 0 : size = ((M_Layer2D *)self)->size;
228 0 : break;
229 0 : case TAG_MPEG4_Layer3D:
230 0 : size = ((M_Layer3D *)self)->size;
231 0 : break;
232 0 : case TAG_MPEG4_Form:
233 0 : size = ((M_Form *)self)->size;
234 0 : break;
235 : }
236 : #endif
237 83 : if ((size.x>=0) && (size.y>=0)) {
238 0 : tr_state->bounds = gf_rect_center(size.x, size.y);
239 0 : return;
240 : }
241 :
242 83 : gf_mx2d_copy(cur_mx, tr_state->transform);
243 83 : rc = gf_rect_center(0,0);
244 :
245 : i = 0;
246 427 : while (children) {
247 261 : if (child_idx && (i != (u32) *child_idx)) {
248 0 : children = children->next;
249 0 : continue;
250 : }
251 261 : gf_mx2d_init(tr_state->transform);
252 261 : tr_state->bounds = gf_rect_center(0,0);
253 :
254 : /*we hit the target node*/
255 261 : if (children->node == tr_state->for_node)
256 0 : tr_state->abort_bounds_traverse = 1;
257 :
258 261 : gf_node_traverse(children->node, tr_state);
259 :
260 261 : if (tr_state->abort_bounds_traverse) {
261 0 : gf_mx2d_add_matrix(&tr_state->mx_at_node, &cur_mx);
262 0 : return;
263 : }
264 :
265 261 : gf_mx2d_apply_rect(&tr_state->transform, &tr_state->bounds);
266 261 : gf_rect_union(&rc, &tr_state->bounds);
267 261 : children = children->next;
268 261 : if (child_idx)
269 : break;
270 : }
271 :
272 : #ifndef GPAC_DISABLE_SVG
273 83 : if (gf_node_get_tag(self)==TAG_SVG_use) {
274 : GF_FieldInfo info;
275 0 : if (gf_node_get_attribute_by_tag(self, TAG_XLINK_ATT_href, 0, 0, &info)==GF_OK) {
276 0 : GF_Node *iri = ((XMLRI*)info.far_ptr)->target;
277 0 : if (iri) {
278 0 : gf_mx2d_init(tr_state->transform);
279 0 : tr_state->bounds = gf_rect_center(0,0);
280 :
281 : /*we hit the target node*/
282 0 : if (iri == tr_state->for_node)
283 0 : tr_state->abort_bounds_traverse = 1;
284 :
285 0 : gf_node_traverse(iri, tr_state);
286 :
287 0 : if (tr_state->abort_bounds_traverse) {
288 0 : gf_mx2d_pre_multiply(&tr_state->mx_at_node, &cur_mx);
289 0 : return;
290 : }
291 :
292 0 : gf_mx2d_apply_rect(&tr_state->transform, &tr_state->bounds);
293 0 : gf_rect_union(&rc, &tr_state->bounds);
294 : }
295 : }
296 : }
297 : #endif
298 :
299 : gf_mx2d_copy(tr_state->transform, cur_mx);
300 83 : if (self != tr_state->for_node) {
301 83 : gf_mx2d_apply_rect(&tr_state->transform, &rc);
302 : }
303 83 : tr_state->bounds = rc;
304 : }
305 :
306 1 : void visual_reset_graphics(GF_VisualManager *visual)
307 : {
308 1 : if (!visual) return;
309 : #ifndef GPAC_DISABLE_3D
310 1 : if (visual->type_3d) {
311 0 : visual_3d_reset_graphics(visual);
312 : }
313 1 : compositor_2d_reset_gl_auto(visual->compositor);
314 : #endif
315 : }
316 :
|