📄 render2d.c
字号:
Bool R2D_IsPixelMetrics(GF_Node *n){ GF_SceneGraph *sg = gf_node_get_graph(n); return gf_sg_use_pixel_metrics(sg);}static GF_Err R2D_RecomputeAR(GF_VisualRenderer *vr){ Double ratio; GF_Event evt; u32 out_width, out_height; Fixed scaleX, scaleY; Render2D *sr = (Render2D *)vr->user_priv; if (!sr->compositor->scene_height || !sr->compositor->scene_width) return GF_OK; if (!sr->compositor->height || !sr->compositor->width) return GF_OK; sr->cur_width = sr->compositor->scene_width; sr->cur_height = sr->compositor->scene_height; sr->offset_x = sr->offset_y = 0; /*force complete clean*/ sr->top_effect->invalidate_all = 1; if (!sr->compositor->has_size_info && !(sr->compositor->override_size_flags & 2) ) { sr->cur_width = sr->compositor->width; sr->cur_height = sr->compositor->height; R2D_SetScaling(sr, FIX_ONE, FIX_ONE); /*and resize hardware surface*/ evt.type = GF_EVENT_VIDEO_SETUP; evt.size.width = sr->cur_width; evt.size.height = sr->cur_height; return sr->compositor->video_out->ProcessEvent(sr->compositor->video_out, &evt); } out_width = sr->compositor->width; out_height = sr->compositor->height; switch (sr->compositor->aspect_ratio) { case GF_ASPECT_RATIO_FILL_SCREEN: break; case GF_ASPECT_RATIO_16_9: out_width = sr->compositor->width; out_height = 9 * sr->compositor->width / 16; if (out_height>sr->compositor->height) { out_height = sr->compositor->height; out_width = 16 * sr->compositor->height / 9; } break; case GF_ASPECT_RATIO_4_3: out_width = sr->compositor->width; out_height = 3 * sr->compositor->width / 4; if (out_height>sr->compositor->height) { out_height = sr->compositor->height; out_width = 4 * sr->compositor->height / 3; } break; default: ratio = sr->compositor->scene_height; ratio /= sr->compositor->scene_width; if (out_width * ratio > out_height) { out_width = out_height * sr->compositor->scene_width; out_width /= sr->compositor->scene_height; } else { out_height = out_width * sr->compositor->scene_height; out_height /= sr->compositor->scene_width; } break; } sr->offset_x = (sr->compositor->width - out_width) / 2; sr->offset_y = (sr->compositor->height - out_height) / 2; scaleX = gf_divfix(INT2FIX(out_width), INT2FIX(sr->compositor->scene_width)); scaleY = gf_divfix(INT2FIX(out_height), INT2FIX(sr->compositor->scene_height)); if (!sr->scalable_zoom) { sr->cur_width = sr->compositor->scene_width; sr->cur_height = sr->compositor->scene_height; out_width = FIX2INT(gf_divfix(INT2FIX(sr->compositor->width), scaleX)); out_height = FIX2INT(gf_divfix(INT2FIX(sr->compositor->height), scaleY)); sr->offset_x = (out_width - sr->cur_width) / 2; sr->offset_y = (out_height - sr->cur_height) / 2; scaleX = scaleY = FIX_ONE; } else { sr->cur_width = out_width; sr->cur_height = out_height; out_width = sr->compositor->width; out_height = sr->compositor->height; } /*set scale factor*/ R2D_SetScaling(sr, scaleX, scaleY); gf_sr_invalidate(sr->compositor, NULL); /*and resize hardware surface*/ evt.type = GF_EVENT_VIDEO_SETUP; evt.size.width = out_width; evt.size.height = out_height; return sr->compositor->video_out->ProcessEvent(sr->compositor->video_out, &evt);}GF_Node *R2D_PickNode(GF_VisualRenderer *vr, s32 X, s32 Y){ GF_Node *res = NULL; Render2D *sr = (Render2D *)vr->user_priv; if (!sr) return NULL; /*lock to prevent any change while picking*/ gf_sr_lock(sr->compositor, 1); if (sr->compositor->scene) { R2D_MapCoordsToAR(sr, &X, &Y); res = VS2D_PickNode(sr->surface, INT2FIX(X), INT2FIX(Y) ); } gf_sr_lock(sr->compositor, 0); return res;}GF_Err R2D_GetSurfaceAccess(VisualSurface2D *surf){ GF_Err e; Render2D *sr = surf->render; if (!surf->the_surface) return GF_BAD_PARAM; sr->locked = 0; e = GF_IO_ERR; /*try from device*/ if (sr->compositor->r2d->surface_attach_to_device && sr->compositor->video_out->LockOSContext) { sr->hardware_context = sr->compositor->video_out->LockOSContext(sr->compositor->video_out, 1); if (sr->hardware_context) { e = sr->compositor->r2d->surface_attach_to_device(surf->the_surface, sr->hardware_context, sr->cur_width, sr->cur_height); if (!e) { surf->is_attached = 1; GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render2D] Video surface handle attached to raster\n")); return GF_OK; } sr->compositor->video_out->LockOSContext(sr->compositor->video_out, 0); GF_LOG(GF_LOG_ERROR, GF_LOG_RENDER, ("[Render2D] Cannot attach video surface handle to raster: %s\n", gf_error_to_string(e) )); } } /*TODO - collect hw accelerated blit routines if any*/ if (sr->compositor->video_out->LockBackBuffer(sr->compositor->video_out, &sr->hw_surface, 1)==GF_OK) { sr->locked = 1; e = sr->compositor->r2d->surface_attach_to_buffer(surf->the_surface, sr->hw_surface.video_buffer, sr->hw_surface.width, sr->hw_surface.height, sr->hw_surface.pitch, (GF_PixelFormat) sr->hw_surface.pixel_format); if (!e) { surf->is_attached = 1; GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render2D] Video surface memory attached to raster\n")); return GF_OK; } GF_LOG(GF_LOG_ERROR, GF_LOG_RENDER, ("[Render2D] Cannot attach video surface memory to raster: %s\n", gf_error_to_string(e) )); sr->compositor->video_out->LockBackBuffer(sr->compositor->video_out, &sr->hw_surface, 0); } sr->locked = 0; surf->is_attached = 0; return e; }void R2D_ReleaseSurfaceAccess(VisualSurface2D *surf){ Render2D *sr = surf->render; if (surf->is_attached) { sr->compositor->r2d->surface_detach(surf->the_surface); surf->is_attached = 0; } if (sr->hardware_context) { sr->compositor->video_out->LockOSContext(sr->compositor->video_out, 0); sr->hardware_context = NULL; } else if (sr->locked) { sr->compositor->video_out->LockBackBuffer(sr->compositor->video_out, &sr->hw_surface, 0); sr->locked = 0; }}Bool R2D_SupportsFormat(VisualSurface2D *surf, u32 pixel_format){ switch (pixel_format) { case GF_PIXEL_RGB_24: case GF_PIXEL_BGR_24: case GF_PIXEL_RGB_555: case GF_PIXEL_RGB_565: case GF_PIXEL_ARGB: case GF_PIXEL_RGBA: case GF_PIXEL_YV12: case GF_PIXEL_IYUV: case GF_PIXEL_I420: return 1; /*the rest has to be displayed through brush for now, we only use YUV and RGB pool*/ default: return 0; }}void R2D_DrawBitmap(VisualSurface2D *surf, struct _gf_sr_texture_handler *txh, GF_IRect *clip, GF_Rect *unclip, u8 alpha, u32 *col_key, GF_ColorMatrix *cmat){ GF_VideoSurface video_src; Fixed w_scale, h_scale, tmp; GF_Err e; Bool use_soft_stretch; GF_Window src_wnd, dst_wnd; u32 start_x, start_y, cur_width, cur_height; GF_IRect clipped_final = *clip; GF_Rect final = *unclip; if (!txh->data) return; if (!surf->render->compositor->has_size_info && !(surf->render->compositor->msg_type & GF_SR_CFG_OVERRIDE_SIZE) && (surf->render->compositor->override_size_flags & 1) && !(surf->render->compositor->override_size_flags & 2) ) { if ( (surf->render->compositor->scene_width < txh->width) || (surf->render->compositor->scene_height < txh->height)) { surf->render->compositor->scene_width = txh->width; surf->render->compositor->scene_height = txh->height; surf->render->compositor->msg_type |= GF_SR_CFG_OVERRIDE_SIZE; return; } } /*this should never happen but we check for float rounding safety*/ if (final.width<=0 || final.height <=0) return; w_scale = final.width / txh->width; h_scale = final.height / txh->height; /*take care of pixel rounding for odd width/height and make sure we strictly draw in the clipped bounds*/ cur_width = surf->render->cur_width; cur_height = surf->render->cur_height; if (surf->center_coords) { if (cur_width % 2) { clipped_final.x += (cur_width-1) / 2; final.x += INT2FIX( (cur_width-1) / 2 ); } else { clipped_final.x += cur_width / 2; final.x += INT2FIX( cur_width / 2 ); } if (cur_height % 2) { clipped_final.y = (cur_height-1) / 2 - clipped_final.y; final.y = INT2FIX( (cur_height - 1) / 2) - final.y; } else { clipped_final.y = cur_height/ 2 - clipped_final.y; final.y = INT2FIX( cur_height / 2) - final.y; } } else { final.x -= surf->render->offset_x; clipped_final.x -= surf->render->offset_x; final.y -= surf->render->offset_y + final.height; clipped_final.y -= surf->render->offset_y + clipped_final.height; } /*make sure we lie in the final rect (this is needed for directRender mode)*/ if (clipped_final.x<0) { clipped_final.width += clipped_final.x; clipped_final.x = 0; if (clipped_final.width <= 0) return; } if (clipped_final.y<0) { clipped_final.height += clipped_final.y; clipped_final.y = 0; if (clipped_final.height <= 0) return; } if (clipped_final.x + clipped_final.width > (s32) cur_width) { clipped_final.width = cur_width - clipped_final.x; clipped_final.x = cur_width - clipped_final.width; } if (clipped_final.y + clipped_final.height > (s32) cur_height) { clipped_final.height = cur_height - clipped_final.y; clipped_final.y = cur_height - clipped_final.height; } /*needed in direct rendering since clipping is not performed*/ if (clipped_final.width<=0 || clipped_final.height <=0) return; /*compute X offset in src bitmap*/ start_x = 0; tmp = INT2FIX(clipped_final.x); if (tmp >= final.x) start_x = FIX2INT( gf_divfix(tmp - final.x, w_scale) ); /*compute Y offset in src bitmap*/ start_y = 0; tmp = INT2FIX(clipped_final.y); if (tmp >= final.y) start_y = FIX2INT( gf_divfix(tmp - final.y, h_scale) ); /*add AR offset */ clipped_final.x += surf->render->offset_x; clipped_final.y += surf->render->offset_y; dst_wnd.x = (u32) clipped_final.x; dst_wnd.y = (u32) clipped_final.y; dst_wnd.w = (u32) clipped_final.width; dst_wnd.h = (u32) clipped_final.height; src_wnd.w = FIX2INT( gf_divfix(INT2FIX(dst_wnd.w), w_scale) ); src_wnd.h = FIX2INT( gf_divfix(INT2FIX(dst_wnd.h), h_scale) ); if (src_wnd.w>txh->width) src_wnd.w=txh->width; if (src_wnd.h>txh->height) src_wnd.h=txh->height; src_wnd.x = start_x; src_wnd.y = start_y; if (!src_wnd.w || !src_wnd.h) return; /*make sure we lie in src bounds*/ if (src_wnd.x + src_wnd.w>txh->width) src_wnd.w = txh->width - src_wnd.x; if (src_wnd.y + src_wnd.h>txh->height) src_wnd.h = txh->height - src_wnd.y; use_soft_stretch = 1; if (!cmat && (alpha==0xFF) && surf->render->compositor->video_out->Blit) { u32 hw_caps = surf->render->compositor->video_out->hw_caps; /*get the right surface and copy the part of the image on it*/ switch (txh->pixelformat) { case GF_PIXEL_RGB_24: case GF_PIXEL_BGR_24: use_soft_stretch = 0; break; case GF_PIXEL_YV12: case GF_PIXEL_IYUV: case GF_PIXEL_I420: if (surf->render->enable_yuv_hw && (hw_caps & GF_VIDEO_HW_HAS_YUV)) use_soft_stretch = 0; break; default: break; } if (col_key && (GF_COL_A(*col_key) || !(hw_caps & GF_VIDEO_HW_HAS_COLOR_KEY))) use_soft_stretch = 1; } /*most graphic cards can't perform bliting on locked surface - force unlock by releasing the hardware*/ VS2D_TerminateSurface(surf); video_src.height = txh->height; video_src.width = txh->width; video_src.pitch = txh->stride; video_src.pixel_format = txh->pixelformat; video_src.video_buffer = txh->data; if (!use_soft_stretch) { e = surf->render->compositor->video_out->Blit(surf->render->compositor->video_out, &video_src, &src_wnd, &dst_wnd, col_key); /*HW pb, try soft*/ if (e) { GF_LOG(GF_LOG_ERROR, GF_LOG_RENDER, ("[Render 2D] Error during hardware blit - trying with soft one\n")); use_soft_stretch = 1; } } if (use_soft_stretch) { GF_VideoSurface backbuffer; e = surf->render->compositor->video_out->LockBackBuffer(surf->render->compositor->video_out, &backbuffer, 1); gf_stretch_bits(&backbuffer, &video_src, &dst_wnd, &src_wnd, 0, alpha, 0, col_key, cmat); e = surf->render->compositor->video_out->LockBackBuffer(surf->render->compositor->video_out, &backbuffer, 0); } VS2D_InitSurface(surf);}GF_Err R2D_LoadRenderer(GF_VisualRenderer *vr, GF_Renderer *compositor){ Render2D *sr; const char *sOpt; if (vr->user_priv) return GF_BAD_PARAM; GF_SAFEALLOC(sr, Render2D); if (!sr) return GF_OUT_OF_MEM; sr->compositor = compositor; sr->strike_bank = gf_list_new(); sr->surfaces_2D = gf_list_new(); GF_SAFEALLOC(sr->top_effect, RenderEffect2D); sr->top_effect->sensors = gf_list_new(); sr->sensors = gf_list_new(); /*and create main surface*/ sr->surface = NewVisualSurface2D(); sr->surface->GetSurfaceAccess = R2D_GetSurfaceAccess; sr->surface->ReleaseSurfaceAccess = R2D_ReleaseSurfaceAccess; sr->surface->DrawBitmap = R2D_DrawBitmap; sr->surface->SupportsFormat = R2D_SupportsFormat; sr->surface->render = sr; gf_list_add(sr->surfaces_2D, sr->surface); sr->zoom = sr->scale_x = sr->scale_y = FIX_ONE; vr->user_priv = sr; sOpt = gf_cfg_get_key(compositor->user->config, "Render2D", "FocusHighlightFill"); if (sOpt) sscanf(sOpt, "%x", &sr->highlight_fill); sOpt = gf_cfg_get_key(compositor->user->config, "Render2D", "FocusHighlightStroke"); if (sOpt) sscanf(sOpt, "%x", &sr->highlight_stroke); else sr->highlight_stroke = 0xFF000000; /*create a drawable for focus highlight*/ sr->focus_highlight = drawable_new(); /*associate a dummy node for rendering*/ sr->focus_highlight->node = gf_node_new(NULL, TAG_UndefinedNode); gf_node_register(sr->focus_highlight->node, NULL); gf_node_set_callback_function(sr->focus_highlight->node, drawable_render_focus);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -