📄 dx_2d.c
字号:
if ((dst_w==src_w) && (dst_h==src_h)) { flags = DDBLTFAST_WAIT; if (key) flags |= DDBLTFAST_SRCCOLORKEY; if (dst_wnd) { left = r_dst.left; top = r_dst.top; } else left = top = 0; hr = IDirectDrawSurface_BltFast(dd->pBack, left, top, src->pSurface, src_wnd ? &r_src : NULL, flags); } else { flags = DDBLT_WAIT; if (key) flags |= DDBLT_KEYSRC; hr = IDirectDrawSurface_Blt(dd->pBack, dst_wnd ? &r_dst : NULL, src->pSurface, src_wnd ? &r_src : NULL, flags, NULL); } return FAILED(hr) ? GF_IO_ERR : GF_OK;}static Bool pixelformat_yuv(u32 pixel_format){ switch (pixel_format) { case GF_PIXEL_YUY2: case GF_PIXEL_YVYU: case GF_PIXEL_UYVY: case GF_PIXEL_VYUY: case GF_PIXEL_Y422: case GF_PIXEL_UYNV: case GF_PIXEL_YUNV: case GF_PIXEL_V422: case GF_PIXEL_YV12: case GF_PIXEL_IYUV: case GF_PIXEL_I420: return 1; default: return 0; }}static u32 get_win_4CC(u32 pixel_format){ switch (pixel_format) { case GF_PIXEL_YUY2: return mmioFOURCC('Y', 'U', 'Y', '2'); case GF_PIXEL_YVYU: return mmioFOURCC('Y', 'V', 'Y', 'U'); case GF_PIXEL_UYVY: return mmioFOURCC('U', 'Y', 'V', 'Y'); case GF_PIXEL_VYUY: return mmioFOURCC('V', 'Y', 'U', 'Y'); case GF_PIXEL_Y422: return mmioFOURCC('Y', '4', '2', '2'); case GF_PIXEL_UYNV: return mmioFOURCC('U', 'Y', 'N', 'V'); case GF_PIXEL_YUNV: return mmioFOURCC('Y', 'U', 'N', 'V'); case GF_PIXEL_V422: return mmioFOURCC('V', '4', '2', '2'); case GF_PIXEL_YV12: return mmioFOURCC('Y', 'V', '1', '2'); case GF_PIXEL_IYUV: return mmioFOURCC('I', 'Y', 'U', 'V'); case GF_PIXEL_I420: return mmioFOURCC('I', '4', '2', '0'); default: return 0; }}static DDSurface *DD_GetSurface(GF_VideoOutput *dr, u32 width, u32 height, u32 pixel_format){#ifdef USE_DX_3 DDSURFACEDESC ddsd;#else DDSURFACEDESC2 ddsd;#endif HRESULT hr; DDCONTEXT; /*yuv format*/ if (pixelformat_yuv(pixel_format)) { if (dr->yuv_pixel_format) { /*don't recreate a surface if not needed*/ if (dd->yuv_pool.pSurface && (dd->yuv_pool.width >= width) && (dd->yuv_pool.height >= height) ) return &dd->yuv_pool; width = MAX(dd->yuv_pool.width, width); height = MAX(dd->yuv_pool.height, height); SAFE_DD_RELEASE(dd->yuv_pool.pSurface); memset(&dd->yuv_pool, 0, sizeof(DDSurface)); memset (&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat); ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY; ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC; ddsd.dwWidth = width; ddsd.dwHeight = height; ddsd.ddpfPixelFormat.dwFourCC = get_win_4CC(dr->yuv_pixel_format);#ifdef USE_DX_3 if( FAILED( hr = IDirectDraw_CreateSurface(dd->pDD, &ddsd, &dd->yuv_pool.pSurface, NULL ) ) ) return NULL;#else if( FAILED( hr = IDirectDraw7_CreateSurface(dd->pDD, &ddsd, &dd->yuv_pool.pSurface, NULL ) ) ) return NULL;#endif dd->yuv_pool.format = dr->yuv_pixel_format; dd->yuv_pool.width = width; dd->yuv_pool.height = height; return &dd->yuv_pool; } } /*don't recreate a surface if not needed*/ if ((dd->rgb_pool.width >= width) && (dd->rgb_pool.height >= height) ) return &dd->rgb_pool; width = MAX(dd->rgb_pool.width, width); height = MAX(dd->rgb_pool.height, height); SAFE_DD_RELEASE(dd->rgb_pool.pSurface); memset(&dd->rgb_pool, 0, sizeof(DDSurface)); memset (&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; ddsd.dwWidth = width; ddsd.dwHeight = height;#ifdef USE_DX_3 if( FAILED( hr = IDirectDraw_CreateSurface(dd->pDD, &ddsd, &dd->rgb_pool.pSurface, NULL ) ) ) return NULL;#else if( FAILED( hr = IDirectDraw7_CreateSurface(dd->pDD, &ddsd, &dd->rgb_pool.pSurface, NULL ) ) ) return NULL;#endif dd->rgb_pool.width = width; dd->rgb_pool.height = height; dd->rgb_pool.format = dd->pixelFormat; return &dd->rgb_pool;}static GF_Err DD_Blit(GF_VideoOutput *dr, GF_VideoSurface *video_src, GF_Window *src_wnd, GF_Window *dst_wnd, u32 *key){ GF_VideoSurface temp_surf; GF_Err e; GF_Window src_wnd_2; u32 w, h; DDSurface *pool; DDCONTEXT; if (src_wnd) { w = src_wnd->w; h = src_wnd->h; } else { w = video_src->width; h = video_src->height; } /*get RGB or YUV pool surface*/ pool = DD_GetSurface(dr, w, h, key ? dd->pixelFormat : video_src->pixel_format); if (!pool) return GF_IO_ERR; temp_surf.pixel_format = pool->format; e = DD_LockSurface(dd, &temp_surf, pool->pSurface); if (e) return e; /*copy pixels to pool*/ dx_copy_pixels(&temp_surf, video_src, src_wnd); e = DD_UnlockSurface(dd, pool->pSurface); if (e) return e; src_wnd_2.x = src_wnd_2.y = 0; if (src_wnd) { src_wnd_2.w = src_wnd->w; src_wnd_2.h = src_wnd->h; } else { src_wnd_2.w = video_src->width; src_wnd_2.h = video_src->height; } /*and blit surface*/ return DD_BlitSurface(dd, pool, &src_wnd_2, dst_wnd, key);}static GFINLINE u32 is_yuv_supported(u32 win_4cc){ if (win_4cc==get_win_4CC(GF_PIXEL_YV12)) return GF_PIXEL_YV12; else if (win_4cc==get_win_4CC(GF_PIXEL_I420)) return GF_PIXEL_I420; else if (win_4cc==get_win_4CC(GF_PIXEL_IYUV)) return GF_PIXEL_IYUV; else if (win_4cc==get_win_4CC(GF_PIXEL_UYVY)) return GF_PIXEL_UYVY; else if (win_4cc==get_win_4CC(GF_PIXEL_Y422)) return GF_PIXEL_Y422; else if (win_4cc==get_win_4CC(GF_PIXEL_UYNV)) return GF_PIXEL_UYNV; else if (win_4cc==get_win_4CC(GF_PIXEL_YUY2)) return GF_PIXEL_YUY2; else if (win_4cc==get_win_4CC(GF_PIXEL_YUNV)) return GF_PIXEL_YUNV; else if (win_4cc==get_win_4CC(GF_PIXEL_V422)) return GF_PIXEL_V422; else if (win_4cc==get_win_4CC(GF_PIXEL_YVYU)) return GF_PIXEL_YVYU; else return 0;}static GFINLINE Bool is_yuv_planar(u32 format){ switch (format) { case GF_PIXEL_YV12: case GF_PIXEL_I420: case GF_PIXEL_IYUV: return 1; default: return 0; }}#define YUV_NUM_TEST 20/*gets fastest YUV format for YUV to RGB blit from YUV overlay (support is quite random on most cards)*/void DD_InitYUV(GF_VideoOutput *dr){ u32 w, h, j, i, num_yuv; DWORD numCodes; DWORD formats[30]; DWORD *codes; u32 now, min_packed = 0xFFFFFFFF, min_planar = 0xFFFFFFFF; u32 best_packed = 0, best_planar = 0; Bool checkPacked = TRUE; DDCONTEXT; w = 320; h = 240; dd->yuv_init = 1;#ifdef USE_DX_3 IDirectDraw_GetFourCCCodes(dd->pDD, &numCodes, NULL); if (!numCodes) return; codes = (DWORD *)malloc(numCodes*sizeof(DWORD)); IDirectDraw_GetFourCCCodes(dd->pDD, &numCodes, codes);#else IDirectDraw7_GetFourCCCodes(dd->pDD, &numCodes, NULL); if (!numCodes) return; codes = (DWORD *)malloc(numCodes*sizeof(DWORD)); IDirectDraw7_GetFourCCCodes(dd->pDD, &numCodes, codes);#endif num_yuv = 0; for (i=0; i<numCodes; i++) { formats[num_yuv] = is_yuv_supported(codes[i]); if (formats[num_yuv]) num_yuv++; } free(codes); /*too bad*/ if (!num_yuv) { dr->hw_caps &= ~GF_VIDEO_HW_HAS_YUV; dr->yuv_pixel_format = 0; return; } for (i=0; i<num_yuv; i++) { /*check planar first*/ if (!checkPacked && !is_yuv_planar(formats[i])) goto go_on; /*then check packed */ if (checkPacked && is_yuv_planar(formats[i])) goto go_on; if (dd->yuv_pool.pSurface) { SAFE_DD_RELEASE(dd->yuv_pool.pSurface); memset(&dd->yuv_pool, 0, sizeof(DDSurface)); } dr->yuv_pixel_format = formats[i]; if (DD_GetSurface(dr, w, h, dr->yuv_pixel_format) == NULL) goto rem_fmt; now = gf_sys_clock(); /*perform blank blit*/ for (j=0; j<YUV_NUM_TEST; j++) { if (DD_BlitSurface(dd, &dd->yuv_pool, NULL, NULL, NULL) != GF_OK) goto rem_fmt; } now = gf_sys_clock() - now; if (!checkPacked) { if (now<min_planar) { min_planar = now; best_planar = dr->yuv_pixel_format; } } else { if (now<min_packed) { min_packed = now; best_packed = dr->yuv_pixel_format; } }go_on: if (checkPacked && (i+1==num_yuv)) { i = -1; checkPacked = FALSE; } continue;rem_fmt: for (j=i; j<num_yuv-1; j++) { formats[j] = formats[j+1]; } i--; num_yuv--; } if (dd->yuv_pool.pSurface) { SAFE_DD_RELEASE(dd->yuv_pool.pSurface); memset(&dd->yuv_pool, 0, sizeof(DDSurface)); } /*too bad*/ if (!num_yuv) { dr->hw_caps &= ~GF_VIDEO_HW_HAS_YUV; dr->yuv_pixel_format = 0; return; } if (best_planar && (min_planar < min_packed )) { dr->yuv_pixel_format = best_planar; } else { dr->yuv_pixel_format = best_packed; } dr->hw_caps |= GF_VIDEO_HW_HAS_YUV;}GF_Err DD_SetBackBufferSize(GF_VideoOutput *dr, u32 width, u32 height){ DDCONTEXT; if (dd->is_3D_out) return GF_BAD_PARAM; if (!dd->ddraw_init) return InitDirectDraw(dr, width, height); return CreateBackBuffer(dr, width, height);}void DD_SetupDDraw(GF_VideoOutput *driv){ driv->hw_caps |= GF_VIDEO_HW_HAS_COLOR_KEY; driv->Blit = DD_Blit; driv->LockBackBuffer = DD_LockBackBuffer; driv->LockOSContext = LockOSContext;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -