summaryrefslogtreecommitdiffstats
path: root/libvo/vo_direct3d.c
diff options
context:
space:
mode:
Diffstat (limited to 'libvo/vo_direct3d.c')
-rw-r--r--libvo/vo_direct3d.c162
1 files changed, 70 insertions, 92 deletions
diff --git a/libvo/vo_direct3d.c b/libvo/vo_direct3d.c
index 43f594777c..78b8dbc159 100644
--- a/libvo/vo_direct3d.c
+++ b/libvo/vo_direct3d.c
@@ -52,9 +52,9 @@ const LIBVO_EXTERN(direct3d)
static struct global_priv {
int is_paused; /**< 1 = Movie is paused,
0 = Movie is not paused */
- int is_cfg_finished; /**< Synchronization "semaphore". 1 when
- instance of reconfigure_d3d is finished */
-
+ int is_clear_needed; /**< 1 = Clear the backbuffer before StretchRect
+ 0 = (default) Don't clear it */
+ 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
@@ -155,6 +155,12 @@ static void calc_fs_rect(void)
"<vo_direct3d>Fullscreen Movie Rect: t: %ld, l: %ld, r: %ld, b:%ld\r\n",
priv->fs_movie_rect.top, priv->fs_movie_rect.left,
priv->fs_movie_rect.right, priv->fs_movie_rect.bottom);
+
+ /* The backbuffer should be cleared before next StretchRect. This is
+ * necessary because our new draw area could be smaller than the
+ * previous one used by StretchRect and without it, leftovers from the
+ * previous frame will be left. */
+ priv->is_clear_needed = 1;
}
/** @brief Destroy D3D Context related to the current window.
@@ -164,6 +170,11 @@ static void destroy_d3d_context(void)
mp_msg(MSGT_VO,MSGL_V,"<vo_direct3d>destroy_d3d_context called\r\n");
/* Let's destroy the old (if any) D3D Content */
+ if (priv->locked_rect.pBits) {
+ IDirect3DSurface9_UnlockRect(priv->d3d_surface);
+ priv->locked_rect.pBits = NULL;
+ }
+
if (priv->d3d_surface != NULL) {
IDirect3DSurface9_Release (priv->d3d_surface);
priv->d3d_surface = NULL;
@@ -254,10 +265,6 @@ static int reconfigure_d3d(void)
return 0;
}
- /* Fill the Surface with black color. */
- IDirect3DDevice9_ColorFill(priv->d3d_device, priv->d3d_surface, NULL,
- D3DCOLOR_ARGB(0xFF, 0, 0, 0) );
-
calc_fs_rect();
return 1;
@@ -269,9 +276,6 @@ static void uninit_d3d(void)
{
mp_msg(MSGT_VO,MSGL_V,"<vo_direct3d>uninit_d3d called\r\n");
- /* Block further calls to reconfigure_d3d(). */
- priv->is_cfg_finished = 0;
-
/* Destroy D3D Context inside the window. */
destroy_d3d_context();
@@ -288,40 +292,48 @@ static void uninit_d3d(void)
*/
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 (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,"<vo_direct3d>BeginScene failed\n");
- return VO_ERROR;
- }
-
- if (FAILED(IDirect3DSurface9_LockRect(priv->d3d_surface,
- &locked_rect, NULL, 0))) {
- mp_msg(MSGT_VO,MSGL_ERR,"<vo_direct3d>Surface lock failure\n");
- return VO_ERROR;
+ /* If we're here, then we should lock the rect and copy a packed frame */
+ if (!priv->locked_rect.pBits) {
+ if (FAILED(IDirect3DSurface9_LockRect(priv->d3d_surface,
+ &priv->locked_rect, NULL, 0))) {
+ mp_msg(MSGT_VO,MSGL_ERR,"<vo_direct3d>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]);
+ memcpy_pic(priv->locked_rect.pBits, mpi->planes[0], mpi->stride[0],
+ mpi->height, priv->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,"<vo_direct3d>Surface unlock failure\n");
return VO_ERROR;
}
+ priv->locked_rect.pBits = NULL;
+
+ if (FAILED(IDirect3DDevice9_BeginScene(priv->d3d_device))) {
+ mp_msg(MSGT_VO,MSGL_ERR,"<vo_direct3d>BeginScene failed\n");
+ return VO_ERROR;
+ }
+
+ if (priv->is_clear_needed) {
+ IDirect3DDevice9_Clear (priv->d3d_device, 0, NULL,
+ D3DCLEAR_TARGET, 0, 0, 0);
+ priv->is_clear_needed = 0;
+ }
if (FAILED(IDirect3DDevice9_StretchRect(priv->d3d_device,
priv->d3d_surface,
@@ -441,9 +453,6 @@ static int preinit(const char *arg)
return -1;
}
- /* Allow the first call to reconfigure_d3d. */
- priv->is_cfg_finished = 1;
-
return 0;
}
@@ -527,14 +536,9 @@ static int config(uint32_t width, uint32_t height, uint32_t d_width,
return VO_ERROR;
}
- if (priv->is_cfg_finished) {
- priv->is_cfg_finished = 0;
- if (!reconfigure_d3d()) {
- priv->is_cfg_finished = 1;
- return VO_ERROR;
- }
- priv->is_cfg_finished = 1;
- }
+ if (!reconfigure_d3d())
+ return VO_ERROR;
+
return 0; /* Success */
}
@@ -560,7 +564,6 @@ static void flip_page(void)
mp_msg(MSGT_VO,MSGL_V,"<vo_direct3d>Video adapter reinitialized.\n");
}
- /*IDirect3DDevice9_Clear (priv->d3d_device, 0, NULL, D3DCLEAR_TARGET, 0, 0, 0);*/
}
/** @brief libvo Callback: Draw OSD/Subtitles,
@@ -607,75 +610,50 @@ static void check_events(void)
*/
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 */
-
- if (FAILED(IDirect3DDevice9_BeginScene(priv->d3d_device))) {
- mp_msg(MSGT_VO,MSGL_ERR,"<vo_direct3d>BeginScene failed\n");
- return VO_ERROR;
- }
-
- if (FAILED(IDirect3DSurface9_LockRect(priv->d3d_surface,
- &locked_rect, NULL, 0))) {
- mp_msg(MSGT_VO,MSGL_V,"<vo_direct3d>Surface lock failure\n");
- return VO_FALSE;
+ char *my_src; /**< Pointer to the source image */
+ char *dst; /**< Pointer to the destination image */
+ int uv_stride; /**< Stride of the U/V planes */
+
+ /* Lock the offscreen surface if it's not already locked. */
+ if (!priv->locked_rect.pBits) {
+ if (FAILED(IDirect3DSurface9_LockRect(priv->d3d_surface,
+ &priv->locked_rect, NULL, 0))) {
+ mp_msg(MSGT_VO,MSGL_V,"<vo_direct3d>Surface lock failure\n");
+ return VO_FALSE;
+ }
}
- UVstride = locked_rect.Pitch / 2;
+ uv_stride = priv->locked_rect.Pitch / 2;
/* Copy Y */
- Dst = locked_rect.pBits;
- Dst = Dst + locked_rect.Pitch * y + x;
- Src=src[0];
- memcpy_pic(Dst, Src, w, h, locked_rect.Pitch, stride[0]);
+ dst = priv->locked_rect.pBits;
+ dst = dst + priv->locked_rect.Pitch * y + x;
+ my_src=src[0];
+ memcpy_pic(dst, my_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
- + UVstride * y + x;
+ dst = priv->locked_rect.pBits;
+ dst = dst + priv->locked_rect.Pitch * priv->src_height
+ + uv_stride * y + x;
if (priv->movie_src_fmt == MAKEFOURCC('Y','V','1','2'))
- Src=src[2];
+ my_src=src[2];
else
- Src=src[1];
+ my_src=src[1];
- memcpy_pic(Dst, Src, w, h, UVstride, stride[1]);
+ memcpy_pic(dst, my_src, w, h, uv_stride, stride[1]);
/* Copy V */
- Dst = locked_rect.pBits;
- Dst = Dst + locked_rect.Pitch * priv->src_height
- + UVstride * (priv->src_height / 2) + UVstride * y + x;
+ dst = priv->locked_rect.pBits;
+ dst = dst + priv->locked_rect.Pitch * priv->src_height
+ + uv_stride * (priv->src_height / 2) + uv_stride * y + x;
if (priv->movie_src_fmt == MAKEFOURCC('Y','V','1','2'))
- Src=src[1];
+ my_src=src[1];
else
- Src=src[2];
-
- memcpy_pic(Dst, Src, w, h, UVstride, stride[2]);
+ my_src=src[2];
- if (FAILED(IDirect3DSurface9_UnlockRect(priv->d3d_surface))) {
- mp_msg(MSGT_VO,MSGL_V,"<vo_direct3d>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,
- "<vo_direct3d>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,"<vo_direct3d>EndScene failed\n");
- return VO_ERROR;
- }
+ memcpy_pic(dst, my_src, w, h, uv_stride, stride[2]);
return 0; /* Success */
}