static Bool composite2d_draw_bitmap(GF_VisualManager *visual, GF_TraverseState *tr_state, struct _drawable_context *ctx, GF_ColorKey *col_key) { u8 alpha = 0xFF; GF_VideoSurface offscreen_dst, video_src; GF_Window src_wnd, dst_wnd; Bool use_blit, has_scale; CompositeTextureStack *st; if (visual->compositor->disable_composite_blit) return 0; if (!ctx->aspect.fill_texture) return 1; if (ctx->transform.m[0]<0) return 0; if (ctx->transform.m[4]<0) { if (!(ctx->flags & CTX_FLIPED_COORDS)) return 0; } else { if (ctx->flags & CTX_FLIPED_COORDS) return 0; } if (ctx->transform.m[1] || ctx->transform.m[3]) return 0; #ifndef GPAC_DISABLE_VRML if ((ctx->flags & CTX_HAS_APPEARANCE) && ctx->appear && ((M_Appearance*)ctx->appear)->textureTransform) return 0; #endif alpha = GF_COL_A(ctx->aspect.fill_color); /*THIS IS A HACK, will not work when setting filled=0, transparency and XLineProps*/ if (!alpha) alpha = GF_COL_A(ctx->aspect.line_color); if (!alpha) return 1; st = (CompositeTextureStack *) gf_node_get_private(visual->offscreen); if (!compositor_texture_rectangles(visual, ctx->aspect.fill_texture, &ctx->bi->clip, &ctx->bi->unclip, &src_wnd, &dst_wnd, &use_blit, &has_scale)) return 1; memset(&video_src, 0, sizeof(GF_VideoSurface)); video_src.height = ctx->aspect.fill_texture->height; video_src.width = ctx->aspect.fill_texture->width; video_src.pitch_x = 0; video_src.pitch_y = ctx->aspect.fill_texture->stride; video_src.pixel_format = ctx->aspect.fill_texture->pixelformat; #ifdef GF_SR_USE_DEPTH if (ctx->aspect.fill_texture->pixelformat==GF_PIXEL_YUVD) video_src.pixel_format = GF_PIXEL_YV12; #endif video_src.video_buffer = ctx->aspect.fill_texture->data; memset(&offscreen_dst, 0, sizeof(GF_VideoSurface)); offscreen_dst.width = st->txh.width; offscreen_dst.height = st->txh.height; offscreen_dst.pitch_y = st->txh.stride; offscreen_dst.pixel_format = st->txh.pixelformat; offscreen_dst.video_buffer = st->txh.data; gf_stretch_bits(&offscreen_dst, &video_src, &dst_wnd, &src_wnd, alpha, 0, col_key, ctx->col_mat); return 1; }
void visual_2d_texture_path_extended(GF_VisualManager *visual, GF_Path *path, GF_TextureHandler *txh, struct _drawable_context *ctx, GF_Rect *orig_bounds, GF_Matrix2D *ext_mx, GF_TraverseState *tr_state) { Fixed sS, sT; u32 tx_tile; GF_STENCIL tx_raster; GF_Matrix2D mx_texture; GF_Rect orig_rc; GF_Raster2D *raster; if (! visual->CheckAttached(visual) ) return; raster = visual->compositor->rasterizer; if (!txh) txh = ctx->aspect.fill_texture; if (!txh) return; if (!txh->tx_io) { gf_node_dirty_set(txh->owner, 0, 1); txh->needs_refresh=1; return; } /*this is gradient draw*/ if (txh->compute_gradient_matrix) { visual_2d_draw_gradient(visual, path, txh, ctx, tr_state, ext_mx, orig_bounds); return; } #ifndef GPAC_DISABLE_3D if (visual->compositor->hybrid_opengl) { visual_2d_texture_path_opengl_auto(visual, path, txh, ctx, orig_bounds, ext_mx, tr_state); return; } #endif if (txh->flags & GF_SR_TEXTURE_PRIVATE_MEDIA) { GF_Window src, dst; visual_2d_fill_path(visual, ctx, NULL, tr_state, 0); /*if texture not ready, update the size before computing output rectangles */ if (!txh->width || !txh->height) { gf_mo_get_visual_info(txh->stream, &txh->width, &txh->height, &txh->stride, &txh->pixel_ar, &txh->pixelformat, &txh->is_flipped); /*in case the node is an MPEG-4 bitmap, force stack rebuild at next frame */ gf_node_dirty_set(ctx->drawable->node, GF_SG_NODE_DIRTY, 1); } if (compositor_texture_rectangles(visual, txh, &ctx->bi->clip, &ctx->bi->unclip, &src, &dst, NULL, NULL)) { if (txh->stream && gf_mo_set_position(txh->stream, &src, &dst)) { gf_mo_get_visual_info(txh->stream, &txh->width, &txh->height, &txh->stride, &txh->pixel_ar, &txh->pixelformat, &txh->is_flipped); /*force dirty flag to get called again*/ gf_node_dirty_set(ctx->drawable->node, GF_SG_NODE_DIRTY, 1); gf_sc_next_frame_state(visual->compositor, GF_SC_DRAW_FRAME); } } return; } if (!gf_sc_texture_push_image(txh, 0, 1)) return; tx_raster = gf_sc_texture_get_stencil(txh); /*setup quality even for background (since quality concerns images)*/ visual_2d_set_options(visual->compositor, visual->raster_surface, ctx->flags & CTX_IS_TEXT, ctx->flags & CTX_NO_ANTIALIAS); /*get original bounds*/ if (orig_bounds) { orig_rc = *orig_bounds; } else { gf_path_get_bounds(path, &orig_rc); } /*get scaling ratio so that active texture view is stretched to original bounds (std 2D shape texture mapping in MPEG4)*/ sS = orig_rc.width / txh->width; sT = orig_rc.height / txh->height; gf_mx2d_init(mx_texture); gf_mx2d_add_scale(&mx_texture, sS, sT); #ifndef GPAC_DISABLE_VRML /*apply texture transform*/ if (ctx->flags & CTX_HAS_APPEARANCE) { GF_Matrix2D tex_trans; visual_2d_get_texture_transform(ctx->appear, txh, &tex_trans, (txh == ctx->aspect.fill_texture) ? 0 : 1, txh->width * sS, txh->height * sT); gf_mx2d_add_matrix(&mx_texture, &tex_trans); } #endif /*move to bottom-left corner of bounds */ gf_mx2d_add_translation(&mx_texture, (orig_rc.x), (orig_rc.y - orig_rc.height)); if (ext_mx) gf_mx2d_add_matrix(&mx_texture, ext_mx); /*move to final coordinate system (except background which is built directly in final coord system)*/ if (!(ctx->flags & CTX_IS_BACKGROUND) ) gf_mx2d_add_matrix(&mx_texture, &ctx->transform); /*set path transform*/ raster->stencil_set_matrix(tx_raster, &mx_texture); tx_tile = 0; if (txh->flags & GF_SR_TEXTURE_REPEAT_S) tx_tile |= GF_TEXTURE_REPEAT_S; if (txh->flags & GF_SR_TEXTURE_REPEAT_T) tx_tile |= GF_TEXTURE_REPEAT_T; if (ctx->flags & CTX_FLIPED_COORDS) tx_tile |= GF_TEXTURE_FLIP; raster->stencil_set_tiling(tx_raster, (GF_TextureTiling) tx_tile); if (!(ctx->flags & CTX_IS_BACKGROUND) ) { u8 a = GF_COL_A(ctx->aspect.fill_color); if (!a) a = GF_COL_A(ctx->aspect.line_color); /*texture alpha scale is the original material transparency, NOT the one after color transform*/ raster->stencil_set_alpha(tx_raster, a ); raster->stencil_set_color_matrix(tx_raster, ctx->col_mat); raster->surface_set_matrix(visual->raster_surface, &ctx->transform); } else { raster->surface_set_matrix(visual->raster_surface, NULL); } txh->flags |= GF_SR_TEXTURE_USED; /*push path & draw*/ raster->surface_set_path(visual->raster_surface, path); visual_2d_fill_path(visual, ctx, tx_raster, tr_state, 0); raster->surface_set_path(visual->raster_surface, NULL); ctx->flags |= CTX_PATH_FILLED; }