summaryrefslogtreecommitdiffstats
path: root/video/out/vo_direct3d.c
diff options
context:
space:
mode:
Diffstat (limited to 'video/out/vo_direct3d.c')
-rw-r--r--video/out/vo_direct3d.c856
1 files changed, 199 insertions, 657 deletions
diff --git a/video/out/vo_direct3d.c b/video/out/vo_direct3d.c
index a131d210cb..91e962faa1 100644
--- a/video/out/vo_direct3d.c
+++ b/video/out/vo_direct3d.c
@@ -30,6 +30,7 @@
#include "config.h"
#include "options/options.h"
#include "options/m_option.h"
+#include "sub/draw_bmp.h"
#include "mpv_talloc.h"
#include "vo.h"
#include "video/csputils.h"
@@ -45,32 +46,16 @@
#error GPL only
#endif
-// shaders generated by fxc.exe from d3d_shader_yuv.hlsl
-#include "d3d_shader_420p.h"
-
-#define IMGFMT_IS_Y(x) ((x) == IMGFMT_Y8 || (x) == IMGFMT_Y16)
-#define IMGFMT_Y_DEPTH(x) ((x) == IMGFMT_Y8 ? 8 : 16)
-
#define DEVTYPE D3DDEVTYPE_HAL
//#define DEVTYPE D3DDEVTYPE_REF
-#define D3DFVF_OSD_VERTEX (D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_DIFFUSE)
+#define D3DFVF_OSD_VERTEX (D3DFVF_XYZ | D3DFVF_TEX1)
typedef struct {
float x, y, z;
- D3DCOLOR color;
float tu, tv;
} vertex_osd;
-#define D3DFVF_VIDEO_VERTEX (D3DFVF_XYZ | D3DFVF_TEX3)
-
-typedef struct {
- float x, y, z;
- // pairs of texture coordinates for up to 3 planes
- float t[3][2];
-} vertex_video;
-
-
struct d3dtex {
// user-requested size
int w, h;
@@ -88,51 +73,19 @@ struct d3dtex {
IDirect3DTexture9 *device;
};
-struct texplane {
- int bytes_per_pixel;
- int bits_per_pixel;
- // chroma shifts
- // e.g. get the plane's width in pixels with (priv->src_width >> shift_x)
- int shift_x, shift_y;
- D3DFORMAT d3d_format;
- struct d3dtex texture;
- // temporary locking during uploading the frame (e.g. for draw_slice)
- D3DLOCKED_RECT locked_rect;
- // value used to clear the image with memset (YUV chroma planes do not use
- // the value 0 for this)
- uint8_t clearval;
-};
-
-struct osdpart {
- enum sub_bitmap_format format;
- int change_id;
- struct d3dtex texture;
- int num_vertices;
- vertex_osd *vertices;
-};
-
-enum shaders {
- SHADER_NONE = 0,
- SHADER_420P,
- NUM_SHADERS
-};
+#define MAX_OSD_RECTS 64
/* Global variables "priv" structure. I try to keep their count low.
*/
typedef struct d3d_priv {
struct mp_log *log;
- int opt_prefer_stretchrect;
- int opt_disable_textures;
- int opt_disable_stretchrect;
- int opt_disable_shaders;
- int opt_only_8bit;
- int opt_disable_texture_align;
+ bool opt_disable_texture_align;
// debugging
- int opt_force_power_of_2;
+ bool opt_force_power_of_2;
int opt_texture_memory;
- int opt_swap_discard;
- int opt_exact_backbuffer;
+ bool opt_swap_discard;
+ bool opt_exact_backbuffer;
struct vo *vo;
@@ -145,20 +98,11 @@ typedef struct d3d_priv {
RECT fs_panscan_rect; /**< PanScan source surface cropping in
fullscreen */
int src_width; /**< Source (movie) width */
- int src_height; /**< Source (movie) heigth */
+ int src_height; /**< Source (movie) height */
struct mp_osd_res osd_res;
int image_format; /**< mplayer image format */
struct mp_image_params params;
- bool use_textures; /**< use 3D texture rendering, instead of
- StretchRect */
- int use_shaders; /**< use shader for YUV color conversion, and
- the SHADER_ id (0 is SHADER_NONE)
- (or possibly for RGB video equalizers) */
-
- int plane_count;
- struct texplane planes[3];
-
- IDirect3DPixelShader9 *pixel_shaders[NUM_SHADERS];
+ struct mp_image_params dst_params;
D3DFORMAT movie_src_fmt; /**< Movie colorspace format (depends on
the movie's codec) */
@@ -187,11 +131,12 @@ typedef struct d3d_priv {
int max_texture_width; /**< from the device capabilities */
int max_texture_height; /**< from the device capabilities */
- D3DFORMAT osd_fmt_table[SUBBITMAP_COUNT];
-
D3DMATRIX d3d_colormatrix;
- struct osdpart *osd[MAX_OSD_PARTS];
+ struct mp_draw_sub_cache *osd_cache;
+ struct d3dtex osd_texture;
+ int osd_num_vertices;
+ vertex_osd osd_vertices[MAX_OSD_RECTS * 6];
} d3d_priv;
struct fmt_entry {
@@ -211,19 +156,14 @@ static const struct fmt_entry fmt_table[] = {
// packed YUV
{IMGFMT_UYVY, D3DFMT_UYVY},
// packed RGB
- {IMGFMT_BGR32, D3DFMT_X8R8G8B8},
- {IMGFMT_RGB32, D3DFMT_X8B8G8R8},
+ {IMGFMT_BGR0, D3DFMT_X8R8G8B8},
+ {IMGFMT_RGB0, D3DFMT_X8B8G8R8},
{IMGFMT_BGR24, D3DFMT_R8G8B8}, //untested
{IMGFMT_RGB565, D3DFMT_R5G6B5},
- // grayscale (can be considered both packed and planar)
- {IMGFMT_Y8, D3DFMT_L8},
- {IMGFMT_Y16, D3DFMT_L16},
{0},
};
-static void update_colorspace(d3d_priv *priv);
-static void d3d_clear_video_textures(d3d_priv *priv);
static bool resize_d3d(d3d_priv *priv);
static void uninit(struct vo *vo);
static void flip_page(struct vo *vo);
@@ -398,29 +338,14 @@ static bool d3dtex_update(d3d_priv *priv, struct d3dtex *tex)
static void d3d_unlock_video_objects(d3d_priv *priv)
{
- bool any_failed = false;
-
if (priv->locked_rect.pBits) {
if (FAILED(IDirect3DSurface9_UnlockRect(priv->d3d_surface)))
- any_failed = true;
+ MP_VERBOSE(priv, "Unlocking video objects failed.\n");
}
priv->locked_rect.pBits = NULL;
-
- for (int n = 0; n < priv->plane_count; n++) {
- struct texplane *plane = &priv->planes[n];
- if (plane->locked_rect.pBits) {
- if (FAILED(IDirect3DTexture9_UnlockRect(plane->texture.system, 0)))
- any_failed = true;
- }
- plane->locked_rect.pBits = NULL;
- }
-
- if (any_failed) {
- MP_VERBOSE(priv, "Unlocking video objects failed.\n");
- }
}
-// Free video surface/textures, shaders, etc.
+// Free video surface/textures, etc.
static void d3d_destroy_video_objects(d3d_priv *priv)
{
d3d_unlock_video_objects(priv);
@@ -428,10 +353,6 @@ static void d3d_destroy_video_objects(d3d_priv *priv)
if (priv->d3d_surface)
IDirect3DSurface9_Release(priv->d3d_surface);
priv->d3d_surface = NULL;
-
- for (int n = 0; n < priv->plane_count; n++) {
- d3dtex_release(priv, &priv->planes[n].texture);
- }
}
/** @brief Destroy D3D Offscreen and Backbuffer surfaces.
@@ -441,12 +362,7 @@ static void destroy_d3d_surfaces(d3d_priv *priv)
MP_VERBOSE(priv, "destroy_d3d_surfaces called.\n");
d3d_destroy_video_objects(priv);
-
- for (int n = 0; n < MAX_OSD_PARTS; n++) {
- struct osdpart *osd = priv->osd[n];
- d3dtex_release(priv, &osd->texture);
- osd->change_id = -1;
- }
+ d3dtex_release(priv, &priv->osd_texture);
if (priv->d3d_backbuf)
IDirect3DSurface9_Release(priv->d3d_backbuf);
@@ -455,92 +371,23 @@ static void destroy_d3d_surfaces(d3d_priv *priv)
priv->d3d_in_scene = false;
}
-// Allocate video surface or textures, and create shaders if needed.
+// Allocate video surface.
static bool d3d_configure_video_objects(d3d_priv *priv)
{
- int n;
- bool need_clear = false;
-
assert(priv->image_format != 0);
- if (priv->use_textures) {
- for (n = 0; n < priv->plane_count; n++) {
- struct texplane *plane = &priv->planes[n];
-
- if (!plane->texture.system) {
- if (!d3dtex_allocate(priv,
- &plane->texture,
- plane->d3d_format,
- priv->src_width >> plane->shift_x,
- priv->src_height >> plane->shift_y))
- {
- MP_ERR(priv, "Allocating plane %d"
- " failed.\n", n);
- return false;
- }
-
- MP_VERBOSE(priv, "Allocated plane %d:"
- " %d bit, shift=%d/%d size=%d/%d (%d/%d).\n", n,
- plane->bits_per_pixel,
- plane->shift_x, plane->shift_y,
- plane->texture.w, plane->texture.h,
- plane->texture.tex_w, plane->texture.tex_h);
-
- need_clear = true;
- }
- }
-
- if (need_clear)
- d3d_clear_video_textures(priv);
-
- } else {
-
- if (!priv->d3d_surface &&
- FAILED(IDirect3DDevice9_CreateOffscreenPlainSurface(
- priv->d3d_device, priv->src_width, priv->src_height,
- priv->movie_src_fmt, D3DPOOL_DEFAULT, &priv->d3d_surface, NULL)))
- {
- MP_ERR(priv, "Allocating offscreen surface failed.\n");
- return false;
- }
- }
-
- return true;
-}
-
-static bool d3d_lock_video_textures(d3d_priv *priv)
-{
- for (int n = 0; n < priv->plane_count; n++) {
- struct texplane *plane = &priv->planes[n];
-
- if (!plane->locked_rect.pBits) {
- if (FAILED(IDirect3DTexture9_LockRect(plane->texture.system, 0,
- &plane->locked_rect, NULL, 0)))
- {
- MP_VERBOSE(priv, "Texture lock failure.\n");
- d3d_unlock_video_objects(priv);
- return false;
- }
- }
+ if (!priv->d3d_surface &&
+ FAILED(IDirect3DDevice9_CreateOffscreenPlainSurface(
+ priv->d3d_device, priv->src_width, priv->src_height,
+ priv->movie_src_fmt, D3DPOOL_DEFAULT, &priv->d3d_surface, NULL)))
+ {
+ MP_ERR(priv, "Allocating offscreen surface failed.\n");
+ return false;
}
return true;
}
-static void d3d_clear_video_textures(d3d_priv *priv)
-{
- if (!d3d_lock_video_textures(priv))
- return;
-
- for (int n = 0; n < priv->plane_count; n++) {
- struct texplane *plane = &priv->planes[n];
- memset(plane->locked_rect.pBits, plane->clearval,
- plane->locked_rect.Pitch * plane->texture.tex_h);
- }
-
- d3d_unlock_video_objects(priv);
-}
-
// Recreate and initialize D3D objects if necessary. The amount of work that
// needs to be done can be quite different: it could be that full initialization
// is required, or that some objects need to be created, or that nothing is
@@ -573,6 +420,8 @@ static bool create_d3d_surfaces(d3d_priv *priv)
D3DRS_LIGHTING, FALSE);
// we use up to 3 samplers for up to 3 YUV planes
+ // TODO
+ /*
for (int n = 0; n < 3; n++) {
IDirect3DDevice9_SetSamplerState(priv->d3d_device, n, D3DSAMP_MINFILTER,
D3DTEXF_LINEAR);
@@ -583,6 +432,7 @@ static bool create_d3d_surfaces(d3d_priv *priv)
IDirect3DDevice9_SetSamplerState(priv->d3d_device, n, D3DSAMP_ADDRESSV,
D3DTADDRESS_CLAMP);
}
+ */
return 1;
}
@@ -636,27 +486,18 @@ static bool init_d3d(d3d_priv *priv)
if (priv->opt_force_power_of_2)
priv->device_caps_power2_only = 1;
- priv->osd_fmt_table[SUBBITMAP_LIBASS] = D3DFMT_A8;
- priv->osd_fmt_table[SUBBITMAP_RGBA] = D3DFMT_A8R8G8B8;
-
- for (int n = 0; n < MP_ARRAY_SIZE(priv->osd_fmt_table); n++) {
- int fmt = priv->osd_fmt_table[n];
- if (fmt && FAILED(IDirect3D9_CheckDeviceFormat(priv->d3d_handle,
- D3DADAPTER_DEFAULT,
- DEVTYPE,
- priv->desktop_fmt,
- D3DUSAGE_DYNAMIC | D3DUSAGE_QUERY_FILTER,
- D3DRTYPE_TEXTURE,
- fmt)))
- {
- MP_VERBOSE(priv, "OSD format %#x not supported.\n", fmt);
- priv->osd_fmt_table[n] = 0;
- }
+ if (FAILED(IDirect3D9_CheckDeviceFormat(priv->d3d_handle,
+ D3DADAPTER_DEFAULT,
+ DEVTYPE,
+ priv->desktop_fmt,
+ D3DUSAGE_DYNAMIC | D3DUSAGE_QUERY_FILTER,
+ D3DRTYPE_TEXTURE,
+ D3DFMT_A8R8G8B8)))
+ {
+ MP_ERR(priv, "OSD texture format not supported.\n");
+ return false;
}
- if (!priv->osd_fmt_table[SUBBITMAP_RGBA])
- MP_WARN(priv, "GPU too old - no OSD support.\n");
-
if (!change_d3d_backbuffer(priv))
return false;
@@ -695,12 +536,6 @@ static void fill_d3d_presentparams(d3d_priv *priv,
// Create a new backbuffer. Create or Reset the D3D device.
static bool change_d3d_backbuffer(d3d_priv *priv)
{
- for (int n = 0; n < NUM_SHADERS; n++) {
- if (priv->pixel_shaders[n])
- IDirect3DPixelShader9_Release(priv->pixel_shaders[n]);
- priv->pixel_shaders[n] = NULL;
- }
-
int window_w = priv->vo->dwidth;
int window_h = priv->vo->dheight;
@@ -736,7 +571,7 @@ static bool change_d3d_backbuffer(d3d_priv *priv)
}
} else {
if (FAILED(IDirect3DDevice9_Reset(priv->d3d_device, &present_params))) {
- MP_ERR(priv, "Reseting Direct3D device failed.\n");
+ MP_ERR(priv, "Resetting Direct3D device failed.\n");
return 0;
}
}
@@ -745,22 +580,6 @@ static bool change_d3d_backbuffer(d3d_priv *priv)
present_params.BackBufferWidth, present_params.BackBufferHeight,
window_w, window_h);
- const DWORD* shaders[NUM_SHADERS] = {
- [SHADER_420P] = (DWORD *)d3d_shader_420p,
- };
-
- for (int n = 0; n < NUM_SHADERS; n++) {
- if (!shaders[n])
- continue;
- if (FAILED(IDirect3DDevice9_CreatePixelShader(priv->d3d_device,
- shaders[n], &priv->pixel_shaders[n])))
- {
- priv->pixel_shaders[n] = NULL;
- if (!priv->opt_disable_shaders)
- MP_WARN(priv, "Shader could not be created - disabling shaders.\n");
- }
- }
-
return 1;
}
@@ -768,12 +587,6 @@ static void destroy_d3d(d3d_priv *priv)
{
destroy_d3d_surfaces(priv);
- for (int n = 0; n < NUM_SHADERS; n++) {
- if (priv->pixel_shaders[n])
- IDirect3DPixelShader9_Release(priv->pixel_shaders[n]);
- priv->pixel_shaders[n] = NULL;
- }
-
if (priv->d3d_device)
IDirect3DDevice9_Release(priv->d3d_device);
priv->d3d_device = NULL;
@@ -868,8 +681,6 @@ static void uninit_d3d(d3d_priv *priv)
static uint32_t d3d_draw_frame(d3d_priv *priv)
{
- int n;
-
if (!priv->d3d_device)
return VO_TRUE;
@@ -884,70 +695,18 @@ static uint32_t d3d_draw_frame(d3d_priv *priv)
RECT rm = priv->fs_movie_rect;
RECT rs = priv->fs_panscan_rect;
- if (priv->use_textures) {
-
- for (n = 0; n < priv->plane_count; n++) {
- IDirect3DDevice9_SetTexture(priv->d3d_device, n,
- d3dtex_get_render_texture(priv, &priv->planes[n].texture));
- }
-
- vertex_video vb[] = {
- { rm.left, rm.top, 0.0f},
- { rm.right, rm.top, 0.0f},
- { rm.left, rm.bottom, 0.0f},
- { rm.right, rm.bottom, 0.0f}
- };
-
- float texc[4][2] = {
- { rs.left, rs.top},
- { rs.right, rs.top},
- { rs.left, rs.bottom},
- { rs.right, rs.bottom}
- };
-
- for (n = 0; n < priv->plane_count; n++) {
- float s_x = (1.0f / (1 << priv->planes[n].shift_x))
- / priv->planes[n].texture.tex_w;
- float s_y = (1.0f / (1 << priv->planes[n].shift_y))
- / priv->planes[n].texture.tex_h;
- for (int i = 0; i < 4; i++) {
- vb[i].t[n][0] = texc[i][0] * s_x;
- vb[i].t[n][1] = texc[i][1] * s_y;
- }
- }
-
- if (priv->use_shaders) {
- IDirect3DDevice9_SetPixelShader(priv->d3d_device,
- priv->pixel_shaders[priv->use_shaders]);
- IDirect3DDevice9_SetPixelShaderConstantF(priv->d3d_device, 0,
- &priv->d3d_colormatrix._11,
- 4);
- }
-
- IDirect3DDevice9_SetFVF(priv->d3d_device, D3DFVF_VIDEO_VERTEX);
- IDirect3DDevice9_DrawPrimitiveUP(priv->d3d_device, D3DPT_TRIANGLESTRIP,
- 2, &vb[0], sizeof(vertex_video));
-
- IDirect3DDevice9_SetPixelShader(priv->d3d_device, NULL);
-
- for (n = 0; n < priv->plane_count; n++) {
- IDirect3DDevice9_SetTexture(priv->d3d_device, n, NULL);
- }
-
- } else {
- rs.left &= ~(ULONG)1;
- rs.top &= ~(ULONG)1;
- rs.right &= ~(ULONG)1;
- rs.bottom &= ~(ULONG)1;
- if (FAILED(IDirect3DDevice9_StretchRect(priv->d3d_device,
- priv->d3d_surface,
- &rs,
- priv->d3d_backbuf,
- &rm,
- D3DTEXF_LINEAR))) {
- MP_ERR(priv, "Copying frame to the backbuffer failed.\n");
- return VO_ERROR;
- }
+ rs.left &= ~(ULONG)1;
+ rs.top &= ~(ULONG)1;
+ rs.right &= ~(ULONG)1;
+ rs.bottom &= ~(ULONG)1;
+ if (FAILED(IDirect3DDevice9_StretchRect(priv->d3d_device,
+ priv->d3d_surface,
+ &rs,
+ priv->d3d_backbuf,
+ &rm,
+ D3DTEXF_LINEAR))) {
+ MP_ERR(priv, "Copying frame to the backbuffer failed.\n");
+ return VO_ERROR;
}
render_osd:
@@ -957,70 +716,28 @@ render_osd:
return VO_TRUE;
}
-// Return the high byte of the value that represents white in chroma (U/V)
-static int get_chroma_clear_val(int bit_depth)
-{
- return 1 << ((bit_depth - 1) & 7);
-}
-
-// this macro is supposed to work on all formats supported by 3D rendering, and
-// that produce "reasonable" output (i.e. no mixed up colors)
-#define IMGFMT_IS_ANY_RND(x) \
- (IMGFMT_IS_RGB(x) || IMGFMT_IS_Y(x))
-
-// pixel size in bit for any IMGFMT_IS_ANY_RND(x)==true
-// we assume that the actual pixel strides are always aligned on bytes
-static int imgfmt_any_rnd_depth(int fmt)
-{
- if (IMGFMT_IS_RGB(fmt))
- return IMGFMT_RGB_DEPTH(fmt);
- if (IMGFMT_IS_Y(fmt))
- return IMGFMT_Y_DEPTH(fmt);
- assert(false);
- return 0;
-}
-
-static D3DFORMAT check_format(d3d_priv *priv, uint32_t movie_fmt,
- bool as_texture)
+static D3DFORMAT check_format(d3d_priv *priv, uint32_t movie_fmt)
{
- const char *type = as_texture ? "texture rendering" : "StretchRect";
const struct fmt_entry *cur = &fmt_table[0];
- // Don't try to handle weird packed texture formats (although I don't know
- // if D3D9 would even accept any such format for 3D rendering; and we
- // certainly don't try any tricks like matching it to RGB formats and
- // applying a YUV conversion matrix)
- if (as_texture && !IMGFMT_IS_ANY_RND(movie_fmt))
- return 0;
-
while (cur->mplayer_fmt) {
if (cur->mplayer_fmt == movie_fmt) {
HRESULT res;
- if (as_texture) {
- res = IDirect3D9_CheckDeviceFormat(priv->d3d_handle,
- D3DADAPTER_DEFAULT,
- DEVTYPE,
- priv->desktop_fmt,
- D3DUSAGE_DYNAMIC | D3DUSAGE_QUERY_FILTER,
- D3DRTYPE_TEXTURE,
- cur->fourcc);
- } else {
- /* Test conversion from Movie colorspace to
- * display's target colorspace. */
- res = IDirect3D9_CheckDeviceFormatConversion(priv->d3d_handle,
- D3DADAPTER_DEFAULT,
- DEVTYPE,
- cur->fourcc,
- priv->desktop_fmt);
- }
+ /* Test conversion from Movie colorspace to
+ * display's target colorspace. */
+ res = IDirect3D9_CheckDeviceFormatConversion(priv->d3d_handle,
+ D3DADAPTER_DEFAULT,
+ DEVTYPE,
+ cur->fourcc,
+ priv->desktop_fmt);
if (FAILED(res)) {
- MP_VERBOSE(priv, "Rejected image format "
- "(%s): %s\n", type, vo_format_name(cur->mplayer_fmt));
+ MP_VERBOSE(priv, "Rejected image format: %s\n",
+ vo_format_name(cur->mplayer_fmt));
return 0;
}
- MP_DBG(priv, "Accepted image format (%s): %s\n",
- type, vo_format_name(cur->mplayer_fmt));
+ MP_DBG(priv, "Accepted image format: %s\n",
+ vo_format_name(cur->mplayer_fmt));
return cur->fourcc;
}
@@ -1030,120 +747,30 @@ static D3DFORMAT check_format(d3d_priv *priv, uint32_t movie_fmt,
return 0;
}
-// Check whether YUV conversion with shaders can be done.
-static int check_shader_conversion(d3d_priv *priv, uint32_t fmt,
- D3DFORMAT shader_d3dfmts[MP_MAX_PLANES])
-{
- if (priv->opt_disable_shaders)
- return 0;
- struct mp_imgfmt_desc desc = mp_imgfmt_get_desc(fmt);
- if ((desc.flags & MP_IMGFLAG_YUV_P) && (desc.flags & MP_IMGFLAG_NE)) {
- if (desc.num_planes > MP_MAX_PLANES)
- return 0;
- int component_bits = desc.plane_bits;
- if (component_bits < 8 || component_bits > 16)
- return 0;
- bool is_8bit = component_bits == 8;
- if (!is_8bit && priv->opt_only_8bit)
- return 0;
- int texfmt = is_8bit ? IMGFMT_Y8 : IMGFMT_Y16;
- D3DFORMAT d3dfmt = check_format(priv, texfmt, true);
- if (d3dfmt) {
- for (int n = 0; n < desc.num_planes; n++)
- shader_d3dfmts[n] = d3dfmt;
- return SHADER_420P;
- }
- }
- return 0;
-}
-
// Return if the image format can be used. If it can, decide which rendering
// and conversion mode to use.
// If initialize is true, actually setup all variables to use the picked
// rendering mode.
static bool init_rendering_mode(d3d_priv *priv, uint32_t fmt, bool initialize)
{
- int n;
- int blit_d3dfmt = check_format(priv, fmt, false);
- int texture_d3dfmt = check_format(priv, fmt, true);
- D3DFORMAT shader_d3dfmts[MP_MAX_PLANES] = {0};
- int shader = check_shader_conversion(priv, fmt, shader_d3dfmts);
-
- if (priv->opt_disable_textures)
- texture_d3dfmt = 0;
- if (priv->opt_disable_shaders || !priv->pixel_shaders[shader])
- shader = 0;
- if (priv->opt_disable_stretchrect)
- blit_d3dfmt = 0;
-
- if (!(blit_d3dfmt || shader || texture_d3dfmt))
+ int blit_d3dfmt = check_format(priv, fmt);
+
+ if (!blit_d3dfmt)
return false;
MP_VERBOSE(priv, "Accepted rendering methods for "
- "format='%s': StretchRect=%#x, Texture=%#x, Texture+Shader=%d.\n",
- vo_format_name(fmt), blit_d3dfmt, texture_d3dfmt, shader);
+ "format='%s': StretchRect=%#x.\n",
+ vo_format_name(fmt), blit_d3dfmt);
if (!initialize)
return true;
// initialization doesn't fail beyond this point
- priv->use_shaders = 0;
- priv->use_textures = false;
priv->movie_src_fmt = 0;
- priv->plane_count = 0;
priv->image_format = fmt;
- if (blit_d3dfmt && priv->opt_prefer_stretchrect)
- texture_d3dfmt = shader = 0;
-
- if (texture_d3dfmt) {
- priv->use_textures = true;
- } else if (shader) {
- priv->use_textures = true;
- priv->use_shaders = shader;
- } else {
- assert(!!blit_d3dfmt);
- }
-
- if (priv->use_textures) {
- MP_VERBOSE(priv, "Using 3D rendering.\n");
-
- struct texplane *planes = &priv->planes[0];
- planes[0].shift_x = planes[0].shift_y = 0;
- planes[0].clearval = 0;
-
- if (!priv->use_shaders) {
- assert(IMGFMT_IS_ANY_RND(priv->image_format));
- priv->plane_count = 1;
- planes[0].bits_per_pixel = imgfmt_any_rnd_depth(priv->image_format);
- planes[0].d3d_format = texture_d3dfmt;
- } else {
- MP_VERBOSE(priv, "Using YUV shaders.\n");
-
- struct mp_imgfmt_desc desc = mp_imgfmt_get_desc(priv->image_format);
- priv->plane_count = desc.num_planes;
- for (n = 0; n < priv->plane_count; n++) {
- planes[n].d3d_format = shader_d3dfmts[n];
- planes[n].bits_per_pixel = desc.plane_bits;
- planes[n].shift_x = desc.xs[n];
- planes[n].shift_y = desc.ys[n];
- if (n > 0)
- planes[n].clearval = get_chroma_clear_val(desc.plane_bits);
- }
- }
-
- for (n = 0; n < priv->plane_count; n++) {
- planes[n].bytes_per_pixel = (planes[n].bits_per_pixel + 7) / 8;
- }
-
- } else {
- MP_VERBOSE(priv, "Using StretchRect.\n");
-
- priv->movie_src_fmt = blit_d3dfmt;
- }
-
- update_colorspace(priv);
+ priv->movie_src_fmt = blit_d3dfmt;
return true;
}
@@ -1171,24 +798,6 @@ static int query_format(struct vo *vo, int movie_fmt)
* *
****************************************************************************/
-static void update_colorspace(d3d_priv *priv)
-{
- struct mp_csp_params csp = MP_CSP_PARAMS_DEFAULTS;
- mp_csp_set_image_params(&csp, &priv->params);
-
- if (priv->use_shaders) {
- csp.input_bits = priv->planes[0].bits_per_pixel;
- csp.texture_bits = (csp.input_bits + 7) & ~7;
-
- struct mp_cmat coeff;
- mp_get_csp_matrix(&csp, &coeff);
- for (int row = 0; row < 3; row++) {
- for (int col = 0; col < 3; col++)
- priv->d3d_colormatrix.m[row][col] = coeff.m[row][col];
- priv->d3d_colormatrix.m[row][3] = coeff.c[row];
- }
- }
-}
/** @brief libvo Callback: Preinitialize the video card.
* Preinit the hardware just enough to be queried about
@@ -1203,9 +812,6 @@ static int preinit(struct vo *vo)
priv->vo = vo;
priv->log = vo->log;
- for (int n = 0; n < MAX_OSD_PARTS; n++)
- priv->osd[n] = talloc_zero(priv, struct osdpart);
-
priv->d3d9_dll = LoadLibraryA("d3d9.dll");
if (!priv->d3d9_dll) {
MP_ERR(priv, "Unable to dynamically load d3d9.dll\n");
@@ -1245,9 +851,6 @@ static int control(struct vo *vo, uint32_t request, void *data)
d3d_priv *priv = vo->priv;
switch (request) {
- case VOCTRL_REDRAW_FRAME:
- d3d_draw_frame(priv);
- return VO_TRUE;
case VOCTRL_SET_PANSCAN:
calc_fs_rect(priv);
priv->vo->want_redraw = true;
@@ -1294,6 +897,18 @@ static int reconfig(struct vo *vo, struct mp_image_params *params)
if (!resize_d3d(priv))
return VO_ERROR;
+ priv->dst_params = *params;
+ for (const struct fmt_entry *cur = &fmt_table[0]; cur->mplayer_fmt; ++cur) {
+ if (cur->fourcc == priv->desktop_fmt) {
+ priv->dst_params.imgfmt = cur->mplayer_fmt;
+ break;
+ }
+ }
+ mp_image_params_guess_csp(&priv->dst_params);
+ mp_mutex_lock(&vo->params_mutex);
+ vo->target_params = &priv->dst_params;
+ mp_mutex_unlock(&vo->params_mutex);
+
return 0; /* Success */
}
@@ -1351,81 +966,64 @@ static bool get_video_buffer(d3d_priv *priv, struct mp_image *out)
if (!priv->d3d_device)
return false;
- if (priv->use_textures) {
- if (!d3d_lock_video_textures(priv))
+ if (!priv->locked_rect.pBits) {
+ if (FAILED(IDirect3DSurface9_LockRect(priv->d3d_surface,
+ &priv->locked_rect, NULL, 0)))
+ {
+ MP_ERR(priv, "Surface lock failed.\n");
return false;
-
- for (int n = 0; n < priv->plane_count; n++) {
- struct texplane *plane = &priv->planes[n];
- out->planes[n] = plane->locked_rect.pBits;
- out->stride[n] = plane->locked_rect.Pitch;
- }
- } else {
- if (!priv->locked_rect.pBits) {
- if (FAILED(IDirect3DSurface9_LockRect(priv->d3d_surface,
- &priv->locked_rect, NULL, 0)))
- {
- MP_ERR(priv, "Surface lock failed.\n");
- return false;
- }
}
+ }
- uint8_t *base = priv->locked_rect.pBits;
- size_t stride = priv->locked_rect.Pitch;
+ uint8_t *base = priv->locked_rect.pBits;
+ size_t stride = priv->locked_rect.Pitch;
- out->planes[0] = base;
- out->stride[0] = stride;
+ out->planes[0] = base;
+ out->stride[0] = stride;
- if (out->num_planes == 2) {
- // NV12, NV21
- out->planes[1] = base + stride * out->h;
- out->stride[1] = stride;
- }
+ if (out->num_planes == 2) {
+ // NV12, NV21
+ out->planes[1] = base + stride * out->h;
+ out->stride[1] = stride;
+ }
- if (out->num_planes == 3) {
- bool swap = priv->movie_src_fmt == MAKEFOURCC('Y','V','1','2');
+ if (out->num_planes == 3) {
+ bool swap = priv->movie_src_fmt == MAKEFOURCC('Y','V','1','2');
- size_t uv_stride = stride / 2;
- uint8_t *u = base + out->h * stride;
- uint8_t *v = u + (out->h / 2) * uv_stride;
+ size_t uv_stride = stride / 2;
+ uint8_t *u = base + out->h * stride;
+ uint8_t *v = u + (out->h / 2) * uv_stride;
- out->planes[1] = swap ? v : u;
- out->planes[2] = swap ? u : v;
+ out->planes[1] = swap ? v : u;
+ out->planes[2] = swap ? u : v;
- out->stride[1] = out->stride[2] = uv_stride;
- }
+ out->stride[1] = out->stride[2] = uv_stride;
}
return true;
}
-static void draw_image(struct vo *vo, mp_image_t *mpi)
+static void draw_frame(struct vo *vo, struct vo_frame *frame)
{
d3d_priv *priv = vo->priv;
if (!priv->d3d_device)
- goto done;
+ return;
struct mp_image buffer;
if (!get_video_buffer(priv, &buffer))
- goto done;
+ return;
- mp_image_copy(&buffer, mpi);
+ if (!frame->current)
+ return;
- d3d_unlock_video_objects(priv);
+ mp_image_copy(&buffer, frame->current);
- if (priv->use_textures) {
- for (int n = 0; n < priv->plane_count; n++) {
- d3dtex_update(priv, &priv->planes[n].texture);
- }
- }
+ d3d_unlock_video_objects(priv);
priv->have_image = true;
- priv->osd_pts = mpi->pts;
+ priv->osd_pts = frame->current->pts;
d3d_draw_frame(priv);
-
-done:
- talloc_free(mpi);
}
static mp_image_t *get_window_screenshot(d3d_priv *priv)
@@ -1493,137 +1091,116 @@ static mp_image_t *get_window_screenshot(d3d_priv *priv)
return image;
error_exit:
- if (image)
- talloc_free(image);
+ talloc_free(image);
if (surface)
IDirect3DSurface9_Release(surface);
return NULL;
}
-static D3DCOLOR ass_to_d3d_color(uint32_t color)
+static void update_osd(d3d_priv *priv)
{
- uint32_t r = (color >> 24) & 0xff;
- uint32_t g = (color >> 16) & 0xff;
- uint32_t b = (color >> 8) & 0xff;
- uint32_t a = 0xff - (color & 0xff);
- return D3DCOLOR_ARGB(a, r, g, b);
-}
+ if (!priv->osd_cache)
+ priv->osd_cache = mp_draw_sub_alloc(priv, priv->vo->global);
-static int next_pow2(int v)
-{
- for (int x = 0; x < 30; x++) {
- if ((1 << x) >= v)
- return 1 << x;
- }
- return INT_MAX;
-}
+ struct sub_bitmap_list *sbs = osd_render(priv->vo->osd, priv->osd_res,
+ priv->osd_pts, 0, mp_draw_sub_formats);
-static bool upload_osd(d3d_priv *priv, struct osdpart *osd,
- struct sub_bitmaps *imgs)
-{
- D3DFORMAT fmt = priv->osd_fmt_table[imgs->format];
+ struct mp_rect act_rc[MAX_OSD_RECTS], mod_rc[64];
+ int num_act_rc = 0, num_mod_rc = 0;
- assert(imgs->packed);
+ struct mp_image *osd = mp_draw_sub_overlay(priv->osd_cache, sbs,
+ act_rc, MP_ARRAY_SIZE(act_rc), &num_act_rc,
+ mod_rc, MP_ARRAY_SIZE(mod_rc), &num_mod_rc);
- osd->change_id = imgs->change_id;
- osd->num_vertices = 0;
+ talloc_free(sbs);
- if (imgs->packed_w > osd->texture.tex_w
- || imgs->packed_h > osd->texture.tex_h
- || osd->format != imgs->format)
- {
- osd->format = imgs->format;
+ if (!osd) {
+ MP_ERR(priv, "Failed to render OSD.\n");
+ return;
+ }
- int new_w = next_pow2(imgs->packed_w);
- int new_h = next_pow2(imgs->packed_h);
+ if (!num_mod_rc && priv->osd_texture.system)
+ return; // nothing changed
+
+ priv->osd_num_vertices = 0;
+
+ if (osd->w > priv->osd_texture.tex_w || osd->h > priv->osd_texture.tex_h) {
+ int new_w = osd->w;
+ int new_h = osd->h;
d3d_fix_texture_size(priv, &new_w, &new_h);
MP_DBG(priv, "reallocate OSD surface to %dx%d.\n", new_w, new_h);
- d3dtex_release(priv, &osd->texture);
- d3dtex_allocate(priv, &osd->texture, fmt, new_w, new_h);
-
- if (!osd->texture.system)
- return false; // failed to allocate
+ d3dtex_release(priv, &priv->osd_texture);
+ if (!d3dtex_allocate(priv, &priv->osd_texture, D3DFMT_A8R8G8B8,
+ new_w, new_h))
+ return;
}
- RECT dirty_rc = { 0, 0, imgs->packed_w, imgs->packed_h };
+ // Lazy; could/should use the bounding rect, or perform multiple lock calls.
+ // The previous approach (fully packed texture) was more efficient.
+ RECT dirty_rc = { 0, 0, priv->osd_texture.w, priv->osd_texture.h };
D3DLOCKED_RECT locked_rect;
- if (FAILED(IDirect3DTexture9_LockRect(osd->texture.system, 0, &locked_rect,
+ if (FAILED(IDirect3DTexture9_LockRect(priv->osd_texture.system, 0, &locked_rect,
&dirty_rc, 0)))
{
MP_ERR(priv, "OSD texture lock failed.\n");
- return false;
+ return;
}
- int ps = fmt == D3DFMT_A8 ? 1 : 4;
- memc