[vlc-commits] direct3d11: sample only the visible area of the texture
Steve Lhomme
git at videolan.org
Thu Aug 27 16:20:57 CEST 2020
vlc | branch: master | Steve Lhomme <robux4 at ycbcr.xyz> | Thu Aug 27 15:38:04 2020 +0200| [968e3788f56b5b6ad6cfdd12b6bbcf87e5853c7c] | committer: Steve Lhomme
direct3d11: sample only the visible area of the texture
This is similar to how the OpenGL module works and is easier to handle cropped
sources.
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=968e3788f56b5b6ad6cfdd12b6bbcf87e5853c7c
---
modules/video_output/win32/d3d11_quad.c | 121 ++++++-----------------------
modules/video_output/win32/d3d11_quad.h | 2 +-
modules/video_output/win32/d3d11_shaders.c | 4 +-
modules/video_output/win32/d3d11_shaders.h | 3 +-
modules/video_output/win32/direct3d11.c | 62 ++++++---------
5 files changed, 52 insertions(+), 140 deletions(-)
diff --git a/modules/video_output/win32/d3d11_quad.c b/modules/video_output/win32/d3d11_quad.c
index f5d2bc285b..ecfbf99b39 100644
--- a/modules/video_output/win32/d3d11_quad.c
+++ b/modules/video_output/win32/d3d11_quad.c
@@ -265,89 +265,14 @@ static void orientationVertexOrder(video_orientation_t orientation, int vertex_o
}
}
-static void SetupQuadFlat(d3d_vertex_t *dst_data, const RECT *output,
- const d3d_quad_t *quad,
+static void SetupQuadFlat(d3d_vertex_t *dst_data, const POINT *output,
WORD *triangle_pos, video_orientation_t orientation)
{
- unsigned int src_width = quad->i_width;
- unsigned int src_height = quad->i_height;
+ unsigned int src_width = output->x;
+ unsigned int src_height = output->y;
float MidX,MidY;
- float top, bottom, left, right;
- /* find the middle of the visible part of the texture, it will be a 0,0
- * the rest of the visible area must correspond to -1,1 */
- switch (orientation)
- {
- case ORIENT_ROTATED_90: /* 90° anti clockwise */
- /* right/top aligned */
- MidY = (output->left + output->right) / 2.f;
- MidX = (output->top + output->bottom) / 2.f;
- top = MidY / (MidY - output->top);
- bottom = -(src_height - MidX) / (MidX - output->top);
- left = (MidX - src_height) / (MidX - output->left);
- right = MidX / (MidX - (src_width - output->right));
- break;
- case ORIENT_ROTATED_180: /* 180° */
- /* right/top aligned */
- MidY = (output->top + output->bottom) / 2.f;
- MidX = (output->left + output->right) / 2.f;
- top = (src_height - MidY) / (output->bottom - MidY);
- bottom = -MidY / (MidY - output->top);
- left = -MidX / (MidX - output->left);
- right = (src_width - MidX) / (output->right - MidX);
- break;
- case ORIENT_ROTATED_270: /* 90° clockwise */
- /* right/top aligned */
- MidY = (output->left + output->right) / 2.f;
- MidX = (output->top + output->bottom) / 2.f;
- top = (src_width - MidX) / (output->right - MidX);
- bottom = -MidY / (MidY - output->top);
- left = -MidX / (MidX - output->left);
- right = (src_height - MidY) / (output->bottom - MidY);
- break;
- case ORIENT_ANTI_TRANSPOSED:
- MidY = (output->left + output->right) / 2.f;
- MidX = (output->top + output->bottom) / 2.f;
- top = (src_width - MidX) / (output->right - MidX);
- bottom = -MidY / (MidY - output->top);
- left = -(src_height - MidY) / (output->bottom - MidY);
- right = MidX / (MidX - output->left);
- break;
- case ORIENT_TRANSPOSED:
- MidY = (output->left + output->right) / 2.f;
- MidX = (output->top + output->bottom) / 2.f;
- top = (src_width - MidX) / (output->right - MidX);
- bottom = -MidY / (MidY - output->top);
- left = -MidX / (MidX - output->left);
- right = (src_height - MidY) / (output->bottom - MidY);
- break;
- case ORIENT_VFLIPPED:
- MidY = (output->top + output->bottom) / 2.f;
- MidX = (output->left + output->right) / 2.f;
- top = (src_height - MidY) / (output->bottom - MidY);
- bottom = -MidY / (MidY - output->top);
- left = -MidX / (MidX - output->left);
- right = (src_width - MidX) / (output->right - MidX);
- break;
- case ORIENT_HFLIPPED:
- MidY = (output->top + output->bottom) / 2.f;
- MidX = (output->left + output->right) / 2.f;
- top = MidY / (MidY - output->top);
- bottom = -(src_height - MidY) / (output->bottom - MidY);
- left = -(src_width - MidX) / (output->right - MidX);
- right = MidX / (MidX - output->left);
- break;
- case ORIENT_NORMAL:
- default:
- /* left/top aligned */
- MidY = (output->top + output->bottom) / 2.f;
- MidX = (output->left + output->right) / 2.f;
- top = MidY / (MidY - output->top);
- bottom = -(src_height - MidY) / (output->bottom - MidY);
- left = -MidX / (MidX - output->left);
- right = (src_width - MidX) / (output->right - MidX);
- break;
- }
+ float top = 1, bottom = -1, left = -1, right = 1;
const float vertices_coords[4][2] = {
{ left, bottom },
@@ -409,11 +334,8 @@ static void SetupQuadFlat(d3d_vertex_t *dst_data, const RECT *output,
}
}
-static void SetupQuadSphere(d3d_vertex_t *dst_data, const RECT *output,
- const d3d_quad_t *quad, WORD *triangle_pos)
+static void SetupQuadSphere(d3d_vertex_t *dst_data, WORD *triangle_pos)
{
- const float scaleX = (float)(RECTWidth(*output)) / quad->i_width;
- const float scaleY = (float)(RECTHeight(*output)) / quad->i_height;
for (unsigned lat = 0; lat <= nbLatBands; lat++) {
float theta = lat * (float) M_PI / nbLatBands;
float sinTheta, cosTheta;
@@ -435,8 +357,8 @@ static void SetupQuadSphere(d3d_vertex_t *dst_data, const RECT *output,
dst_data[off1].position.y = SPHERE_RADIUS * y;
dst_data[off1].position.z = SPHERE_RADIUS * z;
- dst_data[off1].texture.x = scaleX * lon / (float) nbLonBands; // 0(left) to 1(right)
- dst_data[off1].texture.y = scaleY * lat / (float) nbLatBands; // 0(top) to 1 (bottom)
+ dst_data[off1].texture.x = lon / (float) nbLonBands;
+ dst_data[off1].texture.y = lat / (float) nbLatBands;
}
}
@@ -459,8 +381,7 @@ static void SetupQuadSphere(d3d_vertex_t *dst_data, const RECT *output,
}
-static void SetupQuadCube(d3d_vertex_t *dst_data, const RECT *output,
- const d3d_quad_t *quad, WORD *triangle_pos)
+static void SetupQuadCube(d3d_vertex_t *dst_data, WORD *triangle_pos)
{
#define CUBEFACE(swap, value) \
swap(value, -1.f, 1.f), \
@@ -486,11 +407,8 @@ static void SetupQuadCube(d3d_vertex_t *dst_data, const RECT *output,
#undef Z_FACE
#undef CUBEFACE
- const float scaleX = (float)(output->right - output->left) / quad->i_width;
- const float scaleY = (float)(output->bottom - output->top) / quad->i_height;
-
- const float col[] = {0.f, scaleX / 3, scaleX * 2 / 3, scaleX};
- const float row[] = {0.f, scaleY / 2, scaleY};
+ const float col[] = {0.f, 1.f / 3, 2.f / 3, 1.f};
+ const float row[] = {0.f, 1.f / 2, 1.f};
const float tex[] = {
col[1], row[1], // front
@@ -550,7 +468,7 @@ static void SetupQuadCube(d3d_vertex_t *dst_data, const RECT *output,
#undef D3D11_UpdateQuadPosition
bool D3D11_UpdateQuadPosition( vlc_object_t *o, d3d11_device_t *d3d_dev, d3d_quad_t *quad,
- const RECT *output, video_orientation_t orientation )
+ const POINT *output, video_orientation_t orientation )
{
bool result = true;
HRESULT hr;
@@ -579,13 +497,13 @@ bool D3D11_UpdateQuadPosition( vlc_object_t *o, d3d11_device_t *d3d_dev, d3d_qua
switch (quad->projection)
{
case PROJECTION_MODE_RECTANGULAR:
- SetupQuadFlat(dst_data, output, quad, mappedResource.pData, orientation);
+ SetupQuadFlat(dst_data, output, mappedResource.pData, orientation);
break;
case PROJECTION_MODE_EQUIRECTANGULAR:
- SetupQuadSphere(dst_data, output, quad, mappedResource.pData);
+ SetupQuadSphere(dst_data, mappedResource.pData);
break;
case PROJECTION_MODE_CUBEMAP_LAYOUT_STANDARD:
- SetupQuadCube(dst_data, output, quad, mappedResource.pData);
+ SetupQuadCube(dst_data, mappedResource.pData);
break;
default:
msg_Warn(o, "Projection mode %d not handled", quad->projection);
@@ -982,6 +900,17 @@ int D3D11_SetupQuad(vlc_object_t *o, d3d11_device_t *d3d_dev, const video_format
};
PS_COLOR_TRANSFORM colorspace;
+ memcpy(colorspace.SourceCrop, IDENTITY_4X4, sizeof(colorspace.SourceCrop));
+ float scale_w = (float)fmt->i_visible_width / fmt->i_width;
+ float scale_h = (float)fmt->i_visible_height / fmt->i_height;
+ float left = scale_w * fmt->i_x_offset;
+ float top = scale_h * fmt->i_y_offset;
+
+ colorspace.SourceCrop[0*4 + 0] = scale_h;
+ colorspace.SourceCrop[1*4 + 1] = scale_w;
+
+ colorspace.SourceCrop[0*4 + 3] = left / fmt->i_visible_width;
+ colorspace.SourceCrop[1*4 + 3] = top / fmt->i_visible_height;
memcpy(colorspace.WhitePoint, IDENTITY_4X4, sizeof(colorspace.WhitePoint));
diff --git a/modules/video_output/win32/d3d11_quad.h b/modules/video_output/win32/d3d11_quad.h
index db3926befe..662af7fead 100644
--- a/modules/video_output/win32/d3d11_quad.h
+++ b/modules/video_output/win32/d3d11_quad.h
@@ -61,7 +61,7 @@ int D3D11_SetupQuad(vlc_object_t *, d3d11_device_t *, const video_format_t *, d3
#define D3D11_SetupQuad(a,b,c,d,e) D3D11_SetupQuad(VLC_OBJECT(a),b,c,d,e)
bool D3D11_UpdateQuadPosition( vlc_object_t *, d3d11_device_t *, d3d_quad_t *,
- const RECT *output, video_orientation_t );
+ const POINT *output, video_orientation_t );
#define D3D11_UpdateQuadPosition(a,b,c,d,e) D3D11_UpdateQuadPosition(VLC_OBJECT(a),b,c,d,e)
void D3D11_UpdateViewport(d3d_quad_t *, const RECT *, const d3d_format_t *display);
diff --git a/modules/video_output/win32/d3d11_shaders.c b/modules/video_output/win32/d3d11_shaders.c
index 8f718b933c..e1df979692 100644
--- a/modules/video_output/win32/d3d11_shaders.c
+++ b/modules/video_output/win32/d3d11_shaders.c
@@ -61,6 +61,7 @@ static const char* globPixelShaderDefault = "\
};\n\
cbuffer PS_COLOR_TRANSFORM : register(b1)\n\
{\n\
+ float4x4 SourceCrop;\n\
float4x4 WhitePoint;\n\
float4x4 Colorspace;\n\
float4x4 Primaries;\n\
@@ -117,7 +118,8 @@ static const char* globPixelShaderDefault = "\
%s;\n\
}\n\
\n\
- inline float4 sampleTexture(SamplerState samplerState, float3 coords) {\n\
+ inline float4 sampleTexture(SamplerState samplerState, float3 raw_coords) {\n\
+ float3 coords = mul(float4(raw_coords.xyz, 1), SourceCrop).xyz;\n\
float4 sample;\n\
%s /* sampling routine in sample */\n\
return sample;\n\
diff --git a/modules/video_output/win32/d3d11_shaders.h b/modules/video_output/win32/d3d11_shaders.h
index 7712c3eff3..f3e47d48cc 100644
--- a/modules/video_output/win32/d3d11_shaders.h
+++ b/modules/video_output/win32/d3d11_shaders.h
@@ -57,6 +57,7 @@ typedef struct {
} PS_CONSTANT_BUFFER;
typedef struct {
+ FLOAT SourceCrop[4*4];
FLOAT WhitePoint[4*4];
FLOAT Colorspace[4*4];
FLOAT Primaries[4*4];
@@ -94,8 +95,6 @@ typedef struct
ID3D11PixelShader *d3dpixelShader[D3D11_MAX_SHADER_VIEW];
ID3D11SamplerState *d3dsampState[2];
D3D11_VIEWPORT cropViewport[D3D11_MAX_SHADER_VIEW];
- unsigned int i_width;
- unsigned int i_height;
video_projection_mode_t projection;
PS_CONSTANT_BUFFER shaderConstants;
diff --git a/modules/video_output/win32/direct3d11.c b/modules/video_output/win32/direct3d11.c
index b6881ecc8b..b0f2e5ad0d 100644
--- a/modules/video_output/win32/direct3d11.c
+++ b/modules/video_output/win32/direct3d11.c
@@ -277,11 +277,9 @@ static void UpdateSize(vout_display_t *vd)
D3D11_UpdateViewport( &sys->picQuad, &rect_dst, sys->display.pixelFormat );
- RECT source_rect = {
- .left = vd->fmt.i_x_offset,
- .right = vd->fmt.i_x_offset + vd->fmt.i_visible_width,
- .top = vd->fmt.i_y_offset,
- .bottom = vd->fmt.i_y_offset + vd->fmt.i_visible_height,
+ POINT source_rect = {
+ .x = vd->source.i_visible_width,
+ .y = vd->source.i_visible_height,
};
d3d11_device_lock( sys->d3d_dev );
@@ -623,17 +621,9 @@ static void PreparePicture(vout_display_t *vd, picture_t *picture, subpicture_t
* display, do it preferrably when creating the texture */
assert(p_sys->renderSrc[0]!=NULL);
}
- if ( sys->picQuad.i_height != texDesc.Height ||
- sys->picQuad.i_width != texDesc.Width )
- {
- /* the decoder produced different sizes than the vout, we need to
- * adjust the vertex */
- sys->picQuad.i_height = texDesc.Height;
- sys->picQuad.i_width = texDesc.Width;
-
- CommonPlacePicture(vd, &sys->area, &sys->sys);
- UpdateSize(vd);
- }
+ // we should receive a source update if they don't match
+ assert( vd->source.i_height == texDesc.Height );
+ assert( vd->source.i_width == texDesc.Width );
}
}
@@ -818,16 +808,6 @@ static int Direct3D11Open(vout_display_t *vd, video_format_t *fmtp, vlc_video_co
}
}
- /* adjust the decoder sizes to have proper padding */
- sys->picQuad.i_width = fmt.i_width;
- sys->picQuad.i_height = fmt.i_height;
- if ( sys->picQuad.textureFormat->formatTexture != DXGI_FORMAT_R8G8B8A8_UNORM &&
- sys->picQuad.textureFormat->formatTexture != DXGI_FORMAT_B5G6R5_UNORM )
- {
- sys->picQuad.i_width = (sys->picQuad.i_width + 0x01) & ~0x01;
- sys->picQuad.i_height = (sys->picQuad.i_height + 0x01) & ~0x01;
- }
-
CommonPlacePicture(vd, &sys->area, &sys->sys);
err = QueryDisplayFormat(vd, &fmt);
@@ -1075,11 +1055,9 @@ static int Direct3D11CreateFormatResources(vout_display_t *vd, const video_forma
return VLC_EGENERIC;
}
- RECT source_rect = {
- .left = vd->fmt.i_x_offset,
- .right = vd->fmt.i_x_offset + vd->fmt.i_visible_width,
- .top = vd->fmt.i_y_offset,
- .bottom = vd->fmt.i_y_offset + vd->fmt.i_visible_height,
+ POINT source_rect = {
+ .x = vd->source.i_visible_width,
+ .y = vd->source.i_visible_height,
};
if (!D3D11_UpdateQuadPosition(vd, sys->d3d_dev, &sys->picQuad, &source_rect, vd->source.orientation))
{
@@ -1106,8 +1084,15 @@ static int Direct3D11CreateFormatResources(vout_display_t *vd, const video_forma
/* we need a staging texture */
ID3D11Texture2D *textures[D3D11_MAX_SHADER_VIEW] = {0};
video_format_t texture_fmt = vd->source;
- texture_fmt.i_width = sys->picQuad.i_width;
- texture_fmt.i_height = sys->picQuad.i_height;
+
+ /* adjust the decoder sizes to have proper padding */
+ if ( sys->picQuad.textureFormat->formatTexture != DXGI_FORMAT_R8G8B8A8_UNORM &&
+ sys->picQuad.textureFormat->formatTexture != DXGI_FORMAT_B5G6R5_UNORM )
+ {
+ texture_fmt.i_width = (texture_fmt.i_width + 0x01) & ~0x01;
+ texture_fmt.i_height = (texture_fmt.i_height + 0x01) & ~0x01;
+ }
+
if (!is_d3d11_opaque(fmt->i_chroma))
texture_fmt.i_chroma = sys->picQuad.textureFormat->fourcc;
@@ -1329,8 +1314,6 @@ static int Direct3D11MapSubpicture(vout_display_t *vd, int *subpicture_region_co
free(d3dquad);
continue;
}
- d3dquad->i_width = r->fmt.i_width;
- d3dquad->i_height = r->fmt.i_height;
d3dquad->textureFormat = sys->regionQuad.textureFormat;
err = D3D11_AllocateQuad(vd, sys->d3d_dev, PROJECTION_MODE_RECTANGULAR, d3dquad);
@@ -1395,11 +1378,10 @@ static int Direct3D11MapSubpicture(vout_display_t *vd, int *subpicture_region_co
continue;
}
- RECT output;
- output.left = r->fmt.i_x_offset;
- output.right = r->fmt.i_x_offset + r->fmt.i_visible_width;
- output.top = r->fmt.i_y_offset;
- output.bottom = r->fmt.i_y_offset + r->fmt.i_visible_height;
+ POINT output = {
+ .x = r->fmt.i_visible_width,
+ .y = r->fmt.i_visible_height,
+ };
D3D11_UpdateQuadPosition(vd, sys->d3d_dev, quad, &output, ORIENT_NORMAL);
More information about the vlc-commits
mailing list