mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-01 22:21:13 +00:00
d3d11overlaycompositor: Handle premultiplied alpha in pixel shader
Do premultiplied -> straight alpha conversion using GPU Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4825>
This commit is contained in:
parent
15735a4ef3
commit
cb28a16007
1 changed files with 50 additions and 2 deletions
|
@ -57,6 +57,27 @@ static const gchar templ_pixel_shader[] =
|
||||||
" return shaderTexture.Sample(samplerState, input.Texture);\n"
|
" return shaderTexture.Sample(samplerState, input.Texture);\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
|
static const gchar templ_premul_pixel_shader[] =
|
||||||
|
"Texture2D shaderTexture;\n"
|
||||||
|
"SamplerState samplerState;\n"
|
||||||
|
"struct PS_INPUT\n"
|
||||||
|
"{\n"
|
||||||
|
" float4 Position: SV_POSITION;\n"
|
||||||
|
" float2 Texture: TEXCOORD;\n"
|
||||||
|
"};\n"
|
||||||
|
"float4 main(PS_INPUT input): SV_TARGET\n"
|
||||||
|
"{\n"
|
||||||
|
" float4 sample = shaderTexture.Sample(samplerState, input.Texture);\n"
|
||||||
|
" float4 unpremul_sample;\n"
|
||||||
|
" if (sample.a == 0 || sample.a == 1)\n"
|
||||||
|
" return sample;\n"
|
||||||
|
" unpremul_sample.r = saturate (sample.r / sample.a);\n"
|
||||||
|
" unpremul_sample.g = saturate (sample.g / sample.a);\n"
|
||||||
|
" unpremul_sample.b = saturate (sample.b / sample.a);\n"
|
||||||
|
" unpremul_sample.a = sample.a;\n"
|
||||||
|
" return unpremul_sample;\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
static const gchar templ_vertex_shader[] =
|
static const gchar templ_vertex_shader[] =
|
||||||
"struct VS_INPUT\n"
|
"struct VS_INPUT\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
|
@ -83,6 +104,7 @@ struct _GstD3D11OverlayCompositorPrivate
|
||||||
D3D11_VIEWPORT viewport;
|
D3D11_VIEWPORT viewport;
|
||||||
|
|
||||||
ID3D11PixelShader *ps;
|
ID3D11PixelShader *ps;
|
||||||
|
ID3D11PixelShader *premul_ps;
|
||||||
ID3D11VertexShader *vs;
|
ID3D11VertexShader *vs;
|
||||||
ID3D11InputLayout *layout;
|
ID3D11InputLayout *layout;
|
||||||
ID3D11SamplerState *sampler;
|
ID3D11SamplerState *sampler;
|
||||||
|
@ -99,6 +121,7 @@ typedef struct
|
||||||
ID3D11Texture2D *texture;
|
ID3D11Texture2D *texture;
|
||||||
ID3D11ShaderResourceView *srv;
|
ID3D11ShaderResourceView *srv;
|
||||||
ID3D11Buffer *vertex_buffer;
|
ID3D11Buffer *vertex_buffer;
|
||||||
|
gboolean premul_alpha;
|
||||||
} GstD3D11CompositionOverlay;
|
} GstD3D11CompositionOverlay;
|
||||||
|
|
||||||
static void gst_d3d11_overlay_compositor_dispose (GObject * object);
|
static void gst_d3d11_overlay_compositor_dispose (GObject * object);
|
||||||
|
@ -133,6 +156,7 @@ gst_d3d11_overlay_compositor_dispose (GObject * object)
|
||||||
gst_d3d11_overlay_compositor_free_overlays (self);
|
gst_d3d11_overlay_compositor_free_overlays (self);
|
||||||
|
|
||||||
GST_D3D11_CLEAR_COM (priv->ps);
|
GST_D3D11_CLEAR_COM (priv->ps);
|
||||||
|
GST_D3D11_CLEAR_COM (priv->premul_ps);
|
||||||
GST_D3D11_CLEAR_COM (priv->vs);
|
GST_D3D11_CLEAR_COM (priv->vs);
|
||||||
GST_D3D11_CLEAR_COM (priv->layout);
|
GST_D3D11_CLEAR_COM (priv->layout);
|
||||||
GST_D3D11_CLEAR_COM (priv->sampler);
|
GST_D3D11_CLEAR_COM (priv->sampler);
|
||||||
|
@ -172,6 +196,8 @@ gst_d3d11_composition_overlay_new (GstD3D11OverlayCompositor * self,
|
||||||
ComPtr < ID3D11Texture2D > texture;
|
ComPtr < ID3D11Texture2D > texture;
|
||||||
ComPtr < ID3D11ShaderResourceView > srv;
|
ComPtr < ID3D11ShaderResourceView > srv;
|
||||||
ComPtr < ID3D11Buffer > vertex_buffer;
|
ComPtr < ID3D11Buffer > vertex_buffer;
|
||||||
|
GstVideoOverlayFormatFlags flags;
|
||||||
|
gboolean premul_alpha = FALSE;
|
||||||
|
|
||||||
memset (&subresource_data, 0, sizeof (subresource_data));
|
memset (&subresource_data, 0, sizeof (subresource_data));
|
||||||
memset (&texture_desc, 0, sizeof (texture_desc));
|
memset (&texture_desc, 0, sizeof (texture_desc));
|
||||||
|
@ -187,8 +213,16 @@ gst_d3d11_composition_overlay_new (GstD3D11OverlayCompositor * self,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
flags = gst_video_overlay_rectangle_get_flags (overlay_rect);
|
||||||
|
if ((flags & GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA) != 0) {
|
||||||
|
premul_alpha = TRUE;
|
||||||
|
flags = GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA;
|
||||||
|
} else {
|
||||||
|
flags = GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
buf = gst_video_overlay_rectangle_get_pixels_unscaled_argb (overlay_rect,
|
buf = gst_video_overlay_rectangle_get_pixels_unscaled_argb (overlay_rect,
|
||||||
GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
|
flags);
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
GST_ERROR_OBJECT (self, "Failed to get overlay buffer");
|
GST_ERROR_OBJECT (self, "Failed to get overlay buffer");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -314,6 +348,7 @@ gst_d3d11_composition_overlay_new (GstD3D11OverlayCompositor * self,
|
||||||
overlay->texture = texture.Detach ();
|
overlay->texture = texture.Detach ();
|
||||||
overlay->srv = srv.Detach ();
|
overlay->srv = srv.Detach ();
|
||||||
overlay->vertex_buffer = vertex_buffer.Detach ();
|
overlay->vertex_buffer = vertex_buffer.Detach ();
|
||||||
|
overlay->premul_alpha = premul_alpha;
|
||||||
|
|
||||||
return overlay;
|
return overlay;
|
||||||
}
|
}
|
||||||
|
@ -350,6 +385,7 @@ gst_d3d11_overlay_compositor_setup_shader (GstD3D11OverlayCompositor * self)
|
||||||
ID3D11Device *device_handle;
|
ID3D11Device *device_handle;
|
||||||
ID3D11DeviceContext *context_handle;
|
ID3D11DeviceContext *context_handle;
|
||||||
ComPtr < ID3D11PixelShader > ps;
|
ComPtr < ID3D11PixelShader > ps;
|
||||||
|
ComPtr < ID3D11PixelShader > premul_ps;
|
||||||
ComPtr < ID3D11VertexShader > vs;
|
ComPtr < ID3D11VertexShader > vs;
|
||||||
ComPtr < ID3D11InputLayout > layout;
|
ComPtr < ID3D11InputLayout > layout;
|
||||||
ComPtr < ID3D11SamplerState > sampler;
|
ComPtr < ID3D11SamplerState > sampler;
|
||||||
|
@ -387,6 +423,13 @@ gst_d3d11_overlay_compositor_setup_shader (GstD3D11OverlayCompositor * self)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hr = gst_d3d11_create_pixel_shader_simple (device,
|
||||||
|
templ_premul_pixel_shader, "main", &premul_ps);
|
||||||
|
if (!gst_d3d11_result (hr, device)) {
|
||||||
|
GST_ERROR_OBJECT (self, "Couldn't create premul pixel shader");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
input_desc[0].SemanticName = "POSITION";
|
input_desc[0].SemanticName = "POSITION";
|
||||||
input_desc[0].SemanticIndex = 0;
|
input_desc[0].SemanticIndex = 0;
|
||||||
input_desc[0].Format = DXGI_FORMAT_R32G32B32_FLOAT;
|
input_desc[0].Format = DXGI_FORMAT_R32G32B32_FLOAT;
|
||||||
|
@ -464,6 +507,7 @@ gst_d3d11_overlay_compositor_setup_shader (GstD3D11OverlayCompositor * self)
|
||||||
context_handle->Unmap (index_buffer.Get (), 0);
|
context_handle->Unmap (index_buffer.Get (), 0);
|
||||||
|
|
||||||
priv->ps = ps.Detach ();
|
priv->ps = ps.Detach ();
|
||||||
|
priv->premul_ps = premul_ps.Detach ();
|
||||||
priv->vs = vs.Detach ();
|
priv->vs = vs.Detach ();
|
||||||
priv->layout = layout.Detach ();
|
priv->layout = layout.Detach ();
|
||||||
priv->sampler = sampler.Detach ();
|
priv->sampler = sampler.Detach ();
|
||||||
|
@ -653,7 +697,6 @@ gst_d3d11_overlay_compositor_draw_unlocked (GstD3D11OverlayCompositor *
|
||||||
context->IASetIndexBuffer (priv->index_buffer, DXGI_FORMAT_R16_UINT, 0);
|
context->IASetIndexBuffer (priv->index_buffer, DXGI_FORMAT_R16_UINT, 0);
|
||||||
context->PSSetSamplers (0, 1, &priv->sampler);
|
context->PSSetSamplers (0, 1, &priv->sampler);
|
||||||
context->VSSetShader (priv->vs, nullptr, 0);
|
context->VSSetShader (priv->vs, nullptr, 0);
|
||||||
context->PSSetShader (priv->ps, nullptr, 0);
|
|
||||||
context->RSSetViewports (1, &priv->viewport);
|
context->RSSetViewports (1, &priv->viewport);
|
||||||
context->OMSetRenderTargets (1, rtv, nullptr);
|
context->OMSetRenderTargets (1, rtv, nullptr);
|
||||||
context->OMSetBlendState (priv->blend, nullptr, 0xffffffff);
|
context->OMSetBlendState (priv->blend, nullptr, 0xffffffff);
|
||||||
|
@ -662,6 +705,11 @@ gst_d3d11_overlay_compositor_draw_unlocked (GstD3D11OverlayCompositor *
|
||||||
GstD3D11CompositionOverlay *overlay =
|
GstD3D11CompositionOverlay *overlay =
|
||||||
(GstD3D11CompositionOverlay *) iter->data;
|
(GstD3D11CompositionOverlay *) iter->data;
|
||||||
|
|
||||||
|
if (overlay->premul_alpha)
|
||||||
|
context->PSSetShader (priv->premul_ps, nullptr, 0);
|
||||||
|
else
|
||||||
|
context->PSSetShader (priv->ps, nullptr, 0);
|
||||||
|
|
||||||
context->PSSetShaderResources (0, 1, &overlay->srv);
|
context->PSSetShaderResources (0, 1, &overlay->srv);
|
||||||
context->IASetVertexBuffers (0,
|
context->IASetVertexBuffers (0,
|
||||||
1, &overlay->vertex_buffer, &strides, &offsets);
|
1, &overlay->vertex_buffer, &strides, &offsets);
|
||||||
|
|
Loading…
Reference in a new issue