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.c80
1 files changed, 75 insertions, 5 deletions
diff --git a/libvo/vo_direct3d.c b/libvo/vo_direct3d.c
index 95bff26454..fdecee8c94 100644
--- a/libvo/vo_direct3d.c
+++ b/libvo/vo_direct3d.c
@@ -48,13 +48,15 @@
// shaders generated by fxc.exe from d3d_shader_yuv.hlsl
#include "d3d_shader_yuv.h"
+#include "d3d_shader_yuv_2ch.h"
// TODO: beg someone to add this (there is already IMGFMT_Y8)
// equals MAKEFOURCC('Y', '1', '6', ' ')
#define IMGFMT_Y16 0x20363159
+#define IMGFMT_A8Y8 MAKEFOURCC('A', '8', 'Y', '8')
-#define IMGFMT_IS_Y(x) ((x) == IMGFMT_Y8 || (x) == IMGFMT_Y16)
+#define IMGFMT_IS_Y(x) ((x) == IMGFMT_Y8 || (x) == IMGFMT_Y16 || (x) == IMGFMT_A8Y8)
#define IMGFMT_Y_DEPTH(x) ((x) == IMGFMT_Y8 ? 8 : 16)
#define DEVTYPE D3DDEVTYPE_HAL
@@ -132,6 +134,7 @@ typedef struct d3d_priv {
int opt_texture_memory;
int opt_swap_discard;
int opt_exact_backbuffer;
+ int opt_16bit_textures;
struct vo *vo;
@@ -151,6 +154,7 @@ typedef struct d3d_priv {
StretchRect */
bool use_shaders; /**< use shader for YUV color conversion
(or possibly for RGB video equalizers) */
+ bool use_2ch_hack; /**< 2 byte YUV formats use 2 channel hack */
int plane_count;
struct texplane planes[3];
@@ -190,6 +194,7 @@ typedef struct d3d_priv {
int max_texture_height; /**< from the device capabilities */
D3DMATRIX d3d_colormatrix;
+ float d3d_depth_vector[4];
struct mp_csp_details colorspace;
struct mp_csp_equalizer video_eq;
@@ -224,6 +229,7 @@ static const struct fmt_entry fmt_table[] = {
// grayscale (can be considered both packed and planar)
{IMGFMT_Y8, D3DFMT_L8},
{IMGFMT_Y16, D3DFMT_L16},
+ {IMGFMT_A8Y8, D3DFMT_A8L8},
{0},
};
@@ -1013,6 +1019,9 @@ static uint32_t d3d_draw_frame(d3d_priv *priv)
IDirect3DDevice9_SetPixelShaderConstantF(priv->d3d_device, 0,
&priv->d3d_colormatrix._11,
4);
+ IDirect3DDevice9_SetPixelShaderConstantF(priv->d3d_device, 5,
+ priv->d3d_depth_vector,
+ 1);
}
IDirect3DDevice9_SetFVF(priv->d3d_device, D3DFVF_VIDEO_VERTEX);
@@ -1130,7 +1139,14 @@ static D3DFORMAT check_shader_conversion(d3d_priv *priv, uint32_t fmt)
bool is_8bit = component_bits == 8;
if (!is_8bit && priv->opt_only_8bit)
return 0;
- return check_format(priv, is_8bit ? IMGFMT_Y8 : IMGFMT_Y16, true);
+ int texfmt = IMGFMT_Y8;
+ if (!is_8bit) {
+ if (priv->opt_16bit_textures)
+ texfmt = IMGFMT_Y16;
+ else
+ texfmt = IMGFMT_A8Y8;
+ }
+ return check_format(priv, texfmt, true);
}
// Return if the image format can be used. If it can, decide which rendering
@@ -1165,6 +1181,7 @@ static bool init_rendering_mode(d3d_priv *priv, uint32_t fmt, bool initialize)
priv->use_shaders = false;
priv->use_textures = false;
+ priv->use_2ch_hack = false;
priv->movie_src_fmt = 0;
priv->pixel_shader_data = NULL;
priv->plane_count = 0;
@@ -1209,7 +1226,14 @@ static bool init_rendering_mode(d3d_priv *priv, uint32_t fmt, bool initialize)
planes[n].clearval = get_chroma_clear_val(component_bits);
}
}
- priv->pixel_shader_data = d3d_shader_yuv;
+ if (shader_d3dfmt != D3DFMT_A8L8) {
+ priv->pixel_shader_data = d3d_shader_yuv;
+ } else {
+ mp_msg(MSGT_VO, MSGL_WARN, "<vo_direct3d>Using YUV 2ch hack.\n");
+
+ priv->pixel_shader_data = d3d_shader_yuv_2ch;
+ priv->use_2ch_hack = true;
+ }
}
for (n = 0; n < priv->plane_count; n++) {
@@ -1253,6 +1277,30 @@ static int query_format(d3d_priv *priv, uint32_t movie_fmt)
* *
****************************************************************************/
+static void get_2ch_depth_multiplier(int depth, float *out_f1, float *out_f2) {
+ // How to get these values:
+ // The suffix i8 and i16 is for values with 8/16 bit fixed point numbers.
+ // The suffix f is for float, ideally in the range 0.0-1.0.
+ // c_i8 is a two component vector, sampled from a two channel texture.
+ // (c_i8.x is the low byte, c_i8.y is the high byte)
+ // r_f is the resulting color scalar value.
+ //
+ // c_i8 = c_f * (2^8-1)
+ // r_i16 = c_i8.x + c_i8.y * 2^8
+ // r_f = r_i16 / (2^16-1)
+ // = c_f.x * (2^8-1) / (2^16-1) + c_f.y * (2^8-1) * 2^8 / (2^16-1)
+ // = c_f.x * ((2^8-1) / (2^16-1)) + c_f.y * (2^8 * ((2^8-1) / (2^16-1)))
+ // out = ((2^8-1) / (2^16-1), 2^8 * ((2^8-1) / (2^16-1)))
+ // The result color is r_f = dot(c_f, out).
+ // Same goes for other bit depth, such as 10 bit. Assuming (2^depth-1) is
+ // the maximum possible value at that depth, you have to scale the value
+ // r_i16 with it, the factor (2^16-1) in the formula above has to be
+ // replaced with (2^depth-1).
+ float factor = (float)((1 << 8) - 1) / (float)((1 << depth) - 1);
+ *out_f1 = factor;
+ *out_f2 = 256.0 * factor;
+}
+
static void update_colorspace(d3d_priv *priv)
{
float coeff[3][4];
@@ -1260,8 +1308,19 @@ static void update_colorspace(d3d_priv *priv)
mp_csp_copy_equalizer_values(&csp, &priv->video_eq);
if (priv->use_shaders) {
- csp.input_bits = priv->planes[0].bits_per_pixel;
- csp.texture_bits = (csp.input_bits + 7) & ~7;
+ if (!priv->use_2ch_hack) {
+ csp.input_bits = priv->planes[0].bits_per_pixel;
+ csp.texture_bits = (csp.input_bits + 7) & ~7;
+ } else {
+ float f1, f2;
+ get_2ch_depth_multiplier(priv->planes[0].bits_per_pixel, &f1, &f2);
+ priv->d3d_depth_vector[0] = f1;
+ priv->d3d_depth_vector[1] = f2;
+ priv->d3d_depth_vector[2] = priv->d3d_depth_vector[3] = 0;
+ // no change
+ csp.input_bits = 8;
+ csp.texture_bits = 8;
+ }
}
mp_get_yuv2rgb_coeffs(&csp, coeff);
@@ -1314,6 +1373,14 @@ const char *options_help_text = "-vo direct3d command line help:\n"
" Might be slower too, as it must (?) clear every frame.\n"
" exact-backbuffer\n"
" Always resize the backbuffer to window size.\n"
+" no16bit-textures\n"
+" Don't use textures with a 16 bit color channel for YUV formats that\n"
+" use more than 8 bits per component. Instead, use D3DFMT_A8L8 textures\n"
+" and compute the values sampled from the 2 channels back into one.\n"
+" Might be slower, since the shader becomes slightly more complicated.\n"
+" Might work better, if your drivers either don't support D3DFMT_L16,\n"
+" or if either the texture unit or the shaders don't operate in at least\n"
+" 16 bit precision.\n"
"";
/** @brief libvo Callback: Preinitialize the video card.
@@ -1331,6 +1398,8 @@ static int preinit_internal(struct vo *vo, const char *arg, bool allow_shaders)
*priv = (d3d_priv) {
.vo = vo,
+ .opt_16bit_textures = true,
+
.colorspace = MP_CSP_DETAILS_DEFAULTS,
.video_eq = { MP_CSP_EQ_CAPS_COLORMATRIX },
};
@@ -1351,6 +1420,7 @@ static int preinit_internal(struct vo *vo, const char *arg, bool allow_shaders)
{"texture-memory", OPT_ARG_INT, &priv->opt_texture_memory},
{"swap-discard", OPT_ARG_BOOL, &priv->opt_swap_discard},
{"exact-backbuffer", OPT_ARG_BOOL, &priv->opt_exact_backbuffer},
+ {"16bit-textures", OPT_ARG_BOOL, &priv->opt_16bit_textures},
{NULL}
};
if (subopt_parse(arg, subopts) != 0) {