d3d11overlaycompositor: Fix HLSL compiler warning
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-bad / sys / d3d11 / gstd3d11overlaycompositor.cpp
1 /* GStreamer
2  * Copyright (C) <2019> Seungha Yang <seungha.yang@navercorp.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #  include <config.h>
22 #endif
23
24 #include "gstd3d11overlaycompositor.h"
25 #include "gstd3d11shader.h"
26 #include "gstd3d11pluginutils.h"
27 #include <wrl.h>
28
29 GST_DEBUG_CATEGORY_EXTERN (gst_d3d11_overlay_compositor_debug);
30 #define GST_CAT_DEFAULT gst_d3d11_overlay_compositor_debug
31
32 /* *INDENT-OFF* */
33 using namespace Microsoft::WRL;
34
35 typedef struct
36 {
37   struct {
38     FLOAT x;
39     FLOAT y;
40     FLOAT z;
41   } position;
42   struct {
43     FLOAT u;
44     FLOAT v;
45   } texture;
46 } VertexData;
47
48 static const gchar templ_pixel_shader[] =
49     "Texture2D shaderTexture;\n"
50     "SamplerState samplerState;\n"
51     "struct PS_INPUT\n"
52     "{\n"
53     "  float4 Position: SV_POSITION;\n"
54     "  float2 Texture: TEXCOORD;\n"
55     "};\n"
56     "float4 main(PS_INPUT input): SV_TARGET\n"
57     "{\n"
58     "  return shaderTexture.Sample(samplerState, input.Texture);\n"
59     "}\n";
60
61 static const gchar templ_vertex_shader[] =
62     "struct VS_INPUT\n"
63     "{\n"
64     "  float4 Position : POSITION;\n"
65     "  float2 Texture : TEXCOORD;\n"
66     "};\n"
67     "\n"
68     "struct VS_OUTPUT\n"
69     "{\n"
70     "  float4 Position: SV_POSITION;\n"
71     "  float2 Texture: TEXCOORD;\n"
72     "};\n"
73     "\n"
74     "VS_OUTPUT main(VS_INPUT input)\n"
75     "{\n"
76     "  return input;\n"
77     "}\n";
78 /* *INDENT-ON* */
79
80 struct _GstD3D11OverlayCompositor
81 {
82   GstD3D11Device *device;
83   GstVideoInfo out_info;
84
85   D3D11_VIEWPORT viewport;
86
87   ID3D11PixelShader *ps;
88   ID3D11VertexShader *vs;
89   ID3D11InputLayout *layout;
90   ID3D11SamplerState *sampler;
91   ID3D11BlendState *blend;
92   ID3D11Buffer *index_buffer;
93
94   /* GstD3D11CompositionOverlay */
95   GList *overlays;
96 };
97
98 typedef struct
99 {
100   GstVideoOverlayRectangle *overlay_rect;
101   ID3D11Texture2D *texture;
102   ID3D11ShaderResourceView *srv;
103   ID3D11Buffer *vertex_buffer;
104 } GstD3D11CompositionOverlay;
105
106 static GstD3D11CompositionOverlay *
107 gst_d3d11_composition_overlay_new (GstD3D11OverlayCompositor * self,
108     GstVideoOverlayRectangle * overlay_rect)
109 {
110   GstD3D11CompositionOverlay *overlay = NULL;
111   gint x, y;
112   guint width, height;
113   D3D11_SUBRESOURCE_DATA subresource_data;
114   D3D11_TEXTURE2D_DESC texture_desc;
115   D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc;
116   D3D11_BUFFER_DESC buffer_desc;
117   D3D11_MAPPED_SUBRESOURCE map;
118   VertexData *vertex_data;
119   GstBuffer *buf;
120   GstVideoMeta *vmeta;
121   GstMapInfo info;
122   guint8 *data;
123   gint stride;
124   HRESULT hr;
125   ID3D11Device *device_handle;
126   ID3D11DeviceContext *context_handle;
127   GstD3D11Device *device = self->device;
128   FLOAT x1, y1, x2, y2;
129   gdouble val;
130   ComPtr < ID3D11Texture2D > texture;
131   ComPtr < ID3D11ShaderResourceView > srv;
132   ComPtr < ID3D11Buffer > vertex_buffer;
133
134   g_return_val_if_fail (overlay_rect != NULL, NULL);
135
136   memset (&subresource_data, 0, sizeof (subresource_data));
137   memset (&texture_desc, 0, sizeof (texture_desc));
138   memset (&srv_desc, 0, sizeof (srv_desc));
139   memset (&buffer_desc, 0, sizeof (buffer_desc));
140
141   device_handle = gst_d3d11_device_get_device_handle (device);
142   context_handle = gst_d3d11_device_get_device_context_handle (device);
143
144   if (!gst_video_overlay_rectangle_get_render_rectangle (overlay_rect, &x, &y,
145           &width, &height)) {
146     GST_ERROR ("Failed to get render rectangle");
147     return NULL;
148   }
149
150   buf = gst_video_overlay_rectangle_get_pixels_unscaled_argb (overlay_rect,
151       GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
152   if (!buf) {
153     GST_ERROR ("Failed to get overlay buffer");
154     return NULL;
155   }
156
157   vmeta = gst_buffer_get_video_meta (buf);
158   if (!vmeta) {
159     GST_ERROR ("Failed to get video meta");
160     return NULL;
161   }
162
163   if (!gst_video_meta_map (vmeta,
164           0, &info, (gpointer *) & data, &stride, GST_MAP_READ)) {
165     GST_ERROR ("Failed to map");
166     return NULL;
167   }
168
169   /* Do create texture and upload data at once, for create immutable texture */
170   subresource_data.pSysMem = data;
171   subresource_data.SysMemPitch = stride;
172   subresource_data.SysMemSlicePitch = 0;
173
174   texture_desc.Width = width;
175   texture_desc.Height = height;
176   texture_desc.MipLevels = 1;
177   texture_desc.ArraySize = 1;
178   /* FIXME: need to consider non-BGRA ? */
179   texture_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
180   texture_desc.SampleDesc.Count = 1;
181   texture_desc.SampleDesc.Quality = 0;
182   texture_desc.Usage = D3D11_USAGE_IMMUTABLE;
183   texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
184   texture_desc.CPUAccessFlags = 0;
185
186   hr = device_handle->CreateTexture2D (&texture_desc,
187       &subresource_data, &texture);
188   gst_video_meta_unmap (vmeta, 0, &info);
189
190   if (!gst_d3d11_result (hr, device)) {
191     GST_ERROR ("Failed to create texture");
192     return NULL;
193   }
194
195   srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
196   srv_desc.Texture2D.MipLevels = 1;
197
198   hr = device_handle->CreateShaderResourceView (texture.Get (), &srv_desc,
199       &srv);
200   if (!gst_d3d11_result (hr, device) || !srv) {
201     GST_ERROR ("Failed to create shader resource view");
202     return NULL;
203   }
204
205   buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
206   buffer_desc.ByteWidth = sizeof (VertexData) * 4;
207   buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
208   buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
209
210   hr = device_handle->CreateBuffer (&buffer_desc, NULL, &vertex_buffer);
211   if (!gst_d3d11_result (hr, device)) {
212     GST_ERROR ("Couldn't create vertex buffer, hr: 0x%x", (guint) hr);
213     return NULL;
214   }
215
216   gst_d3d11_device_lock (device);
217   hr = context_handle->Map (vertex_buffer.Get (),
218       0, D3D11_MAP_WRITE_DISCARD, 0, &map);
219
220   if (!gst_d3d11_result (hr, device)) {
221     GST_ERROR ("Couldn't map vertex buffer, hr: 0x%x", (guint) hr);
222     gst_d3d11_device_unlock (device);
223     return NULL;
224   }
225
226   vertex_data = (VertexData *) map.pData;
227   /* bottom left */
228   gst_util_fraction_to_double (x, GST_VIDEO_INFO_WIDTH (&self->out_info), &val);
229   x1 = (val * 2.0f) - 1.0f;
230
231   gst_util_fraction_to_double (y + height,
232       GST_VIDEO_INFO_HEIGHT (&self->out_info), &val);
233   y1 = (val * -2.0f) + 1.0f;
234
235   /* top right */
236   gst_util_fraction_to_double (x + width,
237       GST_VIDEO_INFO_WIDTH (&self->out_info), &val);
238   x2 = (val * 2.0f) - 1.0f;
239
240   gst_util_fraction_to_double (y,
241       GST_VIDEO_INFO_HEIGHT (&self->out_info), &val);
242   y2 = (val * -2.0f) + 1.0f;
243
244   /* bottom left */
245   vertex_data[0].position.x = x1;
246   vertex_data[0].position.y = y1;
247   vertex_data[0].position.z = 0.0f;
248   vertex_data[0].texture.u = 0.0f;
249   vertex_data[0].texture.v = 1.0f;
250
251   /* top left */
252   vertex_data[1].position.x = x1;
253   vertex_data[1].position.y = y2;
254   vertex_data[1].position.z = 0.0f;
255   vertex_data[1].texture.u = 0.0f;
256   vertex_data[1].texture.v = 0.0f;
257
258   /* top right */
259   vertex_data[2].position.x = x2;
260   vertex_data[2].position.y = y2;
261   vertex_data[2].position.z = 0.0f;
262   vertex_data[2].texture.u = 1.0f;
263   vertex_data[2].texture.v = 0.0f;
264
265   /* bottom right */
266   vertex_data[3].position.x = x2;
267   vertex_data[3].position.y = y1;
268   vertex_data[3].position.z = 0.0f;
269   vertex_data[3].texture.u = 1.0f;
270   vertex_data[3].texture.v = 1.0f;
271
272   context_handle->Unmap (vertex_buffer.Get (), 0);
273   gst_d3d11_device_unlock (device);
274
275   overlay = g_new0 (GstD3D11CompositionOverlay, 1);
276   overlay->overlay_rect = gst_video_overlay_rectangle_ref (overlay_rect);
277   overlay->texture = texture.Detach ();
278   overlay->srv = srv.Detach ();
279   overlay->vertex_buffer = vertex_buffer.Detach ();
280
281   return overlay;
282 }
283
284 static void
285 gst_d3d11_composition_overlay_free (GstD3D11CompositionOverlay * overlay)
286 {
287   if (!overlay)
288     return;
289
290   if (overlay->overlay_rect)
291     gst_video_overlay_rectangle_unref (overlay->overlay_rect);
292
293   GST_D3D11_CLEAR_COM (overlay->srv);
294   GST_D3D11_CLEAR_COM (overlay->texture);
295   GST_D3D11_CLEAR_COM (overlay->vertex_buffer);
296
297   g_free (overlay);
298 }
299
300 static gboolean
301 gst_d3d11_overlay_compositor_setup_shader (GstD3D11OverlayCompositor * self,
302     GstD3D11Device * device)
303 {
304   HRESULT hr;
305   D3D11_SAMPLER_DESC sampler_desc;
306   D3D11_INPUT_ELEMENT_DESC input_desc[2];
307   D3D11_BUFFER_DESC buffer_desc;
308   D3D11_BLEND_DESC blend_desc;
309   D3D11_MAPPED_SUBRESOURCE map;
310   WORD *indices;
311   ID3D11Device *device_handle;
312   ID3D11DeviceContext *context_handle;
313   ComPtr < ID3D11PixelShader > ps;
314   ComPtr < ID3D11VertexShader > vs;
315   ComPtr < ID3D11InputLayout > layout;
316   ComPtr < ID3D11SamplerState > sampler;
317   ComPtr < ID3D11BlendState > blend;
318   ComPtr < ID3D11Buffer > index_buffer;
319
320   memset (&sampler_desc, 0, sizeof (sampler_desc));
321   memset (input_desc, 0, sizeof (input_desc));
322   memset (&buffer_desc, 0, sizeof (buffer_desc));
323   memset (&blend_desc, 0, sizeof (blend_desc));
324
325   device_handle = gst_d3d11_device_get_device_handle (device);
326   context_handle = gst_d3d11_device_get_device_context_handle (device);
327
328   /* bilinear filtering */
329   sampler_desc.Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
330   sampler_desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
331   sampler_desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
332   sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
333   sampler_desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
334   sampler_desc.MinLOD = 0;
335   sampler_desc.MaxLOD = D3D11_FLOAT32_MAX;
336
337   hr = device_handle->CreateSamplerState (&sampler_desc, &sampler);
338   if (!gst_d3d11_result (hr, device)) {
339     GST_ERROR ("Couldn't create sampler state, hr: 0x%x", (guint) hr);
340     return FALSE;
341   }
342
343   GST_LOG ("Create Pixel Shader \n%s", templ_pixel_shader);
344
345   if (!gst_d3d11_create_pixel_shader (device, templ_pixel_shader, &ps)) {
346     GST_ERROR ("Couldn't create pixel shader");
347     return FALSE;
348   }
349
350   input_desc[0].SemanticName = "POSITION";
351   input_desc[0].SemanticIndex = 0;
352   input_desc[0].Format = DXGI_FORMAT_R32G32B32_FLOAT;
353   input_desc[0].InputSlot = 0;
354   input_desc[0].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
355   input_desc[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
356   input_desc[0].InstanceDataStepRate = 0;
357
358   input_desc[1].SemanticName = "TEXCOORD";
359   input_desc[1].SemanticIndex = 0;
360   input_desc[1].Format = DXGI_FORMAT_R32G32_FLOAT;
361   input_desc[1].InputSlot = 0;
362   input_desc[1].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
363   input_desc[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
364   input_desc[1].InstanceDataStepRate = 0;
365
366   if (!gst_d3d11_create_vertex_shader (device, templ_vertex_shader,
367           input_desc, G_N_ELEMENTS (input_desc), &vs, &layout)) {
368     GST_ERROR ("Couldn't vertex pixel shader");
369     return FALSE;
370   }
371
372   blend_desc.AlphaToCoverageEnable = FALSE;
373   blend_desc.IndependentBlendEnable = FALSE;
374   blend_desc.RenderTarget[0].BlendEnable = TRUE;
375   blend_desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
376   blend_desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
377   blend_desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
378   blend_desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
379   blend_desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
380   blend_desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
381   blend_desc.RenderTarget[0].RenderTargetWriteMask =
382       D3D11_COLOR_WRITE_ENABLE_ALL;
383
384   hr = device_handle->CreateBlendState (&blend_desc, &blend);
385   if (!gst_d3d11_result (hr, device)) {
386     GST_ERROR ("Couldn't create blend staten, hr: 0x%x", (guint) hr);
387     return FALSE;
388   }
389
390   buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
391   buffer_desc.ByteWidth = sizeof (WORD) * 6;
392   buffer_desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
393   buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
394
395   hr = device_handle->CreateBuffer (&buffer_desc, NULL, &index_buffer);
396   if (!gst_d3d11_result (hr, device)) {
397     GST_ERROR ("Couldn't create index buffer, hr: 0x%x", (guint) hr);
398     return FALSE;
399   }
400
401   gst_d3d11_device_lock (device);
402   hr = context_handle->Map (index_buffer.Get (),
403       0, D3D11_MAP_WRITE_DISCARD, 0, &map);
404
405   if (!gst_d3d11_result (hr, device)) {
406     GST_ERROR ("Couldn't map index buffer, hr: 0x%x", (guint) hr);
407     gst_d3d11_device_unlock (device);
408     return FALSE;
409   }
410
411   indices = (WORD *) map.pData;
412
413   /* clockwise indexing */
414   indices[0] = 0;               /* bottom left */
415   indices[1] = 1;               /* top left */
416   indices[2] = 2;               /* top right */
417
418   indices[3] = 3;               /* bottom right */
419   indices[4] = 0;               /* bottom left  */
420   indices[5] = 2;               /* top right */
421
422   context_handle->Unmap (index_buffer.Get (), 0);
423   gst_d3d11_device_unlock (device);
424
425   self->ps = ps.Detach ();
426   self->vs = vs.Detach ();
427   self->layout = layout.Detach ();
428   self->sampler = sampler.Detach ();
429   self->blend = blend.Detach ();
430   self->index_buffer = index_buffer.Detach ();
431
432   return TRUE;
433 }
434
435 GstD3D11OverlayCompositor *
436 gst_d3d11_overlay_compositor_new (GstD3D11Device * device,
437     GstVideoInfo * out_info)
438 {
439   GstD3D11OverlayCompositor *compositor = NULL;
440
441   g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
442   g_return_val_if_fail (out_info != NULL, NULL);
443
444   compositor = g_new0 (GstD3D11OverlayCompositor, 1);
445
446   if (!gst_d3d11_overlay_compositor_setup_shader (compositor, device)) {
447     gst_d3d11_overlay_compositor_free (compositor);
448     return NULL;
449   }
450
451   compositor->device = (GstD3D11Device *) gst_object_ref (device);
452   compositor->out_info = *out_info;
453
454   compositor->viewport.TopLeftX = 0;
455   compositor->viewport.TopLeftY = 0;
456   compositor->viewport.Width = GST_VIDEO_INFO_WIDTH (out_info);
457   compositor->viewport.Height = GST_VIDEO_INFO_HEIGHT (out_info);
458   compositor->viewport.MinDepth = 0.0f;
459   compositor->viewport.MaxDepth = 1.0f;
460
461   return compositor;
462 }
463
464 void
465 gst_d3d11_overlay_compositor_free (GstD3D11OverlayCompositor * compositor)
466 {
467   g_return_if_fail (compositor != NULL);
468
469   gst_d3d11_overlay_compositor_free_overlays (compositor);
470
471   GST_D3D11_CLEAR_COM (compositor->ps);
472   GST_D3D11_CLEAR_COM (compositor->vs);
473   GST_D3D11_CLEAR_COM (compositor->layout);
474   GST_D3D11_CLEAR_COM (compositor->sampler);
475   GST_D3D11_CLEAR_COM (compositor->blend);
476   GST_D3D11_CLEAR_COM (compositor->index_buffer);
477
478   gst_clear_object (&compositor->device);
479   g_free (compositor);
480 }
481
482 static gint
483 find_in_compositor (const GstD3D11CompositionOverlay * overlay,
484     const GstVideoOverlayRectangle * rect)
485 {
486   return !(overlay->overlay_rect == rect);
487 }
488
489 static gboolean
490 is_in_video_overlay_composition (GstVideoOverlayComposition * voc,
491     GstD3D11CompositionOverlay * overlay)
492 {
493   guint i;
494
495   for (i = 0; i < gst_video_overlay_composition_n_rectangles (voc); i++) {
496     GstVideoOverlayRectangle *rectangle =
497         gst_video_overlay_composition_get_rectangle (voc, i);
498     if (overlay->overlay_rect == rectangle)
499       return TRUE;
500   }
501   return FALSE;
502 }
503
504 gboolean
505 gst_d3d11_overlay_compositor_upload (GstD3D11OverlayCompositor * compositor,
506     GstBuffer * buf)
507 {
508   GstVideoOverlayCompositionMeta *meta;
509   gint i, num_overlays;
510   GList *iter;
511
512   g_return_val_if_fail (compositor != NULL, FALSE);
513   g_return_val_if_fail (GST_IS_BUFFER (buf), FALSE);
514
515   meta = gst_buffer_get_video_overlay_composition_meta (buf);
516
517   if (!meta) {
518     gst_d3d11_overlay_compositor_free_overlays (compositor);
519     return TRUE;
520   }
521
522   num_overlays = gst_video_overlay_composition_n_rectangles (meta->overlay);
523   if (!num_overlays) {
524     gst_d3d11_overlay_compositor_free_overlays (compositor);
525     return TRUE;
526   }
527
528   GST_LOG ("Upload %d overlay rectangles", num_overlays);
529
530   /* Upload new overlay */
531   for (i = 0; i < num_overlays; i++) {
532     GstVideoOverlayRectangle *rectangle =
533         gst_video_overlay_composition_get_rectangle (meta->overlay, i);
534
535     if (!g_list_find_custom (compositor->overlays,
536             rectangle, (GCompareFunc) find_in_compositor)) {
537       GstD3D11CompositionOverlay *overlay = NULL;
538
539       overlay = gst_d3d11_composition_overlay_new (compositor, rectangle);
540
541       if (!overlay)
542         return FALSE;
543
544       compositor->overlays = g_list_append (compositor->overlays, overlay);
545     }
546   }
547
548   /* Remove old overlay */
549   iter = compositor->overlays;
550   while (iter) {
551     GstD3D11CompositionOverlay *overlay =
552         (GstD3D11CompositionOverlay *) iter->data;
553     GList *next = iter->next;
554
555     if (!is_in_video_overlay_composition (meta->overlay, overlay)) {
556       compositor->overlays = g_list_delete_link (compositor->overlays, iter);
557       gst_d3d11_composition_overlay_free (overlay);
558     }
559
560     iter = next;
561   }
562
563   return TRUE;
564 }
565
566 void
567 gst_d3d11_overlay_compositor_free_overlays (GstD3D11OverlayCompositor *
568     compositor)
569 {
570   g_return_if_fail (compositor != NULL);
571
572   if (compositor->overlays) {
573     g_list_free_full (compositor->overlays,
574         (GDestroyNotify) gst_d3d11_composition_overlay_free);
575
576     compositor->overlays = NULL;
577   }
578 }
579
580 gboolean
581 gst_d3d11_overlay_compositor_update_viewport (GstD3D11OverlayCompositor *
582     compositor, D3D11_VIEWPORT * viewport)
583 {
584   g_return_val_if_fail (compositor != NULL, FALSE);
585   g_return_val_if_fail (viewport != NULL, FALSE);
586
587   compositor->viewport = *viewport;
588
589   return TRUE;
590 }
591
592 gboolean
593 gst_d3d11_overlay_compositor_draw (GstD3D11OverlayCompositor * compositor,
594     ID3D11RenderTargetView * rtv[GST_VIDEO_MAX_PLANES])
595 {
596   gboolean ret = TRUE;
597
598   g_return_val_if_fail (compositor != NULL, FALSE);
599   g_return_val_if_fail (rtv != NULL, FALSE);
600
601   gst_d3d11_device_lock (compositor->device);
602   ret = gst_d3d11_overlay_compositor_draw_unlocked (compositor, rtv);
603   gst_d3d11_device_unlock (compositor->device);
604
605   return ret;
606 }
607
608 gboolean
609 gst_d3d11_overlay_compositor_draw_unlocked (GstD3D11OverlayCompositor *
610     compositor, ID3D11RenderTargetView * rtv[GST_VIDEO_MAX_PLANES])
611 {
612   GList *iter;
613   ID3D11DeviceContext *context;
614   ID3D11ShaderResourceView *clear_view[GST_VIDEO_MAX_PLANES] = { nullptr, };
615   UINT strides = sizeof (VertexData);
616   UINT offsets = 0;
617
618   g_return_val_if_fail (compositor != NULL, FALSE);
619   g_return_val_if_fail (rtv != NULL, FALSE);
620
621   context = gst_d3d11_device_get_device_context_handle (compositor->device);
622   context->IASetPrimitiveTopology (D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
623   context->IASetInputLayout (compositor->layout);
624   context->IASetIndexBuffer (compositor->index_buffer, DXGI_FORMAT_R16_UINT, 0);
625   context->PSSetSamplers (0, 1, &compositor->sampler);
626   context->VSSetShader (compositor->vs, nullptr, 0);
627   context->PSSetShader (compositor->ps, nullptr, 0);
628   context->RSSetViewports (1, &compositor->viewport);
629   context->OMSetRenderTargets (1, rtv, nullptr);
630   context->OMSetBlendState (compositor->blend, nullptr, 0xffffffff);
631
632   for (iter = compositor->overlays; iter; iter = g_list_next (iter)) {
633     GstD3D11CompositionOverlay *overlay =
634         (GstD3D11CompositionOverlay *) iter->data;
635
636     context->PSSetShaderResources (0, 1, &overlay->srv);
637     context->IASetVertexBuffers (0,
638         1, &overlay->vertex_buffer, &strides, &offsets);
639
640     context->DrawIndexed (6, 0, 0);
641   }
642
643   context->PSSetShaderResources (0, 1, clear_view);
644   context->OMSetRenderTargets (0, nullptr, nullptr);
645
646   return TRUE;
647 }