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 :
27 : #include "mpeg4_grouping.h"
28 : #include "visual_manager.h"
29 : #include "texturing.h"
30 : #include "nodes_stacks.h"
31 :
32 : #ifndef GPAC_DISABLE_VRML
33 :
34 :
35 : #define B2D_PLANE_HSIZE FLT2FIX(0.5025f)
36 :
37 : typedef struct
38 : {
39 : DrawableContext ctx;
40 : BoundInfo bi;
41 : } BackgroundStatus;
42 :
43 622 : static void DestroyBackground2D(GF_Node *node)
44 : {
45 622 : Background2DStack *stack = (Background2DStack *) gf_node_get_private(node);
46 :
47 622 : PreDestroyBindable(node, stack->reg_stacks);
48 622 : gf_list_del(stack->reg_stacks);
49 :
50 1819 : while (gf_list_count(stack->status_stack)) {
51 575 : BackgroundStatus *status = (BackgroundStatus *)gf_list_get(stack->status_stack, 0);
52 575 : gf_list_rem(stack->status_stack, 0);
53 575 : gf_free(status);
54 : }
55 622 : gf_list_del(stack->status_stack);
56 :
57 622 : drawable_del(stack->drawable);
58 622 : gf_sc_texture_destroy(&stack->txh);
59 : #ifndef GPAC_DISABLE_3D
60 622 : if (stack->mesh) mesh_free(stack->mesh);
61 : #endif
62 622 : gf_free(stack);
63 622 : }
64 :
65 575 : static void b2D_new_status(Background2DStack *bck, M_Background2D*back)
66 : {
67 : BackgroundStatus *status;
68 :
69 575 : GF_SAFEALLOC(status, BackgroundStatus);
70 575 : if (!status) {
71 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to allocate background2D status\n"));
72 : return;
73 : }
74 1150 : gf_mx2d_init(status->ctx.transform);
75 575 : status->ctx.drawable = bck->drawable;
76 575 : status->ctx.flags = CTX_IS_BACKGROUND;
77 575 : status->ctx.bi = &status->bi;
78 575 : status->ctx.aspect.fill_color = GF_COL_ARGB_FIXED(FIX_ONE, back->backColor.red, back->backColor.green, back->backColor.blue);
79 575 : status->ctx.aspect.fill_texture = &bck->txh;
80 575 : gf_list_add(bck->status_stack, status);
81 : }
82 :
83 49655 : static BackgroundStatus *b2d_get_status(Background2DStack *stack, GF_List *background_stack)
84 : {
85 : u32 i, count;
86 49655 : if (!background_stack) return NULL;
87 :
88 49655 : count = gf_list_count(stack->reg_stacks);
89 0 : for (i=0; i<count; i++) {
90 49655 : GF_List *bind_stack = (GF_List *)gf_list_get(stack->reg_stacks, i);
91 49655 : if (bind_stack == background_stack) {
92 49655 : return gf_list_get(stack->status_stack, i);
93 : }
94 : }
95 : return NULL;
96 : }
97 :
98 :
99 : static Bool back_use_texture(M_Background2D *bck)
100 : {
101 50198 : if (!bck->url.count) return 0;
102 5796 : if (bck->url.vals[0].OD_ID > 0) return 1;
103 2351 : if (bck->url.vals[0].url && strlen(bck->url.vals[0].url)) return 1;
104 : return 0;
105 : }
106 :
107 14166 : static void DrawBackground2D_2D(DrawableContext *ctx, GF_TraverseState *tr_state)
108 : {
109 : Bool clear_all = GF_TRUE;
110 : u32 color;
111 : Bool use_texture;
112 : Bool is_offscreen = GF_FALSE;
113 : Background2DStack *stack;
114 14166 : if (!ctx || !ctx->drawable || !ctx->drawable->node) return;
115 14166 : stack = (Background2DStack *) gf_node_get_private(ctx->drawable->node);
116 :
117 14166 : if (!ctx->bi->clip.width || !ctx->bi->clip.height) return;
118 :
119 14166 : stack->flags &= ~CTX_PATH_FILLED;
120 14166 : color = ctx->aspect.fill_color;
121 :
122 14166 : use_texture = back_use_texture((M_Background2D *)ctx->drawable->node);
123 12750 : if (!use_texture && !tr_state->visual->is_attached) {
124 : use_texture = 1;
125 11891 : stack->txh.data = stack->col_tx;
126 11891 : stack->txh.width = 2;
127 11891 : stack->txh.height = 2;
128 11891 : stack->txh.stride = 6;
129 11891 : stack->txh.pixelformat = GF_PIXEL_RGB;
130 : }
131 :
132 2275 : if (use_texture) {
133 :
134 13307 : if (!tr_state->visual->DrawBitmap(tr_state->visual, tr_state, ctx)) {
135 : /*set target rect*/
136 207 : gf_path_reset(stack->drawable->path);
137 621 : gf_path_add_rect_center(stack->drawable->path,
138 207 : ctx->bi->unclip.x + ctx->bi->unclip.width/2,
139 207 : ctx->bi->unclip.y - ctx->bi->unclip.height/2,
140 207 : ctx->bi->unclip.width, ctx->bi->unclip.height);
141 :
142 : /*draw texture*/
143 207 : visual_2d_texture_path(tr_state->visual, stack->drawable->path, ctx, tr_state);
144 : }
145 : //a quick hack, if texture not ready return (we don't have direct notification of this through the above functions
146 : #ifndef GPAC_DISABLE_3D
147 13307 : if (tr_state->visual->compositor->hybrid_opengl && !stack->txh.tx_io)
148 : return;
149 : #endif
150 :
151 13285 : stack->flags &= ~(CTX_APP_DIRTY | CTX_TEXTURE_DIRTY);
152 13285 : tr_state->visual->has_modif = 1;
153 : #ifndef GPAC_DISABLE_3D
154 : //in opengl auto mode we still have to clear the canvas
155 13285 : if (!tr_state->immediate_draw && !tr_state->visual->offscreen && tr_state->visual->compositor->hybrid_opengl) {
156 : clear_all = GF_FALSE;
157 : is_offscreen = GF_TRUE;
158 442 : color &= 0x00FFFFFF;
159 : } else
160 : #endif
161 : return;
162 : }
163 :
164 :
165 : #ifndef GPAC_DISABLE_3D
166 1301 : if (ctx->flags & CTX_BACKROUND_NOT_LAYER) {
167 1055 : if (clear_all && !tr_state->visual->offscreen && tr_state->visual->compositor->hybrid_opengl) {
168 151 : compositor_2d_hybgl_clear_surface(tr_state->visual, NULL, color, GF_FALSE);
169 : is_offscreen = GF_TRUE;
170 151 : color &= 0x00FFFFFF;
171 : //we may need to clear the canvas for immediate mode
172 : }
173 : } else {
174 : is_offscreen = GF_TRUE;
175 : }
176 1301 : if (ctx->flags & CTX_BACKROUND_NO_CLEAR) {
177 0 : stack->flags &= ~(CTX_APP_DIRTY | CTX_TEXTURE_DIRTY);
178 0 : tr_state->visual->has_modif = 1;
179 0 : return;
180 : }
181 : #endif
182 :
183 : /*direct drawing, draw without clippers */
184 1301 : if (tr_state->immediate_draw
185 : ) {
186 : /*directly clear with specified color*/
187 11 : if (clear_all)
188 11 : tr_state->visual->ClearSurface(tr_state->visual, &ctx->bi->clip, color, is_offscreen);
189 : } else {
190 : u32 i;
191 : GF_IRect clip;
192 1289 : for (i=0; i<tr_state->visual->to_redraw.count; i++) {
193 : /*there's an opaque region above, don't draw*/
194 : #ifdef TRACK_OPAQUE_REGIONS
195 : if (tr_state->visual->draw_node_index < tr_state->visual->to_redraw.list[i].opaque_node_index) continue;
196 : #endif
197 1289 : clip = ctx->bi->clip;
198 1289 : gf_irect_intersect(&clip, &tr_state->visual->to_redraw.list[i].rect);
199 1289 : if (clip.width && clip.height) {
200 1289 : tr_state->visual->ClearSurface(tr_state->visual, &clip, color, is_offscreen ? 2 : 0);
201 : }
202 : }
203 : }
204 1301 : stack->flags &= ~(CTX_APP_DIRTY | CTX_TEXTURE_DIRTY);
205 1301 : tr_state->visual->has_modif = 1;
206 : }
207 :
208 : #ifndef GPAC_DISABLE_3D
209 4665 : static Bool back_texture_enabled(M_Background2D *bck, GF_TextureHandler *txh)
210 : {
211 4665 : Bool use_texture = back_use_texture(bck);
212 : if (use_texture) {
213 : /*texture not ready*/
214 972 : if (!txh->tx_io) {
215 : use_texture = 0;
216 112 : gf_sc_invalidate(txh->compositor, NULL);
217 : }
218 972 : gf_sc_texture_set_blend_mode(txh, gf_sc_texture_is_transparent(txh) ? TX_REPLACE : TX_DECAL);
219 : }
220 4665 : return use_texture;
221 : }
222 :
223 4665 : static void DrawBackground2D_3D(M_Background2D *bck, Background2DStack *st, GF_TraverseState *tr_state)
224 : {
225 : GF_Matrix mx, bck_mx, bck_mx_cam;
226 : Bool use_texture;
227 :
228 4665 : use_texture = back_texture_enabled(bck, &st->txh);
229 :
230 4665 : visual_3d_set_background_state(tr_state->visual, 1);
231 :
232 4665 : gf_mx_copy(bck_mx_cam, tr_state->camera->modelview);
233 4665 : gf_mx_copy(bck_mx, tr_state->model_matrix);
234 :
235 : /*little opt: if we clear the main visual clear it entirely */
236 4665 : if (! tr_state->is_layer) {
237 3572 : visual_3d_clear(tr_state->visual, bck->backColor, FIX_ONE);
238 3572 : if (!use_texture) {
239 3144 : visual_3d_set_background_state(tr_state->visual, 0);
240 3144 : return;
241 : }
242 : /*we need a hack here because main vp is always traversed before main background, and in the case of a
243 : 2D viewport it modifies the modelview matrix, which we don't want ...*/
244 856 : gf_mx_init(tr_state->model_matrix);
245 856 : gf_mx_init(tr_state->camera->modelview);
246 : }
247 1521 : if (!use_texture || (!tr_state->is_layer && st->txh.transparent) ) visual_3d_set_material_2d(tr_state->visual, bck->backColor, FIX_ONE);
248 1521 : if (use_texture) {
249 860 : visual_3d_set_state(tr_state->visual, V3D_STATE_COLOR, ! tr_state->is_layer);
250 860 : tr_state->mesh_num_textures = gf_sc_texture_enable(&st->txh, NULL);
251 860 : if (!tr_state->mesh_num_textures) visual_3d_set_material_2d(tr_state->visual, bck->backColor, FIX_ONE);
252 : }
253 :
254 : /*create mesh object if needed*/
255 1521 : if (!st->mesh) {
256 19 : st->mesh = new_mesh();
257 19 : mesh_set_vertex(st->mesh, -B2D_PLANE_HSIZE, -B2D_PLANE_HSIZE, 0, 0, 0, FIX_ONE, 0, 0);
258 19 : mesh_set_vertex(st->mesh, B2D_PLANE_HSIZE, -B2D_PLANE_HSIZE, 0, 0, 0, FIX_ONE, FIX_ONE, 0);
259 19 : mesh_set_vertex(st->mesh, B2D_PLANE_HSIZE, B2D_PLANE_HSIZE, 0, 0, 0, FIX_ONE, FIX_ONE, FIX_ONE);
260 19 : mesh_set_vertex(st->mesh, -B2D_PLANE_HSIZE, B2D_PLANE_HSIZE, 0, 0, 0, FIX_ONE, 0, FIX_ONE);
261 19 : mesh_set_triangle(st->mesh, 0, 1, 2);
262 19 : mesh_set_triangle(st->mesh, 0, 2, 3);
263 19 : st->mesh->flags |= MESH_IS_2D;
264 : }
265 :
266 1521 : gf_mx_init(mx);
267 1521 : if (tr_state->camera->is_3D) {
268 : Fixed sx, sy;
269 : /*reset matrix*/
270 1542 : gf_mx_init(tr_state->model_matrix);
271 771 : sx = sy = 2 * gf_mulfix(gf_tan(tr_state->camera->fieldOfView/2), tr_state->camera->z_far);
272 771 : if (tr_state->camera->width > tr_state->camera->height) {
273 454 : sx = gf_muldiv(sx, tr_state->camera->width, tr_state->camera->height);
274 : } else {
275 317 : sy = gf_muldiv(sy, tr_state->camera->height, tr_state->camera->width);
276 : }
277 771 : gf_mx_add_scale(&mx, sx, sy, FIX_ONE);
278 : #ifdef GPAC_FIXED_POINT
279 : gf_mx_add_translation(&mx, 0, 0, - (tr_state->camera->z_far/100)*99);
280 : #else
281 771 : gf_mx_add_translation(&mx, 0, 0, -0.995f*tr_state->camera->z_far);
282 : #endif
283 : } else {
284 750 : gf_mx_add_scale(&mx, tr_state->bbox.max_edge.x - tr_state->bbox.min_edge.x,
285 750 : tr_state->bbox.max_edge.y - tr_state->bbox.min_edge.y,
286 : FIX_ONE);
287 : /*when in layer2D, DON'T MOVE BACKGROUND TO ZFAR*/
288 750 : if (!tr_state->is_layer) {
289 : Fixed tr;
290 : #ifdef GPAC_FIXED_POINT
291 : tr = -(tr_state->camera->z_far/100)*99;
292 : #else
293 279 : tr = -0.999f*tr_state->camera->z_far;
294 : #endif
295 279 : if (!tr_state->camera->is_3D) tr = -tr;
296 279 : gf_mx_add_translation(&mx, 0, 0, tr);
297 : }
298 : }
299 1521 : gf_mx_add_matrix(&tr_state->model_matrix, &mx);
300 1521 : visual_3d_mesh_paint(tr_state, st->mesh);
301 1521 : if (tr_state->mesh_num_textures) {
302 860 : gf_sc_texture_disable(&st->txh);
303 860 : tr_state->mesh_num_textures = 0;
304 : }
305 :
306 : gf_mx_copy(tr_state->model_matrix, bck_mx);
307 1521 : gf_mx_copy(tr_state->camera->modelview, bck_mx_cam);
308 :
309 1521 : visual_3d_set_background_state(tr_state->visual, 0);
310 : }
311 : #endif
312 :
313 53074 : static void TraverseBackground2D(GF_Node *node, void *rs, Bool is_destroy)
314 : {
315 : u32 col;
316 : BackgroundStatus *status;
317 : M_Background2D *bck;
318 53074 : Background2DStack *stack = (Background2DStack *) gf_node_get_private(node);
319 : GF_TraverseState *tr_state = (GF_TraverseState *)rs;
320 :
321 53074 : if (is_destroy) {
322 622 : DestroyBackground2D(node);
323 622 : return;
324 : }
325 52452 : if (tr_state->visual->compositor->noback)
326 : return;
327 :
328 : bck = (M_Background2D *)node;
329 :
330 : /*special case for background in Layer2D: the background is seen as a regular drawable, so
331 : RENDER_BINDABLE is not used*/
332 52407 : switch (tr_state->traversing_mode) {
333 14070 : case TRAVERSE_DRAW_2D:
334 14070 : DrawBackground2D_2D(tr_state->ctx, tr_state);
335 14070 : return;
336 : case TRAVERSE_PICK:
337 : case TRAVERSE_GET_BOUNDS:
338 : return;
339 : }
340 :
341 : /*first traverse, bound if needed*/
342 32163 : if (gf_list_find(tr_state->backgrounds, node) < 0) {
343 : M_Background2D *top_bck;
344 :
345 575 : gf_list_add(tr_state->backgrounds, node);
346 : assert(gf_list_find(stack->reg_stacks, tr_state->backgrounds)==-1);
347 575 : gf_list_add(stack->reg_stacks, tr_state->backgrounds);
348 575 : b2D_new_status(stack, bck);
349 :
350 : /*only bound if we're on top*/
351 575 : top_bck = gf_list_get(tr_state->backgrounds, 0);
352 575 : if (!bck->isBound) {
353 575 : if (top_bck== bck) {
354 543 : Bindable_SetIsBound(node, 1);
355 32 : } else if (!top_bck->isBound) {
356 0 : bck->set_bind = 1;
357 0 : bck->on_set_bind(node, NULL);
358 : }
359 : }
360 : /*open the stream if any*/
361 640 : if (back_use_texture(bck) && !stack->txh.is_open) gf_sc_texture_play(&stack->txh, &bck->url);
362 : /*in any case don't draw the first time (since the background could have been declared last)*/
363 575 : gf_sc_invalidate(stack->txh.compositor, NULL);
364 575 : return;
365 : }
366 31588 : if (!bck->isBound) return;
367 :
368 30792 : status = b2d_get_status(stack, tr_state->backgrounds);
369 30792 : if (!status) return;
370 :
371 30792 : if (gf_node_dirty_get(node)) {
372 : u32 i;
373 :
374 869 : stack->flags |= CTX_APP_DIRTY;
375 869 : gf_node_dirty_clear(node, 0);
376 :
377 :
378 869 : col = GF_COL_ARGB_FIXED(FIX_ONE, bck->backColor.red, bck->backColor.green, bck->backColor.blue);
379 869 : if (col != status->ctx.aspect.fill_color) {
380 277 : status->ctx.aspect.fill_color = col;
381 277 : stack->flags |= CTX_APP_DIRTY;
382 : }
383 3476 : for (i=0; i<4; i++) {
384 3476 : stack->col_tx[3*i] = FIX2INT(255 * bck->backColor.red);
385 3476 : stack->col_tx[3*i+1] = FIX2INT(255 * bck->backColor.green);
386 3476 : stack->col_tx[3*i+2] = FIX2INT(255 * bck->backColor.blue);
387 : }
388 : }
389 :
390 30792 : if (back_use_texture(bck) ) {
391 : #ifndef GPAC_DISABLE_3D
392 3343 : if (stack->txh.compositor->hybrid_opengl && !tr_state->visual->offscreen && stack->hybgl_init) {
393 1010 : stack->flags |= CTX_HYBOGL_NO_CLEAR;
394 : }
395 3343 : stack->hybgl_init = 1;
396 : #endif
397 3343 : if (stack->txh.tx_io && !(status->ctx.flags & CTX_APP_DIRTY) && stack->txh.needs_refresh) {
398 368 : stack->flags |= CTX_TEXTURE_DIRTY;
399 : }
400 : }
401 30792 : if (status->ctx.flags & CTX_BACKROUND_NOT_LAYER) {
402 96 : status->ctx.flags = stack->flags | CTX_BACKROUND_NOT_LAYER;
403 : } else {
404 30696 : status->ctx.flags = stack->flags;
405 30696 : if (tr_state->is_layer)
406 2653 : status->ctx.flags &= ~CTX_BACKROUND_NOT_LAYER;
407 : }
408 :
409 :
410 30792 : if (tr_state->traversing_mode != TRAVERSE_BINDABLE) return;
411 :
412 : /*3D mode*/
413 : #ifndef GPAC_DISABLE_3D
414 4761 : if (tr_state->visual->type_3d) {
415 4665 : DrawBackground2D_3D(bck, stack, tr_state);
416 : } else
417 : #endif
418 96 : DrawBackground2D_2D(&status->ctx, tr_state);
419 : }
420 :
421 :
422 52 : static void b2D_set_bind(GF_Node *node, GF_Route *route)
423 : {
424 52 : Background2DStack *stack = (Background2DStack *)gf_node_get_private(node);
425 52 : Bindable_OnSetBind(node, stack->reg_stacks, NULL);
426 :
427 52 : if (stack->drawable->flags & DRAWABLE_IS_OVERLAY) {
428 0 : stack->txh.compositor->video_out->Blit(stack->txh.compositor->video_out, NULL, NULL, NULL, 1);
429 : }
430 52 : stack->flags |= CTX_APP_DIRTY;
431 :
432 52 : }
433 :
434 18863 : DrawableContext *b2d_get_context(M_Background2D *node, GF_List *from_stack)
435 : {
436 18863 : Background2DStack *stack = (Background2DStack *)gf_node_get_private((GF_Node *)node);
437 18863 : BackgroundStatus *status = b2d_get_status(stack, from_stack);
438 18863 : if (status) {
439 18863 : status->ctx.bi = &status->bi;
440 18863 : return &status->ctx;
441 : }
442 : return NULL;
443 : }
444 :
445 :
446 :
447 41079 : static void UpdateBackgroundTexture(GF_TextureHandler *txh)
448 : {
449 41079 : gf_sc_texture_update_frame(txh, 0);
450 :
451 41079 : if (!txh->compositor->player && !txh->compositor->passthrough_txh && txh->stream && txh->stream->odm && (txh->stream->odm->flags & GF_ODM_PASSTHROUGH)) {
452 290 : if (!txh->width || ((txh->width==txh->compositor->display_width) && (txh->height==txh->compositor->display_height)))
453 290 : txh->compositor->passthrough_txh = txh;
454 : else
455 0 : txh->compositor->passthrough_txh = NULL;
456 : }
457 :
458 : /*restart texture if needed (movie background controled by MediaControl)*/
459 41079 : if (txh->stream_finished && gf_mo_get_loop(txh->stream, 0))
460 0 : gf_sc_texture_restart(txh);
461 41079 : }
462 :
463 622 : void compositor_init_background2d(GF_Compositor *compositor, GF_Node *node)
464 : {
465 : Background2DStack *ptr;
466 622 : GF_SAFEALLOC(ptr, Background2DStack);
467 622 : if (!ptr) {
468 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to allocate background2D stack\n"));
469 : return;
470 : }
471 :
472 622 : ptr->status_stack = gf_list_new();
473 622 : ptr->reg_stacks = gf_list_new();
474 : /*setup drawable object for background*/
475 622 : ptr->drawable = drawable_stack_new(compositor, node);
476 622 : ptr->drawable->flags = DRAWABLE_USE_TRAVERSE_DRAW;
477 622 : ((M_Background2D *)node)->on_set_bind = b2D_set_bind;
478 :
479 :
480 622 : gf_sc_texture_setup(&ptr->txh, compositor, node);
481 622 : ptr->txh.update_texture_fcnt = UpdateBackgroundTexture;
482 622 : ptr->txh.flags = GF_SR_TEXTURE_REPEAT_S | GF_SR_TEXTURE_REPEAT_T;
483 622 : ptr->flags = CTX_IS_BACKGROUND;
484 :
485 622 : gf_node_set_private(node, ptr);
486 622 : gf_node_set_callback_function(node, TraverseBackground2D);
487 : }
488 :
489 319 : void compositor_background2d_modified(GF_Node *node)
490 : {
491 : M_Background2D *bck = (M_Background2D *)node;
492 319 : Background2DStack *st = (Background2DStack *) gf_node_get_private(node);
493 319 : if (!st) return;
494 :
495 : /*dirty node and parents in order to trigger parent visual redraw*/
496 319 : gf_node_dirty_set(node, 0, 1);
497 :
498 : /*if open and changed, stop and play*/
499 319 : if (st->txh.is_open) {
500 9 : if (! gf_sc_texture_check_url_change(&st->txh, &bck->url)) return;
501 1 : gf_sc_texture_stop(&st->txh);
502 1 : gf_sc_texture_play(&st->txh, &bck->url);
503 1 : return;
504 : }
505 : /*if not open and changed play*/
506 310 : if (bck->url.count)
507 0 : gf_sc_texture_play(&st->txh, &bck->url);
508 310 : gf_sc_invalidate(st->txh.compositor, NULL);
509 : }
510 :
511 : #if 0 //unused
512 : Bool compositor_background_transparent(GF_Node *node)
513 : {
514 : if (node && (gf_node_get_tag(node) == TAG_MPEG4_Background2D)) {
515 : Background2DStack *st;
516 : if (!((M_Background2D *)node)->isBound) return 1;
517 :
518 : st = (Background2DStack *) gf_node_get_private(node);
519 : if (st->txh.transparent) return 1;
520 : return 0;
521 : }
522 : /*consider all other background nodes transparent*/
523 : return 1;
524 : }
525 : #endif
526 :
527 :
528 : #endif /*GPAC_DISABLE_VRML*/
|