Index: libvo/vo_direct3d.c =================================================================== --- libvo/vo_direct3d.c (revision 27999) +++ libvo/vo_direct3d.c (working copy) @@ -54,7 +54,9 @@ 0 = Movie is not paused */ int is_cfg_finished; /**< Synchronization "semaphore". 1 when instance of reconfigure_d3d is finished */ - + int is_surface_locked; /**< 1 = The offscreen surface is locked, + 0 = it's not */ + D3DLOCKED_RECT locked_rect; /**< The locked Offscreen surface */ RECT fs_movie_rect; /**< Rect (upscaled) of the movie when displayed in fullscreen */ RECT fs_panscan_rect; /**< PanScan source surface cropping in @@ -164,6 +166,11 @@ mp_msg(MSGT_VO,MSGL_V,"destroy_d3d_context called\r\n"); /* Let's destroy the old (if any) D3D Content */ + if (priv->is_surface_locked) { + IDirect3DSurface9_UnlockRect(priv->d3d_surface); + priv->is_surface_locked = 0; + } + if (priv->d3d_surface != NULL) { IDirect3DSurface9_Release (priv->d3d_surface); priv->d3d_surface = NULL; @@ -288,41 +295,40 @@ */ static uint32_t render_d3d_frame(mp_image_t *mpi) { - D3DLOCKED_RECT locked_rect; /**< Offscreen surface we lock in order - to copy MPlayer's frame inside it.*/ - /* Uncomment when direct rendering is implemented. * if (mpi->flags & MP_IMGFLAG_DIRECT) ... */ + /* If the whole image is ready */ if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK) - return VO_TRUE; + goto skip_upload; if (mpi->flags & MP_IMGFLAG_PLANAR) { /* Copy a planar frame. */ draw_slice(mpi->planes,mpi->stride,mpi->w,mpi->h,0,0); - return VO_TRUE; + goto skip_upload; } - /* If the previous if failed, we should draw a packed frame */ - if (FAILED(IDirect3DDevice9_BeginScene(priv->d3d_device))) { - mp_msg(MSGT_VO,MSGL_ERR,"BeginScene failed\n"); - return VO_ERROR; + /* If we're here, then we should lock the rect and copy a packed frame */ + if (!priv->is_surface_locked) { + if (FAILED(IDirect3DSurface9_LockRect(priv->d3d_surface, + &priv->locked_rect, NULL, 0))) { + mp_msg(MSGT_VO,MSGL_V,"Surface lock failure\n"); + return VO_FALSE; + } + priv->is_surface_locked = 1; /* Don't lock again */ } + memcpy_pic(priv->locked_rect.pBits, mpi->planes[0], mpi->stride[0], + mpi->height, priv->locked_rect.Pitch, mpi->stride[0]); - if (FAILED(IDirect3DSurface9_LockRect(priv->d3d_surface, - &locked_rect, NULL, 0))) { - mp_msg(MSGT_VO,MSGL_ERR,"Surface lock failure\n"); - return VO_ERROR; - } - - memcpy_pic(locked_rect.pBits, mpi->planes[0], mpi->stride[0], - mpi->height, locked_rect.Pitch, mpi->stride[0]); - +skip_upload: + /* This unlock is used for both slice_draw path and render_d3d_frame path. */ if (FAILED(IDirect3DSurface9_UnlockRect(priv->d3d_surface))) { mp_msg(MSGT_VO,MSGL_V,"Surface unlock failure\n"); - return VO_ERROR; + return VO_ERROR; } + priv->is_surface_locked = 0; + if (FAILED(IDirect3DDevice9_StretchRect(priv->d3d_device, priv->d3d_surface, &priv->fs_panscan_rect, @@ -607,8 +613,6 @@ */ static int draw_slice(uint8_t *src[], int stride[], int w,int h,int x,int y ) { - D3DLOCKED_RECT locked_rect; /**< Offscreen surface we lock in order - to copy MPlayer's frame inside it.*/ char *Src; /**< Pointer to the source image */ char *Dst; /**< Pointer to the destination image */ int UVstride; /**< Stride of the U/V planes */ @@ -618,25 +622,29 @@ return VO_ERROR; } + /* Lock the offscreen surface if it's not already locked. */ + if (!priv->is_surface_locked) { if (FAILED(IDirect3DSurface9_LockRect(priv->d3d_surface, - &locked_rect, NULL, 0))) { + &priv->locked_rect, NULL, 0))) { mp_msg(MSGT_VO,MSGL_V,"Surface lock failure\n"); return VO_FALSE; } + priv->is_surface_locked = 1; /* Don't lock again */ + } - UVstride = locked_rect.Pitch / 2; + UVstride = priv->locked_rect.Pitch / 2; /* Copy Y */ - Dst = locked_rect.pBits; - Dst = Dst + locked_rect.Pitch * y + x; + Dst = priv->locked_rect.pBits; + Dst = Dst + priv->locked_rect.Pitch * y + x; Src=src[0]; - memcpy_pic(Dst, Src, w, h, locked_rect.Pitch, stride[0]); + memcpy_pic(Dst, Src, w, h, priv->locked_rect.Pitch, stride[0]); w/=2;h/=2;x/=2;y/=2; /* Copy U */ - Dst = locked_rect.pBits; - Dst = Dst + locked_rect.Pitch * priv->src_height + Dst = priv->locked_rect.pBits; + Dst = Dst + priv->locked_rect.Pitch * priv->src_height + UVstride * y + x; if (priv->movie_src_fmt == MAKEFOURCC('Y','V','1','2')) Src=src[2]; @@ -646,8 +654,8 @@ memcpy_pic(Dst, Src, w, h, UVstride, stride[1]); /* Copy V */ - Dst = locked_rect.pBits; - Dst = Dst + locked_rect.Pitch * priv->src_height + Dst = priv->locked_rect.pBits; + Dst = Dst + priv->locked_rect.Pitch * priv->src_height + UVstride * (priv->src_height / 2) + UVstride * y + x; if (priv->movie_src_fmt == MAKEFOURCC('Y','V','1','2')) Src=src[1]; @@ -656,22 +664,6 @@ memcpy_pic(Dst, Src, w, h, UVstride, stride[2]); - if (FAILED(IDirect3DSurface9_UnlockRect(priv->d3d_surface))) { - mp_msg(MSGT_VO,MSGL_V,"Surface unlock failure\n"); - return VO_ERROR; - } - - if (FAILED(IDirect3DDevice9_StretchRect(priv->d3d_device, - priv->d3d_surface, - &priv->fs_panscan_rect, - priv->d3d_backbuf, - &priv->fs_movie_rect, - D3DTEXF_LINEAR))) { - mp_msg(MSGT_VO,MSGL_V, - "Unable to copy the frame to the back buffer\n"); - return VO_ERROR; - } - if (FAILED(IDirect3DDevice9_EndScene(priv->d3d_device))) { mp_msg(MSGT_VO,MSGL_ERR,"EndScene failed\n"); return VO_ERROR;