mirror of https://github.com/mpv-player/mpv
Allocate a larger backbuffer to allow resizing without reinit.
Patch by Georgi Petrov [gogothebee gmail com] and Jim Hauxwell [james (at) dattrax co uk] git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@28379 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
parent
c1cd81818a
commit
7fcf438a2f
|
@ -78,6 +78,8 @@ static struct global_priv {
|
||||||
cannot lock a normal texture. Uses RGBA */
|
cannot lock a normal texture. Uses RGBA */
|
||||||
IDirect3DSurface9 *d3d_backbuf; /**< Video card's back buffer (used to
|
IDirect3DSurface9 *d3d_backbuf; /**< Video card's back buffer (used to
|
||||||
display next frame) */
|
display next frame) */
|
||||||
|
int cur_backbuf_width; /**< Current backbuffer width */
|
||||||
|
int cur_backbuf_height; /**< Current backbuffer height */
|
||||||
int is_osd_populated; /**< 1 = OSD texture has something to display,
|
int is_osd_populated; /**< 1 = OSD texture has something to display,
|
||||||
0 = OSD texture is clear */
|
0 = OSD texture is clear */
|
||||||
int device_caps_power2_only; /**< 1 = texture sizes have to be power 2
|
int device_caps_power2_only; /**< 1 = texture sizes have to be power 2
|
||||||
|
@ -126,6 +128,10 @@ typedef struct {
|
||||||
float tu, tv; /* Texture coordinates */
|
float tu, tv; /* Texture coordinates */
|
||||||
} struct_vertex;
|
} struct_vertex;
|
||||||
|
|
||||||
|
typedef enum back_buffer_action {
|
||||||
|
BACKBUFFER_CREATE,
|
||||||
|
BACKBUFFER_RESET
|
||||||
|
} back_buffer_action_e;
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* *
|
* *
|
||||||
* *
|
* *
|
||||||
|
@ -224,7 +230,8 @@ static void destroy_d3d_surfaces(void)
|
||||||
priv->d3d_backbuf = NULL;
|
priv->d3d_backbuf = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief Create D3D Offscreen and Backbuffer surfaces.
|
/** @brief Create D3D Offscreen and Backbuffer surfaces. Each
|
||||||
|
* surface is created only if it's not already present.
|
||||||
* @return 1 on success, 0 on failure
|
* @return 1 on success, 0 on failure
|
||||||
*/
|
*/
|
||||||
static int create_d3d_surfaces(void)
|
static int create_d3d_surfaces(void)
|
||||||
|
@ -233,7 +240,8 @@ static int create_d3d_surfaces(void)
|
||||||
int tex_width = osd_width, tex_height = osd_height;
|
int tex_width = osd_width, tex_height = osd_height;
|
||||||
mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d><INFO>create_d3d_surfaces called.\n");
|
mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d><INFO>create_d3d_surfaces called.\n");
|
||||||
|
|
||||||
if (FAILED(IDirect3DDevice9_CreateOffscreenPlainSurface(
|
if (!priv->d3d_surface &&
|
||||||
|
FAILED(IDirect3DDevice9_CreateOffscreenPlainSurface(
|
||||||
priv->d3d_device, priv->src_width, priv->src_height,
|
priv->d3d_device, priv->src_width, priv->src_height,
|
||||||
priv->movie_src_fmt, D3DPOOL_DEFAULT, &priv->d3d_surface, NULL))) {
|
priv->movie_src_fmt, D3DPOOL_DEFAULT, &priv->d3d_surface, NULL))) {
|
||||||
mp_msg(MSGT_VO, MSGL_ERR,
|
mp_msg(MSGT_VO, MSGL_ERR,
|
||||||
|
@ -241,7 +249,8 @@ static int create_d3d_surfaces(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FAILED(IDirect3DDevice9_GetBackBuffer(priv->d3d_device, 0, 0,
|
if (!priv->d3d_backbuf &&
|
||||||
|
FAILED(IDirect3DDevice9_GetBackBuffer(priv->d3d_device, 0, 0,
|
||||||
D3DBACKBUFFER_TYPE_MONO,
|
D3DBACKBUFFER_TYPE_MONO,
|
||||||
&priv->d3d_backbuf))) {
|
&priv->d3d_backbuf))) {
|
||||||
mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Back Buffer address get failed\n");
|
mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Back Buffer address get failed\n");
|
||||||
|
@ -279,7 +288,8 @@ static int create_d3d_surfaces(void)
|
||||||
vo_dwidth, vo_dheight, priv->osd_texture_width, priv->osd_texture_height);
|
vo_dwidth, vo_dheight, priv->osd_texture_width, priv->osd_texture_height);
|
||||||
|
|
||||||
/* create OSD */
|
/* create OSD */
|
||||||
if (FAILED(IDirect3DDevice9_CreateTexture(priv->d3d_device,
|
if (!priv->d3d_texture_system &&
|
||||||
|
FAILED(IDirect3DDevice9_CreateTexture(priv->d3d_device,
|
||||||
priv->osd_texture_width,
|
priv->osd_texture_width,
|
||||||
priv->osd_texture_height,
|
priv->osd_texture_height,
|
||||||
1,
|
1,
|
||||||
|
@ -295,7 +305,8 @@ static int create_d3d_surfaces(void)
|
||||||
|
|
||||||
if (!priv->device_texture_sys) {
|
if (!priv->device_texture_sys) {
|
||||||
/* only create if we need a shadow version on the external device */
|
/* only create if we need a shadow version on the external device */
|
||||||
if (FAILED(IDirect3DDevice9_CreateTexture(priv->d3d_device,
|
if (!priv->d3d_texture_osd &&
|
||||||
|
FAILED(IDirect3DDevice9_CreateTexture(priv->d3d_device,
|
||||||
priv->osd_texture_width,
|
priv->osd_texture_width,
|
||||||
priv->osd_texture_height,
|
priv->osd_texture_height,
|
||||||
1,
|
1,
|
||||||
|
@ -332,27 +343,78 @@ static void fill_d3d_presentparams(D3DPRESENT_PARAMETERS *present_params)
|
||||||
present_params->SwapEffect = D3DSWAPEFFECT_COPY;
|
present_params->SwapEffect = D3DSWAPEFFECT_COPY;
|
||||||
present_params->Flags = D3DPRESENTFLAG_VIDEO;
|
present_params->Flags = D3DPRESENTFLAG_VIDEO;
|
||||||
present_params->hDeviceWindow = vo_w32_window; /* w32_common var */
|
present_params->hDeviceWindow = vo_w32_window; /* w32_common var */
|
||||||
present_params->BackBufferWidth = 0; /* Fill up window Width */
|
present_params->BackBufferWidth = priv->cur_backbuf_width;
|
||||||
present_params->BackBufferHeight = 0; /* Fill up window Height */
|
present_params->BackBufferHeight = priv->cur_backbuf_height;
|
||||||
present_params->MultiSampleType = D3DMULTISAMPLE_NONE;
|
present_params->MultiSampleType = D3DMULTISAMPLE_NONE;
|
||||||
/* D3DPRESENT_INTERVAL_ONE = vsync */
|
|
||||||
present_params->PresentationInterval = D3DPRESENT_INTERVAL_ONE;
|
present_params->PresentationInterval = D3DPRESENT_INTERVAL_ONE;
|
||||||
present_params->BackBufferFormat = priv->desktop_fmt;
|
present_params->BackBufferFormat = priv->desktop_fmt;
|
||||||
present_params->BackBufferCount = 1;
|
present_params->BackBufferCount = 1;
|
||||||
present_params->EnableAutoDepthStencil = FALSE;
|
present_params->EnableAutoDepthStencil = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** @brief Create a new backbuffer. Create or Reset the D3D
|
||||||
|
* device.
|
||||||
|
* @return 1 on success, 0 on failure
|
||||||
|
*/
|
||||||
|
static int change_d3d_backbuffer(back_buffer_action_e action)
|
||||||
|
{
|
||||||
|
D3DPRESENT_PARAMETERS present_params;
|
||||||
|
|
||||||
|
destroy_d3d_surfaces();
|
||||||
|
|
||||||
|
/* Grow the backbuffer in the required dimension. */
|
||||||
|
if (vo_dwidth > priv->cur_backbuf_width)
|
||||||
|
priv->cur_backbuf_width = vo_dwidth;
|
||||||
|
|
||||||
|
if (vo_dheight > priv->cur_backbuf_height)
|
||||||
|
priv->cur_backbuf_height = vo_dheight;
|
||||||
|
|
||||||
|
/* The grown backbuffer dimensions are ready and fill_d3d_presentparams
|
||||||
|
* will use them, so we can reset the device.
|
||||||
|
*/
|
||||||
|
fill_d3d_presentparams(&present_params);
|
||||||
|
|
||||||
|
/* vo_w32_window is w32_common variable. It's a handle to the window. */
|
||||||
|
if (action == BACKBUFFER_CREATE &&
|
||||||
|
FAILED(IDirect3D9_CreateDevice(priv->d3d_handle,
|
||||||
|
D3DADAPTER_DEFAULT,
|
||||||
|
D3DDEVTYPE_HAL, vo_w32_window,
|
||||||
|
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
|
||||||
|
&present_params, &priv->d3d_device))) {
|
||||||
|
mp_msg(MSGT_VO, MSGL_ERR,
|
||||||
|
"<vo_direct3d><INFO>Could not create the D3D device\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == BACKBUFFER_RESET &&
|
||||||
|
FAILED(IDirect3DDevice9_Reset(priv->d3d_device, &present_params))) {
|
||||||
|
mp_msg(MSGT_VO, MSGL_ERR,
|
||||||
|
"<vo_direct3d><INFO>Could not reset the D3D device\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_msg(MSGT_VO, MSGL_V,
|
||||||
|
"<vo_direct3d><INFO>New backbuffer: Width: %d, Height:%d. VO Dest Width:%d, Height: %d\n",
|
||||||
|
present_params.BackBufferWidth, present_params.BackBufferHeight,
|
||||||
|
vo_dwidth, vo_dheight);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/** @brief Configure initial Direct3D context. The first
|
/** @brief Configure initial Direct3D context. The first
|
||||||
* function called to initialize the D3D context.
|
* function called to initialize the D3D context.
|
||||||
* @return 1 on success, 0 on failure
|
* @return 1 on success, 0 on failure
|
||||||
*/
|
*/
|
||||||
static int configure_d3d(void)
|
static int configure_d3d(void)
|
||||||
{
|
{
|
||||||
D3DPRESENT_PARAMETERS present_params;
|
|
||||||
D3DDISPLAYMODE disp_mode;
|
D3DDISPLAYMODE disp_mode;
|
||||||
|
D3DVIEWPORT9 vp = {0, 0, vo_dwidth, vo_dheight, 0, 1};
|
||||||
|
|
||||||
mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d><INFO>configure_d3d called\n");
|
mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d><INFO>configure_d3d called\n");
|
||||||
|
|
||||||
|
destroy_d3d_surfaces();
|
||||||
|
|
||||||
/* Get the current desktop display mode, so we can set up a back buffer
|
/* Get the current desktop display mode, so we can set up a back buffer
|
||||||
* of the same format. */
|
* of the same format. */
|
||||||
if (FAILED(IDirect3D9_GetAdapterDisplayMode(priv->d3d_handle,
|
if (FAILED(IDirect3D9_GetAdapterDisplayMode(priv->d3d_handle,
|
||||||
|
@ -366,26 +428,17 @@ static int configure_d3d(void)
|
||||||
/* Write current Desktop's colorspace format in the global storage. */
|
/* Write current Desktop's colorspace format in the global storage. */
|
||||||
priv->desktop_fmt = disp_mode.Format;
|
priv->desktop_fmt = disp_mode.Format;
|
||||||
|
|
||||||
fill_d3d_presentparams(&present_params);
|
if (!change_d3d_backbuffer(BACKBUFFER_CREATE))
|
||||||
|
|
||||||
/* vo_w32_window is w32_common variable. It's a handle to the window. */
|
|
||||||
if (FAILED(IDirect3D9_CreateDevice(priv->d3d_handle,
|
|
||||||
D3DADAPTER_DEFAULT,
|
|
||||||
D3DDEVTYPE_HAL, vo_w32_window,
|
|
||||||
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
|
|
||||||
&present_params, &priv->d3d_device))) {
|
|
||||||
mp_msg(MSGT_VO, MSGL_ERR,
|
|
||||||
"<vo_direct3d><INFO>Could not create the D3D device\n");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
if (!create_d3d_surfaces())
|
if (!create_d3d_surfaces())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
mp_msg(MSGT_VO, MSGL_V,
|
if (FAILED(IDirect3DDevice9_SetViewport(priv->d3d_device,
|
||||||
"New BackBuffer: Width: %d, Height:%d. VO Dest Width:%d, Height: %d\n",
|
&vp))) {
|
||||||
present_params.BackBufferWidth, present_params.BackBufferHeight,
|
mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Unable to set the viewport\n");
|
||||||
vo_dwidth, vo_dheight);
|
return VO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
calc_fs_rect();
|
calc_fs_rect();
|
||||||
|
|
||||||
|
@ -400,7 +453,7 @@ static int reconfigure_d3d(void)
|
||||||
{
|
{
|
||||||
mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d><INFO>reconfigure_d3d called.\n");
|
mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d><INFO>reconfigure_d3d called.\n");
|
||||||
|
|
||||||
/* Destroy the Offscreen and Backbuffer surfaces */
|
/* Destroy the offscreen, OSD and backbuffer surfaces */
|
||||||
destroy_d3d_surfaces();
|
destroy_d3d_surfaces();
|
||||||
|
|
||||||
/* Destroy the D3D Device */
|
/* Destroy the D3D Device */
|
||||||
|
@ -425,35 +478,49 @@ static int reconfigure_d3d(void)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** @brief Resize Direct3D context on window resize.
|
/** @brief Resize Direct3D context on window resize.
|
||||||
* @return 1 on success, 0 on failure
|
* @return 1 on success, 0 on failure
|
||||||
*/
|
*/
|
||||||
static int resize_d3d(void)
|
static int resize_d3d(void)
|
||||||
{
|
{
|
||||||
D3DPRESENT_PARAMETERS present_params;
|
D3DVIEWPORT9 vp = {0, 0, vo_dwidth, vo_dheight, 0, 1};
|
||||||
|
|
||||||
mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d><INFO>resize_d3d called.\n");
|
mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d><INFO>resize_d3d called.\n");
|
||||||
|
|
||||||
destroy_d3d_surfaces();
|
/* Make sure that backbuffer is large enough to accomodate the new
|
||||||
|
viewport dimensions. Grow it if necessary. */
|
||||||
|
|
||||||
/* Reset the D3D Device with all parameters the same except the new
|
if (vo_dwidth > priv->cur_backbuf_width ||
|
||||||
* width/height.
|
vo_dheight > priv->cur_backbuf_height) {
|
||||||
*/
|
change_d3d_backbuffer (BACKBUFFER_RESET);
|
||||||
fill_d3d_presentparams(&present_params);
|
|
||||||
if (FAILED(IDirect3DDevice9_Reset(priv->d3d_device, &present_params))) {
|
|
||||||
mp_msg(MSGT_VO, MSGL_ERR,
|
|
||||||
"<vo_direct3d><INFO>Could not reset the D3D device\n");
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Destroy the OSD textures. They should always match the new dimensions
|
||||||
|
* of the onscreen window, so on each resize we need new OSD dimensions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (priv->d3d_texture_osd)
|
||||||
|
IDirect3DTexture9_Release(priv->d3d_texture_osd);
|
||||||
|
priv->d3d_texture_osd = NULL;
|
||||||
|
|
||||||
|
if (priv->d3d_texture_system)
|
||||||
|
IDirect3DTexture9_Release(priv->d3d_texture_system);
|
||||||
|
priv->d3d_texture_system = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
/* Recreate the OSD. The function will observe that the offscreen plain
|
||||||
|
* surface and the backbuffer are not destroyed and will skip their creation,
|
||||||
|
* effectively recreating only the OSD.
|
||||||
|
*/
|
||||||
|
|
||||||
if (!create_d3d_surfaces())
|
if (!create_d3d_surfaces())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
mp_msg(MSGT_VO, MSGL_V,
|
if (FAILED(IDirect3DDevice9_SetViewport(priv->d3d_device,
|
||||||
"New BackBuffer: Width: %d, Height:%d. VO Dest Width:%d, Height: %d\n",
|
&vp))) {
|
||||||
present_params.BackBufferWidth, present_params.BackBufferHeight,
|
mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Unable to set the viewport\n");
|
||||||
vo_dwidth, vo_dheight);
|
return VO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
calc_fs_rect();
|
calc_fs_rect();
|
||||||
|
|
||||||
|
@ -644,8 +711,10 @@ static int preinit(const char *arg)
|
||||||
|
|
||||||
/* Store in priv->desktop_fmt the user desktop's colorspace. Usually XRGB. */
|
/* Store in priv->desktop_fmt the user desktop's colorspace. Usually XRGB. */
|
||||||
priv->desktop_fmt = disp_mode.Format;
|
priv->desktop_fmt = disp_mode.Format;
|
||||||
|
priv->cur_backbuf_width = disp_mode.Width;
|
||||||
|
priv->cur_backbuf_height = disp_mode.Height;
|
||||||
|
|
||||||
mp_msg(MSGT_VO, MSGL_V, "disp_mode.Width %d, disp_mode.Height %d\n",
|
mp_msg(MSGT_VO, MSGL_V, "Setting backbuffer to the screen width: %d, height: %d\n",
|
||||||
disp_mode.Width, disp_mode.Height);
|
disp_mode.Width, disp_mode.Height);
|
||||||
|
|
||||||
if (FAILED(IDirect3D9_GetDeviceCaps(priv->d3d_handle,
|
if (FAILED(IDirect3D9_GetDeviceCaps(priv->d3d_handle,
|
||||||
|
@ -787,7 +856,8 @@ static int config(uint32_t width, uint32_t height, uint32_t d_width,
|
||||||
*/
|
*/
|
||||||
static void flip_page(void)
|
static void flip_page(void)
|
||||||
{
|
{
|
||||||
if (FAILED(IDirect3DDevice9_Present(priv->d3d_device, 0, 0, 0, 0))) {
|
RECT rect = {0, 0, vo_dwidth, vo_dheight};
|
||||||
|
if (FAILED(IDirect3DDevice9_Present(priv->d3d_device, &rect, 0, 0, 0))) {
|
||||||
mp_msg(MSGT_VO, MSGL_V,
|
mp_msg(MSGT_VO, MSGL_V,
|
||||||
"<vo_direct3d>Video adapter became uncooperative.\n");
|
"<vo_direct3d>Video adapter became uncooperative.\n");
|
||||||
mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Trying to reinitialize it...\n");
|
mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Trying to reinitialize it...\n");
|
||||||
|
@ -795,7 +865,7 @@ static void flip_page(void)
|
||||||
mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Reinitialization Failed.\n");
|
mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Reinitialization Failed.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (FAILED(IDirect3DDevice9_Present(priv->d3d_device, 0, 0, 0, 0))) {
|
if (FAILED(IDirect3DDevice9_Present(priv->d3d_device, &rect, 0, 0, 0))) {
|
||||||
mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Reinitialization Failed.\n");
|
mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Reinitialization Failed.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue