Mercurial > mplayer.hg
changeset 28026:ace2f84df2bd
Reorganize Direct3D initialization code.
Patch by Georgi Petrov [gogothebee gmail com]
author | reimar |
---|---|
date | Tue, 02 Dec 2008 09:36:47 +0000 |
parents | bb992646f29d |
children | f210d48c4396 |
files | libvo/vo_direct3d.c |
diffstat | 1 files changed, 150 insertions(+), 51 deletions(-) [+] |
line wrap: on
line diff
--- a/libvo/vo_direct3d.c Tue Dec 02 08:35:30 2008 +0000 +++ b/libvo/vo_direct3d.c Tue Dec 02 09:36:47 2008 +0000 @@ -168,12 +168,12 @@ priv->is_clear_needed = 1; } -/** @brief Destroy D3D Context related to the current window. +/** @brief Destroy D3D Offscreen and Backbuffer surfaces. */ -static void destroy_d3d_context(void) +static void destroy_d3d_surfaces(void) { - mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>destroy_d3d_context called\r\n"); - /* Let's destroy the old (if any) D3D Content */ + mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>destroy_d3d_surfaces called\r\n"); + /* Let's destroy the old (if any) D3D Surfaces */ if (priv->locked_rect.pBits) { IDirect3DSurface9_UnlockRect(priv->d3d_surface); @@ -185,31 +185,67 @@ priv->d3d_surface = NULL; } - if (priv->d3d_device != NULL) { - IDirect3DDevice9_Release(priv->d3d_device); - priv->d3d_device = NULL; + if (priv->d3d_backbuf != NULL) { + IDirect3DSurface9_Release(priv->d3d_backbuf); + priv->d3d_backbuf = NULL; + } +} + +/** @brief Create D3D Offscreen and Backbuffer surfaces. + * @return 1 on success, 0 on failure + */ +static int create_d3d_surfaces(void) +{ + mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d><INFO>create_d3d_surfaces called.\n"); + + if (FAILED(IDirect3DDevice9_CreateOffscreenPlainSurface( + priv->d3d_device, priv->src_width, priv->src_height, + priv->movie_src_fmt, D3DPOOL_DEFAULT, &priv->d3d_surface, NULL))) { + mp_msg(MSGT_VO, MSGL_ERR, + "<vo_direct3d><INFO>IDirect3D9_CreateOffscreenPlainSurface Failed.\n"); + return 0; + } + + if (FAILED(IDirect3DDevice9_GetBackBuffer(priv->d3d_device, 0, 0, + D3DBACKBUFFER_TYPE_MONO, + &(priv->d3d_backbuf)))) { + mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Back Buffer address get failed\n"); + return 0; } - /* The following is not a memory leak. d3d_backbuf is not malloc'ed - * but just holds a pointer to the back buffer. Nobody gets hurt from - * setting it to NULL. - */ - priv->d3d_backbuf = NULL; + return 1; } +/** @brief Fill D3D Presentation parameters + */ +static void fill_d3d_presentparams(D3DPRESENT_PARAMETERS *present_params) +{ + /* Prepare Direct3D initialization parameters. */ + memset(present_params, 0, sizeof(D3DPRESENT_PARAMETERS)); + present_params->Windowed = TRUE; + present_params->SwapEffect = D3DSWAPEFFECT_COPY; + present_params->Flags = D3DPRESENTFLAG_VIDEO; + present_params->hDeviceWindow = vo_w32_window; /* w32_common var */ + present_params->BackBufferWidth = 0; /* Fill up window Width */ + present_params->BackBufferHeight = 0; /* Fill up window Height */ + present_params->MultiSampleType = D3DMULTISAMPLE_NONE; + /* D3DPRESENT_INTERVAL_ONE = vsync */ + present_params->PresentationInterval = D3DPRESENT_INTERVAL_ONE; + present_params->BackBufferFormat = priv->desktop_fmt; + present_params->BackBufferCount = 1; + present_params->EnableAutoDepthStencil = FALSE; +} -/** @brief (Re)Initialize Direct3D. Kill and recreate context. - * The first function called to initialize D3D context. +/** @brief Configure initial Direct3D context. The first + * function called to initialize the D3D context. * @return 1 on success, 0 on failure */ -static int reconfigure_d3d(void) +static int configure_d3d(void) { D3DPRESENT_PARAMETERS present_params; D3DDISPLAYMODE disp_mode; - mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d><INFO>reconfigure_d3d called \n"); - - destroy_d3d_context(); + mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d><INFO>configure_d3d called\n"); /* Get the current desktop display mode, so we can set up a back buffer * of the same format. */ @@ -224,20 +260,7 @@ /* Write current Desktop's colorspace format in the global storage. */ priv->desktop_fmt = disp_mode.Format; - /* Prepare Direct3D initialization parameters. */ - memset(&present_params, 0, sizeof(D3DPRESENT_PARAMETERS)); - present_params.Windowed = TRUE; - present_params.SwapEffect = D3DSWAPEFFECT_COPY; - present_params.Flags = D3DPRESENTFLAG_VIDEO; - present_params.hDeviceWindow = vo_w32_window; /* w32_common var */ - present_params.BackBufferWidth = 0; /* Fill up window Width */ - present_params.BackBufferHeight = 0; /* Fill up window Height */ - present_params.MultiSampleType = D3DMULTISAMPLE_NONE; - /* D3DPRESENT_INTERVAL_ONE = vsync */ - present_params.PresentationInterval = D3DPRESENT_INTERVAL_ONE; - present_params.BackBufferFormat = priv->desktop_fmt; - present_params.BackBufferCount = 1; - present_params.EnableAutoDepthStencil = FALSE; + fill_d3d_presentparams(&present_params); /* vo_w32_window is w32_common variable. It's a handle to the window. */ if (FAILED(IDirect3D9_CreateDevice(priv->d3d_handle, @@ -250,29 +273,85 @@ return 0; } + if (!create_d3d_surfaces()) + return 0; + mp_msg(MSGT_VO, MSGL_V, "New BackBuffer: Width: %d, Height:%d. VO Dest Width:%d, Height: %d\n", present_params.BackBufferWidth, present_params.BackBufferHeight, vo_dwidth, vo_dheight); - if (FAILED(IDirect3DDevice9_CreateOffscreenPlainSurface(priv->d3d_device, - priv->src_width, - priv->src_height, - priv->movie_src_fmt, - D3DPOOL_DEFAULT, - &priv->d3d_surface, - NULL))) { + calc_fs_rect(); + + return 1; +} + +/** @brief Reconfigure the whole Direct3D. Called only + * when the video adapter becomes uncooperative. + * @return 1 on success, 0 on failure + */ +static int reconfigure_d3d(void) +{ + mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d><INFO>reconfigure_d3d called.\n"); + + /* Destroy the Offscreen and Backbuffer surfaces */ + destroy_d3d_surfaces(); + + /* Destroy the D3D Device */ + if (priv->d3d_device != NULL) { + IDirect3DDevice9_Release(priv->d3d_device); + priv->d3d_device = NULL; + } + + /* Stop the whole Direct3D */ + IDirect3D9_Release(priv->d3d_handle); + + /* Initialize Direct3D from the beginning */ + priv->d3d_handle = Direct3DCreate9(D3D_SDK_VERSION); + if (!priv->d3d_handle) { + mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Unable to initialize Direct3D\n"); + return -1; + } + + /* Configure Direct3D */ + if (!configure_d3d()) + return 0; + + return 1; +} + + +/** @brief Resize Direct3D context on window resize. + * @return 1 on success, 0 on failure + */ +static int resize_d3d(void) +{ + D3DPRESENT_PARAMETERS present_params; + + mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d><INFO>resize_d3d called.\n"); + + + check_events(); + + destroy_d3d_surfaces(); + + /* Reset the D3D Device with all parameters the same except the new + * width/height. + */ + fill_d3d_presentparams(&present_params); + if (FAILED(IDirect3DDevice9_Reset(priv->d3d_device, &present_params))) { mp_msg(MSGT_VO, MSGL_ERR, - "<vo_direct3d><INFO>IDirect3D9_CreateOffscreenPlainSurface Failed.\n"); + "<vo_direct3d><INFO>Could not reset the D3D device\n"); return 0; } - if (FAILED(IDirect3DDevice9_GetBackBuffer(priv->d3d_device, 0, 0, - D3DBACKBUFFER_TYPE_MONO, - &(priv->d3d_backbuf)))) { - mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Back Buffer address get failed\n"); + if (!create_d3d_surfaces()) return 0; - } + + mp_msg(MSGT_VO, MSGL_V, + "New BackBuffer: Width: %d, Height:%d. VO Dest Width:%d, Height: %d\n", + present_params.BackBufferWidth, present_params.BackBufferHeight, + vo_dwidth, vo_dheight); calc_fs_rect(); @@ -285,8 +364,13 @@ { mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>uninit_d3d called\r\n"); - /* Destroy D3D Context inside the window. */ - destroy_d3d_context(); + destroy_d3d_surfaces(); + + /* Destroy the D3D Device */ + if (priv->d3d_device != NULL) { + IDirect3DDevice9_Release(priv->d3d_device); + priv->d3d_device = NULL; + } /* Stop the whole D3D. */ if (NULL != priv->d3d_handle) { @@ -305,6 +389,8 @@ * if (mpi->flags & MP_IMGFLAG_DIRECT) ... */ + resize_d3d(); + if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK) goto skip_upload; @@ -481,7 +567,7 @@ return render_d3d_frame(data); case VOCTRL_FULLSCREEN: vo_w32_fullscreen(); - reconfigure_d3d(); + resize_d3d(); return VO_TRUE; case VOCTRL_RESET: return VO_NOTIMPL; @@ -502,7 +588,7 @@ return VO_TRUE; case VOCTRL_BORDER: vo_w32_border(); - reconfigure_d3d(); + resize_d3d(); return VO_TRUE; case VOCTRL_UPDATE_SCREENINFO: w32_update_xinerama_info(); @@ -543,7 +629,20 @@ return VO_ERROR; } - if (!reconfigure_d3d()) + /* "config" may be called several times, so if this is not the first + * call, we should destroy Direct3D adapter and surfaces before + * calling configure_d3d, which will create them again. + */ + + destroy_d3d_surfaces(); + + /* Destroy the D3D Device */ + if (priv->d3d_device != NULL) { + IDirect3DDevice9_Release(priv->d3d_device); + priv->d3d_device = NULL; + } + + if (!configure_d3d()) return VO_ERROR; return 0; /* Success */ @@ -606,7 +705,7 @@ */ flags = vo_w32_check_events(); if (flags & VO_EVENT_RESIZE) - reconfigure_d3d(); + resize_d3d(); if ((flags & VO_EVENT_EXPOSE) && priv->is_paused) flip_page();