vlc | branch: master | Steve Lhomme <[email protected]> | 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); _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
