[vlc-devel] [PATCH] direct3d11: handle picture cropping using RSSetViewports()
Steve Lhomme
robux4 at gmail.com
Mon Sep 14 11:23:03 CEST 2015
fixes the cropping of offset_test.ogv
---
modules/video_output/msw/common.h | 1 +
modules/video_output/msw/direct3d11.c | 161 ++++++++++++++++------------------
2 files changed, 78 insertions(+), 84 deletions(-)
diff --git a/modules/video_output/msw/common.h b/modules/video_output/msw/common.h
index 7064dd8..0edf3c5 100644
--- a/modules/video_output/msw/common.h
+++ b/modules/video_output/msw/common.h
@@ -66,6 +66,7 @@ typedef struct
ID3D11ShaderResourceView *d3dresViewY;
ID3D11ShaderResourceView *d3dresViewUV;
ID3D11PixelShader *d3dpixelShader;
+ D3D11_VIEWPORT cropViewport;
} d3d_quad_t;
#endif
diff --git a/modules/video_output/msw/direct3d11.c b/modules/video_output/msw/direct3d11.c
index c4f97e6..ad72b99 100644
--- a/modules/video_output/msw/direct3d11.c
+++ b/modules/video_output/msw/direct3d11.c
@@ -146,7 +146,7 @@ static int AllocQuad(vout_display_t *, const video_format_t *, d3d_quad_t *,
d3d_quad_cfg_t *, ID3D11PixelShader *);
static void ReleaseQuad(d3d_quad_t *);
static void UpdatePicQuadPosition(vout_display_t *);
-static void UpdateQuadPosition(vout_display_t *, const d3d_quad_t *, const RECT *, int w, int h, float o);
+static void UpdateQuadOpacity(vout_display_t *, const d3d_quad_t *, float);
static void Manage(vout_display_t *vd);
@@ -695,16 +695,6 @@ static HRESULT UpdateBackBuffer(vout_display_t *vd)
return hr;
}
- D3D11_VIEWPORT vp;
- vp.Width = (FLOAT)i_width;
- vp.Height = (FLOAT)i_height;
- vp.MinDepth = 0.0f;
- vp.MaxDepth = 1.0f;
- vp.TopLeftX = 0;
- vp.TopLeftY = 0;
-
- ID3D11DeviceContext_RSSetViewports(sys->d3dcontext, 1, &vp);
-
return S_OK;
}
@@ -766,6 +756,7 @@ static void DisplayD3DPicture(vout_display_sys_t *sys, d3d_quad_t *quad)
UINT offset = 0;
/* Render the quad */
+ ID3D11DeviceContext_RSSetViewports(sys->d3dcontext, 1, &quad->cropViewport);
ID3D11DeviceContext_PSSetShader(sys->d3dcontext, quad->d3dpixelShader, NULL, 0);
ID3D11DeviceContext_PSSetShaderResources(sys->d3dcontext, 0, 1, &quad->d3dresViewY);
@@ -1144,23 +1135,24 @@ static void UpdatePicQuadPosition(vout_display_t *vd)
vout_display_sys_t *sys = vd->sys;
int i_width = RECTWidth(sys->rect_dest_clipped);
int i_height = RECTHeight(sys->rect_dest_clipped);
-#if VLC_WINSTORE_APP
- UINT dataSize = sizeof(i_width);
- HRESULT hr = IDXGISwapChain_GetPrivateData(sys->dxgiswapChain, &GUID_SWAPCHAIN_WIDTH, &dataSize, &i_width);
- if (FAILED(hr)) {
- msg_Err(vd, "Can't get swapchain width, size %d. (hr=0x%lX)", hr, dataSize);
- return;
- }
- dataSize = sizeof(i_height);
- hr = IDXGISwapChain_GetPrivateData(sys->dxgiswapChain, &GUID_SWAPCHAIN_HEIGHT, &dataSize, &i_height);
- if (FAILED(hr)) {
- msg_Err(vd, "Can't get swapchain height, size %d. (hr=0x%lX)", hr, dataSize);
- return;
- }
-#endif
- /* Map the subpicture to sys->rect_dest_clipped */
- UpdateQuadPosition(vd, &sys->picQuad, &sys->rect_dest_clipped, i_width, i_height, 1.0f);
+ int i_top = sys->rect_src_clipped.top * i_height;
+ i_top /= vd->source.i_visible_height;
+ i_top -= sys->rect_dest_clipped.top;
+ int i_left = sys->rect_src_clipped.left * i_width;
+ i_left /= vd->source.i_visible_width;
+ i_left -= sys->rect_dest_clipped.left;
+
+ sys->picQuad.cropViewport.Width = (FLOAT) vd->source.i_width * i_width / vd->source.i_visible_width;
+ sys->picQuad.cropViewport.Height = (FLOAT) vd->source.i_height * i_height / vd->source.i_visible_height;
+ sys->picQuad.cropViewport.MinDepth = 0.0f;
+ sys->picQuad.cropViewport.MaxDepth = 1.0f;
+ sys->picQuad.cropViewport.TopLeftX = -i_left;
+ sys->picQuad.cropViewport.TopLeftY = -i_top;
+
+#ifndef NDEBUG
+ msg_Dbg(vd, "picQuad position (%.02f,%.02f) %.02fx%.02f", sys->picQuad.cropViewport.TopLeftX, sys->picQuad.cropViewport.TopLeftY, sys->picQuad.cropViewport.Width, sys->picQuad.cropViewport.Height );
+#endif
}
/* TODO : handle errors better
@@ -1446,6 +1438,7 @@ static int AllocQuad(vout_display_t *vd, const video_format_t *fmt, d3d_quad_t *
d3d_quad_cfg_t *cfg, ID3D11PixelShader *d3dpixelShader)
{
vout_display_sys_t *sys = vd->sys;
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
HRESULT hr;
D3D11_BUFFER_DESC bd;
@@ -1504,6 +1497,53 @@ static int AllocQuad(vout_display_t *vd, const video_format_t *fmt, d3d_quad_t *
quad->d3dpixelShader = d3dpixelShader;
ID3D11PixelShader_AddRef(quad->d3dpixelShader);
+ float right = 1.0f;
+ float left = -1.0f;
+ float top = 1.0f;
+ float bottom = -1.0f;
+
+ hr = ID3D11DeviceContext_Map(sys->d3dcontext, (ID3D11Resource *)quad->pVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ if (SUCCEEDED(hr)) {
+ d3d_vertex_t *dst_data = mappedResource.pData;
+
+ // bottom left
+ dst_data[0].position.x = left;
+ dst_data[0].position.y = bottom;
+ dst_data[0].position.z = 0.0f;
+ dst_data[0].texture.x = 0.0f;
+ dst_data[0].texture.y = 1.0f;
+ dst_data[0].opacity = 1.0f;
+
+ // bottom right
+ dst_data[1].position.x = right;
+ dst_data[1].position.y = bottom;
+ dst_data[1].position.z = 0.0f;
+ dst_data[1].texture.x = 1.0f;
+ dst_data[1].texture.y = 1.0f;
+ dst_data[1].opacity = 1.0f;
+
+ // top right
+ dst_data[2].position.x = right;
+ dst_data[2].position.y = top;
+ dst_data[2].position.z = 0.0f;
+ dst_data[2].texture.x = 1.0f;
+ dst_data[2].texture.y = 0.0f;
+ dst_data[2].opacity = 1.0f;
+
+ // top left
+ dst_data[3].position.x = left;
+ dst_data[3].position.y = top;
+ dst_data[3].position.z = 0.0f;
+ dst_data[3].texture.x = 0.0f;
+ dst_data[3].texture.y = 0.0f;
+ dst_data[3].opacity = 1.0f;
+
+ ID3D11DeviceContext_Unmap(sys->d3dcontext, (ID3D11Resource *)quad->pVertexBuffer, 0);
+ }
+ else {
+ msg_Err(vd, "Failed to lock the subpicture vertex buffer (hr=0x%lX)", hr);
+ }
+
return VLC_SUCCESS;
error:
@@ -1579,51 +1619,18 @@ static void DestroyPictureQuad(picture_t *p_picture)
free( p_picture );
}
-static void UpdateQuadPosition(vout_display_t *vd, const d3d_quad_t *quad, const RECT *dst, int i_width, int i_height, float opacity)
+static void UpdateQuadOpacity(vout_display_t *vd, const d3d_quad_t *quad, float opacity)
{
vout_display_sys_t *sys = vd->sys;
D3D11_MAPPED_SUBRESOURCE mappedResource;
- // adjust with the center at 0,0 and the edges at -1/1
- float left = -1.0f + 2.0f * ((float) dst->left / i_width );
- float right = -1.0f + 2.0f * ((float) dst->right / i_width );
- float top = 1.0f - 2.0f * ((float) dst->top / i_height );
- float bottom = 1.0f - 2.0f * ((float) dst->bottom / i_height );
-
- HRESULT hr = ID3D11DeviceContext_Map(sys->d3dcontext, (ID3D11Resource *)quad->pVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ HRESULT hr = ID3D11DeviceContext_Map(sys->d3dcontext, (ID3D11Resource *)quad->pVertexBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource);
if (SUCCEEDED(hr)) {
d3d_vertex_t *dst_data = mappedResource.pData;
- // bottom left
- dst_data[0].position.x = left;
- dst_data[0].position.y = bottom;
- dst_data[0].position.z = 0.0f;
- dst_data[0].texture.x = 0.0f;
- dst_data[0].texture.y = 1.0f;
dst_data[0].opacity = opacity;
-
- // bottom right
- dst_data[1].position.x = right;
- dst_data[1].position.y = bottom;
- dst_data[1].position.z = 0.0f;
- dst_data[1].texture.x = 1.0f;
- dst_data[1].texture.y = 1.0f;
dst_data[1].opacity = opacity;
-
- // top right
- dst_data[2].position.x = right;
- dst_data[2].position.y = top;
- dst_data[2].position.z = 0.0f;
- dst_data[2].texture.x = 1.0f;
- dst_data[2].texture.y = 0.0f;
dst_data[2].opacity = opacity;
-
- // top left
- dst_data[3].position.x = left;
- dst_data[3].position.y = top;
- dst_data[3].position.z = 0.0f;
- dst_data[3].texture.x = 0.0f;
- dst_data[3].texture.y = 0.0f;
dst_data[3].opacity = opacity;
ID3D11DeviceContext_Unmap(sys->d3dcontext, (ID3D11Resource *)quad->pVertexBuffer, 0);
@@ -1716,30 +1723,16 @@ static int Direct3D11MapSubpicture(vout_display_t *vd, int *subpicture_region_co
continue;
}
+ d3d_quad_t *quad = (d3d_quad_t *) quad_picture->p_sys;
- /* Map the subpicture to sys->rect_dest */
- const int i_original_width = subpicture->i_original_picture_width;
- const int i_original_height = subpicture->i_original_picture_height;
+ quad->cropViewport.Width = (FLOAT) r->fmt.i_visible_width * RECTHeight(sys->rect_dest) / subpicture->i_original_picture_height;
+ quad->cropViewport.Height = (FLOAT) r->fmt.i_visible_height * RECTWidth(sys->rect_dest) / subpicture->i_original_picture_width;
+ quad->cropViewport.MinDepth = 0.0f;
+ quad->cropViewport.MaxDepth = 1.0f;
+ quad->cropViewport.TopLeftX = r->i_x * RECTHeight(sys->rect_dest) / subpicture->i_original_picture_height;
+ quad->cropViewport.TopLeftY = r->i_y * RECTWidth(sys->rect_dest) / subpicture->i_original_picture_width;
- const RECT video = sys->rect_dest;
- const float scale_w = (float)(video.right - video.left) / i_original_width;
- const float scale_h = (float)(video.bottom - video.top) / i_original_height;
-
- RECT dst;
- dst.left = video.left + scale_w * r->i_x,
- dst.right = dst.left + scale_w * r->fmt.i_visible_width,
- dst.top = video.top + scale_h * r->i_y,
- dst.bottom = dst.top + scale_h * r->fmt.i_visible_height;
-
- float opacity = (float)r->i_alpha / 255.0f;
- const RECT *p_viewport;
-#if VLC_WINSTORE_APP
- p_viewport = &sys->rect_display;
-#else
- p_viewport = &video;
-#endif
- UpdateQuadPosition(vd, (d3d_quad_t *)quad_picture->p_sys, &dst,
- RECTWidth( *p_viewport ), RECTHeight( *p_viewport ), opacity );
+ UpdateQuadOpacity(vd, quad, r->i_alpha / 255.0f );
}
return VLC_SUCCESS;
}
--
2.5.0
More information about the vlc-devel
mailing list