vo_direct3d: rip out texture video rendering path

This isn't useful anymore. We have a much better d3d11 renderer in
vo_gpu. D3D11 is available in all supported Windows versions. The
StretchRect path might still be useful for someone (???), and leaving it
at least evades conflict about users who want to keep using this VO for
inexplicable reasons. (Low power usage might be a justified reason, but
still, no.)

Also fuck the win32 platform, it's a heap of stinky shit. Microsoft is
some sort of psycho clown software company. Granted, maybe still better
than much of the rest of Silly Con Valley.
This commit is contained in:
wm4 2020-05-13 21:35:32 +02:00
parent baabd5fce3
commit b36484063f
5 changed files with 66 additions and 659 deletions

View File

@ -67,6 +67,7 @@ Interface changes
entry)
- reading loop-file property as native property or mpv_node will now return
"inf" instead of boolean true (also affects loop option)
- remove some --vo-direct3d-... options (it got dumbed down; use --vo=gpu)
--- mpv 0.32.0 ---
- change behavior when using legacy option syntax with options that start
with two dashes (``--`` instead of a ``-``). Now, using the recommended

View File

@ -204,33 +204,8 @@ Available video output drivers are:
.. note:: This driver is for compatibility with systems that don't provide
proper OpenGL drivers, and where ANGLE does not perform well.
.. note:: Before to 0.21.0, ``direct3d_shaders`` and ``direct3d`` were
different, with ``direct3d`` not using shader by default. Now
both use shaders by default, and ``direct3d_shaders`` is a
deprecated alias. Use the ``--vo-direct3d-prefer-stretchrect``
or the ``--vo-direct3d-disable-shaders`` options to get the old
behavior of ``direct3d``.
The following global options are supported by this video output:
``--vo-direct3d-prefer-stretchrect``
Use ``IDirect3DDevice9::StretchRect`` over other methods if possible.
``--vo-direct3d-disable-stretchrect``
Never render the video using ``IDirect3DDevice9::StretchRect``.
``--vo-direct3d-disable-textures``
Never render the video using D3D texture rendering. Rendering with
textures + shader will still be allowed. Add ``disable-shaders`` to
completely disable video rendering with textures.
``--vo-direct3d-disable-shaders``
Never use shaders when rendering video.
``--vo-direct3d-only-8bit``
Never render YUV video with more than 8 bits per component.
Using this flag will force software conversion to 8-bit.
``--vo-direct3d-disable-texture-align``
Normally texture sizes are always aligned to 16. With this option
enabled, the video texture will always have exactly the same size as

View File

@ -1,142 +0,0 @@
#if 0
//
// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
//
// fxc /Tps_2_0 -DUSE_420P=1 /Fhd3d_shader_420p.h d3d_shader_yuv.hlsl
// /Vnd3d_shader_420p
//
//
// Parameters:
//
// float4x4 colormatrix;
// sampler2D tex0;
// sampler2D tex1;
// sampler2D tex2;
//
//
// Registers:
//
// Name Reg Size
// ------------ ----- ----
// colormatrix c0 4
// tex0 s0 1
// tex1 s1 1
// tex2 s2 1
//
ps_2_0
def c4, 1, 0, 0, 0
dcl t0.xy
dcl t1.xy
dcl t2.xy
dcl_2d s0
dcl_2d s1
dcl_2d s2
texld r0, t0, s0
texld r1, t1, s1
texld r2, t2, s2
mov r0.y, r1.x
mov r0.z, r2.x
mov r0.w, c4.x
dp4 r1.x, r0, c0
dp4 r1.y, r0, c1
dp4 r1.z, r0, c2
dp4 r1.w, r0, c3
mov oC0, r1
// approximately 11 instruction slots used (3 texture, 8 arithmetic)
#endif
const BYTE d3d_shader_420p[] =
{
0, 2, 255, 255, 254, 255,
67, 0, 67, 84, 65, 66,
28, 0, 0, 0, 215, 0,
0, 0, 0, 2, 255, 255,
4, 0, 0, 0, 28, 0,
0, 0, 0, 1, 0, 0,
208, 0, 0, 0, 108, 0,
0, 0, 2, 0, 0, 0,
4, 0, 2, 0, 120, 0,
0, 0, 0, 0, 0, 0,
136, 0, 0, 0, 3, 0,
0, 0, 1, 0, 2, 0,
144, 0, 0, 0, 0, 0,
0, 0, 160, 0, 0, 0,
3, 0, 1, 0, 1, 0,
6, 0, 168, 0, 0, 0,
0, 0, 0, 0, 184, 0,
0, 0, 3, 0, 2, 0,
1, 0, 10, 0, 192, 0,
0, 0, 0, 0, 0, 0,
99, 111, 108, 111, 114, 109,
97, 116, 114, 105, 120, 0,
3, 0, 3, 0, 4, 0,
4, 0, 1, 0, 0, 0,
0, 0, 0, 0, 116, 101,
120, 48, 0, 171, 171, 171,
4, 0, 12, 0, 1, 0,
1, 0, 1, 0, 0, 0,
0, 0, 0, 0, 116, 101,
120, 49, 0, 171, 171, 171,
4, 0, 12, 0, 1, 0,
1, 0, 1, 0, 0, 0,
0, 0, 0, 0, 116, 101,
120, 50, 0, 171, 171, 171,
4, 0, 12, 0, 1, 0,
1, 0, 1, 0, 0, 0,
0, 0, 0, 0, 112, 115,
95, 50, 95, 48, 0, 77,
105, 99, 114, 111, 115, 111,
102, 116, 32, 40, 82, 41,
32, 72, 76, 83, 76, 32,
83, 104, 97, 100, 101, 114,
32, 67, 111, 109, 112, 105,
108, 101, 114, 32, 57, 46,
50, 57, 46, 57, 53, 50,
46, 51, 49, 49, 49, 0,
81, 0, 0, 5, 4, 0,
15, 160, 0, 0, 128, 63,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
31, 0, 0, 2, 0, 0,
0, 128, 0, 0, 3, 176,
31, 0, 0, 2, 0, 0,
0, 128, 1, 0, 3, 176,
31, 0, 0, 2, 0, 0,
0, 128, 2, 0, 3, 176,
31, 0, 0, 2, 0, 0,
0, 144, 0, 8, 15, 160,
31, 0, 0, 2, 0, 0,
0, 144, 1, 8, 15, 160,
31, 0, 0, 2, 0, 0,
0, 144, 2, 8, 15, 160,
66, 0, 0, 3, 0, 0,
15, 128, 0, 0, 228, 176,
0, 8, 228, 160, 66, 0,
0, 3, 1, 0, 15, 128,
1, 0, 228, 176, 1, 8,
228, 160, 66, 0, 0, 3,
2, 0, 15, 128, 2, 0,
228, 176, 2, 8, 228, 160,
1, 0, 0, 2, 0, 0,
2, 128, 1, 0, 0, 128,
1, 0, 0, 2, 0, 0,
4, 128, 2, 0, 0, 128,
1, 0, 0, 2, 0, 0,
8, 128, 4, 0, 0, 160,
9, 0, 0, 3, 1, 0,
1, 128, 0, 0, 228, 128,
0, 0, 228, 160, 9, 0,
0, 3, 1, 0, 2, 128,
0, 0, 228, 128, 1, 0,
228, 160, 9, 0, 0, 3,
1, 0, 4, 128, 0, 0,
228, 128, 2, 0, 228, 160,
9, 0, 0, 3, 1, 0,
8, 128, 0, 0, 228, 128,
3, 0, 228, 160, 1, 0,
0, 2, 0, 8, 15, 128,
1, 0, 228, 128, 255, 255,
0, 0
};

View File

@ -1,32 +0,0 @@
// Compile with:
// fxc.exe /Tps_2_0 -DUSE_420P=1 /Fhd3d_shader_420p.h d3d_shader_yuv.hlsl /Vnd3d_shader_420p
// fxc.exe /Tps_2_0 -DUSE_NV12=1 /Fhd3d_shader_nv12.h d3d_shader_yuv.hlsl /Vnd3d_shader_nv12
// Be careful with this shader. You can't use constant slots, since we don't
// load the shader with D3DX. All uniform variables are mapped to hardcoded
// constant slots.
sampler2D tex0 : register(s0);
sampler2D tex1 : register(s1);
sampler2D tex2 : register(s2);
uniform float4x4 colormatrix : register(c0);
float4 main(float2 t0 : TEXCOORD0,
float2 t1 : TEXCOORD1,
float2 t2 : TEXCOORD2)
: COLOR
{
#ifdef USE_420P
float4 c = float4(tex2D(tex0, t0).x,
tex2D(tex1, t1).x,
tex2D(tex2, t2).x,
1);
#endif
#ifdef USE_NV12
float4 c = float4(tex2D(tex0, t0).x,
tex2D(tex1, t1).xz,
1);
#endif
return mul(c, colormatrix);
}

View File

@ -45,12 +45,6 @@
#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
@ -62,15 +56,6 @@ typedef struct {
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,21 +73,6 @@ 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;
@ -111,22 +81,11 @@ struct osdpart {
vertex_osd *vertices;
};
enum shaders {
SHADER_NONE = 0,
SHADER_420P,
NUM_SHADERS
};
/* 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;
// debugging
int opt_force_power_of_2;
@ -149,16 +108,6 @@ typedef struct d3d_priv {
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];
D3DFORMAT movie_src_fmt; /**< Movie colorspace format (depends on
the movie's codec) */
@ -215,15 +164,10 @@ static const struct fmt_entry fmt_table[] = {
{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 +342,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;
}
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");
}
priv->locked_rect.pBits = NULL;
}
// 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 +357,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.
@ -455,46 +380,11 @@ 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,
@ -503,44 +393,10 @@ static bool d3d_configure_video_objects(d3d_priv *priv)
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;
}
}
}
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 +429,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 +441,7 @@ static bool create_d3d_surfaces(d3d_priv *priv)
IDirect3DDevice9_SetSamplerState(priv->d3d_device, n, D3DSAMP_ADDRESSV,
D3DTADDRESS_CLAMP);
}
*/
return 1;
}
@ -695,12 +554,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;
@ -745,22 +598,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 +605,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 +699,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,57 +713,6 @@ 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;
@ -948,7 +726,6 @@ static uint32_t d3d_draw_frame(d3d_priv *priv)
MP_ERR(priv, "Copying frame to the backbuffer failed.\n");
return VO_ERROR;
}
}
render_osd:
@ -957,54 +734,13 @@ 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)
static D3DFORMAT check_format(d3d_priv *priv, uint32_t movie_fmt)
{
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)
{
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,
@ -1012,15 +748,14 @@ static D3DFORMAT check_format(d3d_priv *priv, uint32_t movie_fmt,
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 +765,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);
int blit_d3dfmt = check_format(priv, fmt);
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))
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);
return true;
}
@ -1171,24 +816,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
@ -1351,16 +978,6 @@ 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))
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)))
@ -1394,7 +1011,6 @@ static bool get_video_buffer(d3d_priv *priv, struct mp_image *out)
out->stride[1] = out->stride[2] = uv_stride;
}
}
return true;
}
@ -1413,12 +1029,6 @@ static void draw_image(struct vo *vo, mp_image_t *mpi)
d3d_unlock_video_objects(priv);
if (priv->use_textures) {
for (int n = 0; n < priv->plane_count; n++) {
d3dtex_update(priv, &priv->planes[n].texture);
}
}
priv->have_image = true;
priv->osd_pts = mpi->pts;
@ -1684,11 +1294,6 @@ static void draw_osd(struct vo *vo)
#define OPT_BASE_STRUCT d3d_priv
static const struct m_option opts[] = {
{"prefer-stretchrect", OPT_FLAG(opt_prefer_stretchrect)},
{"disable-textures", OPT_FLAG(opt_disable_textures)},
{"disable-stretchrect", OPT_FLAG(opt_disable_stretchrect)},
{"disable-shaders", OPT_FLAG(opt_disable_shaders)},
{"only-8bit", OPT_FLAG(opt_only_8bit)},
{"force-power-of-2", OPT_FLAG(opt_force_power_of_2)},
{"disable-texture-align", OPT_FLAG(opt_disable_texture_align)},
{"texture-memory", OPT_CHOICE(opt_texture_memory,