void group_cache_del(GroupCache *cache) { drawable_del(cache->drawable); if (cache->txh.data) gf_free(cache->txh.data); gf_sc_texture_release(&cache->txh); gf_sc_texture_destroy(&cache->txh); gf_free(cache); }
GF_EXPORT void gf_sc_texture_destroy(GF_TextureHandler *txh) { GF_Compositor *compositor = txh->compositor; Bool lock = gf_mx_try_lock(compositor->mx); gf_sc_texture_release(txh); if (txh->is_open) gf_sc_texture_stop(txh); gf_list_del_item(txh->compositor->textures, txh); if (lock) gf_mx_v(compositor->mx); }
GF_EXPORT GF_Err gf_sc_texture_open(GF_TextureHandler *txh, MFURL *url, Bool lock_scene_timeline) { if (txh->is_open) return GF_BAD_PARAM; /*if existing texture in cache destroy it - we don't destroy it on stop to handle MovieTexture*/ if (txh->tx_io) gf_sc_texture_release(txh); /*get media object*/ txh->stream = gf_mo_register(txh->owner, url, lock_scene_timeline, 0); /*bad/Empty URL*/ if (!txh->stream) return GF_NOT_SUPPORTED; return GF_OK; }
GF_EXPORT GF_Err gf_sc_texture_play_from_to(GF_TextureHandler *txh, MFURL *url, Double start_offset, Double end_offset, Bool can_loop, Bool lock_scene_timeline) { if (txh->is_open) return GF_BAD_PARAM; /*if existing texture in cache destroy it - we don't destroy it on stop to handle MovieTexture*/ if (txh->tx_io) gf_sc_texture_release(txh); /*get media object*/ txh->stream = gf_mo_register(txh->owner, url, lock_scene_timeline, 0); /*bad/Empty URL*/ if (!txh->stream) return GF_NOT_SUPPORTED; /*request play*/ gf_mo_play(txh->stream, start_offset, end_offset, can_loop); txh->last_frame_time = (u32) (-1); //gf_sc_invalidate(txh->compositor, NULL); txh->is_open = 1; return GF_OK; }
static void svg_traverse_filter(GF_Node *node, void *rs, Bool is_destroy) { GF_TraverseState *tr_state = (GF_TraverseState *)rs; GF_FilterStack *st = gf_node_get_private(node); if (is_destroy) { drawable_del(st->drawable); if (st->data) gf_free(st->data); st->txh.data = NULL; gf_sc_texture_release(&st->txh); gf_sc_texture_destroy(&st->txh); gf_free(st); return; } if (tr_state->traversing_mode==TRAVERSE_DRAW_2D) { if (! tr_state->visual->DrawBitmap(tr_state->visual, tr_state, tr_state->ctx, NULL)) { visual_2d_texture_path(tr_state->visual, st->drawable->path, tr_state->ctx, tr_state); } } }
static void composite_update(GF_TextureHandler *txh) { s32 w, h; GF_STENCIL stencil; M_Background2D *back; GF_TraverseState *tr_state; Bool invalidate_all; u32 new_pixel_format; GF_Compositor *compositor = (GF_Compositor *)txh->compositor; CompositeTextureStack *st = (CompositeTextureStack *) gf_node_get_private(txh->owner); GF_Raster2D *raster = st->visual->compositor->rasterizer; if (st->unsupported) return; /* if (compositor->recompute_ar) { gf_node_dirty_set(txh->owner, 0, 0); return; } */ if (!compositor->rebuild_offscreen_textures && (!compositor->text_edit_changed || !st->visual->has_text_edit ) && !gf_node_dirty_get(txh->owner)) { txh->needs_refresh = 0; return; } gf_node_dirty_clear(st->txh.owner, 0); new_pixel_format = 0; back = gf_list_get(st->visual->back_stack, 0); if (back && back->isBound) new_pixel_format = GF_PIXEL_RGB_24; else new_pixel_format = GF_PIXEL_RGBA; #ifdef GPAC_USE_TINYGL /*TinyGL pixel format is fixed at compile time, we cannot override it !*/ if (st->visual->type_3d) new_pixel_format = GF_PIXEL_RGBA; #else #ifndef GPAC_DISABLE_3D /*no alpha support in offscreen rendering*/ if ( (st->visual->type_3d) && !(compositor->video_out->hw_caps & GF_VIDEO_HW_OPENGL_OFFSCREEN_ALPHA)) new_pixel_format = GF_PIXEL_RGB_24; #endif /*in OpenGL_ES, only RGBA can be safelly used with glReadPixels*/ #ifdef GPAC_USE_OGL_ES new_pixel_format = GF_PIXEL_RGBA; #endif #endif /*FIXME - we assume RGB+Depth+bitshape, we should check with the video out module*/ #if defined(GF_SR_USE_DEPTH) && !defined(GPAC_DISABLE_3D) if (st->visual->type_3d && (compositor->video_out->hw_caps & GF_VIDEO_HW_HAS_DEPTH) ) new_pixel_format = GF_PIXEL_RGBDS; #endif #ifndef GPAC_DISABLE_3D if (st->visual->type_3d>1) { w = ((M_CompositeTexture3D*)txh->owner)->pixelWidth; h = ((M_CompositeTexture3D*)txh->owner)->pixelHeight; } else #endif { w = ((M_CompositeTexture2D*)txh->owner)->pixelWidth; h = ((M_CompositeTexture2D*)txh->owner)->pixelHeight; } /*internal GPAC hacks for testing color spaces*/ if (w<-1) { w = -w; if (h<0) { h = -h; if (new_pixel_format==GF_PIXEL_RGBA) { new_pixel_format=GF_PIXEL_ARGB; } else { new_pixel_format=GF_PIXEL_BGR_24; } } else { if (new_pixel_format==GF_PIXEL_RGB_24) { new_pixel_format=GF_PIXEL_RGB_32; } } } else if (h<-1) { h = -h; if (new_pixel_format==GF_PIXEL_RGB_24) { new_pixel_format=GF_PIXEL_RGB_32; } } if (w<0) w = 0; if (h<0) h = 0; if (!w || !h) { if (txh->tx_io) { #ifdef GPAC_USE_TINYGL if (st->tgl_ctx) ostgl_delete_context(st->tgl_ctx); #endif gf_sc_texture_release(txh); if (txh->data) gf_free(txh->data); txh->data = NULL; txh->width = txh->height = txh->stride = 0; } return; } invalidate_all = compositor->rebuild_offscreen_textures; /*rebuild stencil*/ if (!txh->tx_io || (w != (s32) txh->width) || ( h != (s32) txh->height) || (new_pixel_format != txh->pixelformat) ) { Bool needs_stencil = 1; if (txh->tx_io) { #ifdef GPAC_USE_TINYGL if (st->tgl_ctx) ostgl_delete_context(st->tgl_ctx); #endif gf_sc_texture_release(txh); if (txh->data) gf_free(txh->data); txh->data = NULL; } /*we don't use rect ext because of no support for texture transforms*/ if (1 #ifndef GPAC_DISABLE_3D || compositor->gl_caps.npot_texture #endif ) { st->txh.width = w; st->txh.height = h; st->sx = st->sy = FIX_ONE; } else { st->txh.width = 2; while (st->txh.width<(u32)w) st->txh.width*=2; st->txh.height = 2; while (st->txh.height<(u32)h) st->txh.height*=2; st->sx = INT2FIX(st->txh.width) / w; st->sy = INT2FIX(st->txh.height) / h; } gf_sc_texture_allocate(txh); txh->pixelformat = new_pixel_format; switch (new_pixel_format) { case GF_PIXEL_RGBA: case GF_PIXEL_ARGB: txh->stride = txh->width * 4; txh->transparent = 1; break; case GF_PIXEL_RGB_565: txh->stride = txh->width * 2; txh->transparent = 0; break; case GF_PIXEL_RGBDS: txh->stride = txh->width * 4; txh->transparent = 1; break; case GF_PIXEL_RGB_24: txh->stride = txh->width * 3; txh->transparent = 0; break; } st->visual->width = txh->width; st->visual->height = txh->height; stencil = raster->stencil_new(raster, GF_STENCIL_TEXTURE); /*TODO - add support for compositeTexture3D when root is 2D visual*/ #ifndef GPAC_DISABLE_3D if (st->visual->type_3d) { GF_Compositor *compositor = st->visual->compositor; /*figure out what to do if main visual (eg video out) is not in OpenGL ...*/ if (!compositor->visual->type_3d) { /*create an offscreen window for OpenGL rendering*/ if ((compositor->offscreen_width < st->txh.width) || (compositor->offscreen_height < st->txh.height)) { #ifndef GPAC_USE_TINYGL GF_Err e; GF_Event evt; compositor->offscreen_width = MAX(compositor->offscreen_width, st->txh.width); compositor->offscreen_height = MAX(compositor->offscreen_height, st->txh.height); evt.type = GF_EVENT_VIDEO_SETUP; evt.setup.width = compositor->offscreen_width; evt.setup.height = compositor->offscreen_height; evt.setup.back_buffer = 0; evt.setup.opengl_mode = 2; e = compositor->video_out->ProcessEvent(compositor->video_out, &evt); if (e) { gf_sc_texture_release(txh); st->unsupported = 1; return; } /*reload openGL ext*/ gf_sc_load_opengl_extensions(compositor, 1); #endif } } else { needs_stencil = 0; } } #endif if (needs_stencil) { txh->data = (char*)gf_malloc(sizeof(unsigned char) * txh->stride * txh->height); memset(txh->data, 0, sizeof(unsigned char) * txh->stride * txh->height); /*set stencil texture - we don't check error as an image could not be supported by the rasterizer but still supported by the blitter (case of RGBD/RGBDS)*/ raster->stencil_set_texture(stencil, txh->data, txh->width, txh->height, txh->stride, txh->pixelformat, txh->pixelformat, 0); #ifdef GPAC_USE_TINYGL if (st->visual->type_3d && !compositor->visual->type_3d) { st->tgl_ctx = ostgl_create_context(txh->width, txh->height, txh->transparent ? 32 : 24, &txh->data, 1); GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[CompositeTexture] Creating TinyGL Offscreen context %p (%d %d - pf %s)\n", st->tgl_ctx, txh->width, txh->width, gf_4cc_to_str(txh->pixelformat))); } #endif } invalidate_all = 1; gf_sc_texture_set_stencil(txh, stencil); } if (!txh->tx_io) return; stencil = gf_sc_texture_get_stencil(txh); if (!stencil) return; #ifdef GPAC_USE_TINYGL if (st->tgl_ctx) ostgl_make_current(st->tgl_ctx, 0); #endif GF_SAFEALLOC(tr_state, GF_TraverseState); tr_state->vrml_sensors = gf_list_new(); tr_state->visual = st->visual; tr_state->invalidate_all = invalidate_all; tr_state->immediate_draw = st->visual->compositor->traverse_state->immediate_draw; gf_mx2d_init(tr_state->transform); gf_cmx_init(&tr_state->color_mat); tr_state->backgrounds = st->visual->back_stack; tr_state->viewpoints = st->visual->view_stack; tr_state->pixel_metrics = gf_sg_use_pixel_metrics(gf_node_get_graph(st->txh.owner)); tr_state->min_hsize = INT2FIX( MIN(txh->width, txh->height) ) / 2; tr_state->vp_size.x = INT2FIX(txh->width); tr_state->vp_size.y = INT2FIX(txh->height); composite_do_bindable(st->txh.owner, tr_state, st->first); st->first = 0; GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[CompositeTexture] Entering draw cycle\n")); txh->needs_refresh = visual_draw_frame(st->visual, st->txh.owner, tr_state, 0); txh->transparent = (st->visual->last_had_back==2) ? 0 : 1; if (!compositor->edited_text && st->visual->has_text_edit) st->visual->has_text_edit = 0; /*set active viewport in image coordinates top-left=(0, 0), not in BIFS*/ if (0 && gf_list_count(st->visual->view_stack)) { M_Viewport *vp = (M_Viewport *)gf_list_get(st->visual->view_stack, 0); if (vp->isBound) { SFVec2f size = vp->size; if (size.x >=0 && size.y>=0) { /*FIXME - we need tracking of VP changes*/ txh->needs_refresh = 1; } } } if (txh->needs_refresh) { #ifndef GPAC_DISABLE_3D if (st->visual->camera.is_3D) { if (st->visual->compositor->visual->type_3d) { #ifndef GPAC_USE_TINYGL gf_sc_copy_to_texture(&st->txh); #else /*in TinyGL we only need to push associated bitmap to the texture*/ gf_sc_texture_push_image(&st->txh, 0, 0); #endif } else { #ifndef GPAC_USE_TINYGL gf_sc_copy_to_stencil(&st->txh); #else if (txh->pixelformat==GF_PIXEL_RGBDS) gf_get_tinygl_depth(&st->txh); #endif } } else #endif { if (raster->stencil_texture_modified) raster->stencil_texture_modified(stencil); gf_sc_texture_set_stencil(txh, stencil); } gf_sc_invalidate(st->txh.compositor, NULL); } gf_list_del(tr_state->vrml_sensors); gf_free(tr_state); GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[CompositeTexture] Leaving draw cycle\n")); }
GF_EXPORT void gf_sc_texture_update_frame(GF_TextureHandler *txh, Bool disable_resync) { Bool needs_reload = 0; u32 size, ts; s32 ms_until_pres, ms_until_next; /*already refreshed*/ if (txh->needs_refresh) return; if (!txh->stream) { txh->data = NULL; return; } /*should never happen!!*/ if (txh->needs_release) gf_mo_release_data(txh->stream, 0xFFFFFFFF, 0); /*check init flag*/ if (!(gf_mo_get_flags(txh->stream) & GF_MO_IS_INIT)) { needs_reload = 1; txh->data = NULL; if (txh->tx_io) { gf_sc_texture_release(txh); } } txh->data = gf_mo_fetch_data(txh->stream, !disable_resync, &txh->stream_finished, &ts, &size, &ms_until_pres, &ms_until_next); if (!(gf_mo_get_flags(txh->stream) & GF_MO_IS_INIT)) { needs_reload = 1; } else if (size && txh->size && (size != txh->size)) { needs_reload = 1; } if (needs_reload) { /*if we had a texture this means the object has changed - delete texture and resetup. Do not skip texture update as this may lead to an empty rendering pass (blank frame for this object), especially in DASH*/ if (txh->tx_io) { gf_sc_texture_release(txh); txh->needs_refresh = 1; } if (gf_mo_is_private_media(txh->stream)) { setup_texture_object(txh, 1); gf_node_dirty_set(txh->owner, 0, 0); } } /*if no frame or muted don't draw*/ if (!txh->data || !size) { GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("|Visual Texture] No output frame available \n")); /*TODO - check if this is needed */ if (txh->flags & GF_SR_TEXTURE_PRIVATE_MEDIA) { //txh->needs_refresh = 1; gf_sc_invalidate(txh->compositor, NULL); } return; } /*if setup and same frame return*/ if (txh->tx_io && (txh->stream_finished || (txh->last_frame_time==ts)) ) { gf_mo_release_data(txh->stream, 0xFFFFFFFF, 0); txh->needs_release = 0; if (!txh->stream_finished) { if (ms_until_next>0 && (txh->compositor->next_frame_delay > (u32) ms_until_next)) txh->compositor->next_frame_delay = ms_until_next; } return; } txh->needs_release = 1; txh->last_frame_time = ts; txh->size = size; if (txh->raw_memory) { gf_mo_get_raw_image_planes(txh->stream, (u8 **) &txh->data, (u8 **) &txh->pU, (u8 **) &txh->pV); } if (gf_mo_is_muted(txh->stream)) return; if (txh->nb_frames) { s32 push_delay = txh->upload_time / txh->nb_frames; if (push_delay > ms_until_pres) ms_until_pres = 0; else ms_until_pres -= push_delay; } if (txh->compositor->frame_delay < ms_until_pres) txh->compositor->frame_delay = ms_until_pres; txh->compositor->next_frame_delay = 1; if (!txh->tx_io) { setup_texture_object(txh, 0); } /*try to push texture on graphics but don't complain if failure*/ gf_sc_texture_set_data(txh); txh->needs_refresh = 1; gf_sc_invalidate(txh->compositor, NULL); }
GF_EXPORT void gf_sc_texture_update_frame(GF_TextureHandler *txh, Bool disable_resync) { u32 size, ts; /*already refreshed*/ if (txh->needs_refresh) return; if (!txh->stream) { txh->data = NULL; return; } /*should never happen!!*/ if (txh->needs_release) gf_mo_release_data(txh->stream, 0xFFFFFFFF, 0); /*check init flag*/ if (!(gf_mo_get_flags(txh->stream) & GF_MO_IS_INIT)) { /*if we had a texture this means the object has changed - delete texture and force next frame composition (this will take care of OD reuse)*/ if (txh->tx_io) { gf_sc_texture_release(txh); txh->data = NULL; txh->needs_refresh = 1; gf_sc_invalidate(txh->compositor, NULL); return; } if (gf_mo_is_private_media(txh->stream)) { setup_texture_object(txh, 1); gf_node_dirty_set(txh->owner, 0, 0); } } txh->data = gf_mo_fetch_data(txh->stream, !disable_resync, &txh->stream_finished, &ts, &size); /*if no frame or muted don't draw*/ if (!txh->data || !size) { /*TODO - check if this is needed */ if (txh->flags & GF_SR_TEXTURE_PRIVATE_MEDIA) { //txh->needs_refresh = 1; gf_sc_invalidate(txh->compositor, NULL); } return; } /*if setup and same frame return*/ if (txh->tx_io && (txh->stream_finished || (txh->last_frame_time==ts)) ) { gf_mo_release_data(txh->stream, 0xFFFFFFFF, 0); txh->needs_release = 0; return; } txh->needs_release = 1; txh->last_frame_time = ts; if (gf_mo_is_muted(txh->stream)) return; if (!txh->tx_io) { setup_texture_object(txh, 0); } /*try to push texture on graphics but don't complain if failure*/ gf_sc_texture_set_data(txh); txh->needs_refresh = 1; gf_sc_invalidate(txh->compositor, NULL); }
GF_EXPORT void gf_sc_texture_update_frame(GF_TextureHandler *txh, Bool disable_resync) { u32 size, ts; /*already refreshed*/ if (txh->needs_refresh) return; if (!txh->stream) { txh->data = NULL; return; } /*should never happen!!*/ if (txh->needs_release) gf_mo_release_data(txh->stream, 0xFFFFFFFF, 0); /*check init flag*/ if (!(gf_mo_get_flags(txh->stream) & GF_MO_IS_INIT)) { /*if we had a texture this means the object has changed - delete texture and resetup. Do not skip texture update as this may lead to an empty rendering pass (blank frame for this object), especially in DASH*/ if (txh->tx_io) { gf_sc_texture_release(txh); txh->data = NULL; txh->needs_refresh = 1; } if (gf_mo_is_private_media(txh->stream)) { setup_texture_object(txh, 1); gf_node_dirty_set(txh->owner, 0, 0); } } txh->data = gf_mo_fetch_data(txh->stream, !disable_resync, &txh->stream_finished, &ts, &size); /*if no frame or muted don't draw*/ if (!txh->data || !size) { GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("No output frame available\n")); /*TODO - check if this is needed */ if (txh->flags & GF_SR_TEXTURE_PRIVATE_MEDIA) { //txh->needs_refresh = 1; gf_sc_invalidate(txh->compositor, NULL); } return; } /*if setup and same frame return*/ if (txh->tx_io && (txh->stream_finished || (txh->last_frame_time==ts)) ) { gf_mo_release_data(txh->stream, 0xFFFFFFFF, 0); txh->needs_release = 0; return; } txh->needs_release = 1; txh->last_frame_time = ts; if (gf_mo_is_muted(txh->stream)) return; if (!txh->tx_io) { setup_texture_object(txh, 0); } /*try to push texture on graphics but don't complain if failure*/ gf_sc_texture_set_data(txh); txh->needs_refresh = 1; gf_sc_invalidate(txh->compositor, NULL); }
u32 layer3d_setup_offscreen(GF_Node *node, Layer3DStack *st, GF_TraverseState *tr_state, Fixed width, Fixed height) { GF_STENCIL stencil; u32 new_pixel_format, w, h; GF_Compositor *compositor = (GF_Compositor *)st->visual->compositor; if (st->unsupported) return 0; #ifndef GPAC_USE_TINYGL /*no support for offscreen rendering*/ if (!(compositor->video_out->hw_caps & GF_VIDEO_HW_OPENGL_OFFSCREEN)) { st->unsupported = 1; return 0; } #endif /* if (tr_state->visual->compositor->recompute_ar) { gf_node_dirty_set(node, 0, 0); return 0; } */ new_pixel_format = GF_PIXEL_RGBA; #ifndef GPAC_USE_TINYGL // if (!compositor_background_transparent(gf_list_get(tr_state->backgrounds, 0)) ) // new_pixel_format = GF_PIXEL_RGB_24; /*in OpenGL_ES, only RGBA can be safelly used with glReadPixels*/ #ifdef GPAC_USE_OGL_ES new_pixel_format = GF_PIXEL_RGBA; #else /*no support for alpha in offscreen rendering*/ if (!(compositor->video_out->hw_caps & GF_VIDEO_HW_OPENGL_OFFSCREEN_ALPHA)) new_pixel_format = GF_PIXEL_RGB_24; #endif #endif /*FIXME - we assume RGB+Depth+bitshape, we should check with the video out module*/ #if defined(GF_SR_USE_DEPTH) && !defined(GPAC_DISABLE_3D) if (st->visual->type_3d && (compositor->video_out->hw_caps & GF_VIDEO_HW_HAS_DEPTH) ) new_pixel_format = GF_PIXEL_RGBDS; #endif w = (u32) FIX2INT(gf_ceil(width)); h = (u32) FIX2INT(gf_ceil(height)); /*1- some implementation of glReadPixel crash if w||h are not multiple of 4*/ /*2- some implementation of glReadPixel don't behave properly here when texture is not a power of 2*/ w = gf_get_next_pow2(w); if (w>1024) w = 1024; h = gf_get_next_pow2(h); if (h>1024) h = 1024; if (!w || !h) return 0; if (st->txh.tx_io && (new_pixel_format == st->txh.pixelformat) && (w == st->txh.width) && (h == st->txh.height) && (compositor->offscreen_width >= w) && (compositor->offscreen_height >= h) ) return 2; if (st->txh.tx_io) { #ifdef GPAC_USE_TINYGL if (st->tgl_ctx) ostgl_delete_context(st->tgl_ctx); #endif gf_sc_texture_release(&st->txh); if (st->txh.data) gf_free(st->txh.data); st->txh.data = NULL; } st->vp = gf_rect_center(INT2FIX(w), INT2FIX(h) ); st->txh.width = w; st->txh.height = h; gf_sc_texture_allocate(&st->txh); st->txh.pixelformat = new_pixel_format; if (new_pixel_format==GF_PIXEL_RGBA) { st->txh.stride = w * 4; st->txh.transparent = 1; } else if (new_pixel_format==GF_PIXEL_RGBDS) { st->txh.stride = w * 4; st->txh.transparent = 1; } else { st->txh.stride = w * 3; st->txh.transparent = 0; } st->visual->width = w; st->visual->height = h; stencil = compositor->rasterizer->stencil_new(compositor->rasterizer, GF_STENCIL_TEXTURE); #ifndef GPAC_USE_TINYGL /*create an offscreen window for OpenGL rendering*/ if ((compositor->offscreen_width < w) || (compositor->offscreen_height < h)) { GF_Err e; GF_Event evt; compositor->offscreen_width = MAX(compositor->offscreen_width, w); compositor->offscreen_height = MAX(compositor->offscreen_height, h); evt.type = GF_EVENT_VIDEO_SETUP; evt.setup.width = tr_state->visual->compositor->offscreen_width; evt.setup.height = tr_state->visual->compositor->offscreen_height; evt.setup.back_buffer = 0; evt.setup.opengl_mode = 2; e = compositor->video_out->ProcessEvent(compositor->video_out, &evt); if (e) { gf_sc_texture_release(&st->txh); st->unsupported = 1; return 0; } /*reload openGL ext*/ gf_sc_load_opengl_extensions(compositor, 1); } #endif st->txh.data = (char*)gf_malloc(sizeof(unsigned char) * st->txh.stride * st->txh.height); memset(st->txh.data, 0, sizeof(unsigned char) * st->txh.stride * st->txh.height); /*set stencil texture - we don't check error as an image could not be supported by the rasterizer but still supported by the blitter (case of RGBD/RGBDS)*/ compositor->rasterizer->stencil_set_texture(stencil, st->txh.data, st->txh.width, st->txh.height, st->txh.stride, st->txh.pixelformat, st->txh.pixelformat, 0); #ifdef GPAC_USE_TINYGL /*create TinyGL offscreen context*/ st->tgl_ctx = ostgl_create_context(st->txh.width, st->txh.height, st->txh.transparent ? 32 : 24, &st->txh.data, 1); st->scale_x = st->scale_y = FIX_ONE; #else st->scale_x = INT2FIX(w) / tr_state->visual->compositor->offscreen_width; st->scale_y = INT2FIX(h) / tr_state->visual->compositor->offscreen_height; #endif gf_sc_texture_set_stencil(&st->txh, stencil); drawable_reset_path(st->drawable); gf_path_add_rect_center(st->drawable->path, 0, 0, st->clip.width, st->clip.height); return 1; }