1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © Microsoft Corporation
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21bf215546Sopenharmony_ci * IN THE SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#include "d3d12_video_buffer.h"
25bf215546Sopenharmony_ci#include "d3d12_resource.h"
26bf215546Sopenharmony_ci#include "d3d12_video_dec.h"
27bf215546Sopenharmony_ci#include "d3d12_residency.h"
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_ci#include "util/format/u_format.h"
30bf215546Sopenharmony_ci#include "util/u_inlines.h"
31bf215546Sopenharmony_ci#include "util/u_memory.h"
32bf215546Sopenharmony_ci#include "util/u_video.h"
33bf215546Sopenharmony_ci#include "vl/vl_video_buffer.h"
34bf215546Sopenharmony_ci#include "util/u_sampler.h"
35bf215546Sopenharmony_ci
36bf215546Sopenharmony_ci/**
37bf215546Sopenharmony_ci * creates a video buffer
38bf215546Sopenharmony_ci */
39bf215546Sopenharmony_cistruct pipe_video_buffer *
40bf215546Sopenharmony_cid3d12_video_buffer_create(struct pipe_context *pipe, const struct pipe_video_buffer *tmpl)
41bf215546Sopenharmony_ci{
42bf215546Sopenharmony_ci   assert(pipe);
43bf215546Sopenharmony_ci   assert(tmpl);
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_ci   ///
46bf215546Sopenharmony_ci   /// Initialize d3d12_video_buffer
47bf215546Sopenharmony_ci   ///
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_ci
50bf215546Sopenharmony_ci   if (!(tmpl->buffer_format == PIPE_FORMAT_NV12)) {
51bf215546Sopenharmony_ci      debug_printf("[d3d12_video_buffer] buffer_format is only supported as PIPE_FORMAT_NV12.\n");
52bf215546Sopenharmony_ci      return nullptr;
53bf215546Sopenharmony_ci   }
54bf215546Sopenharmony_ci
55bf215546Sopenharmony_ci   if (!(pipe_format_to_chroma_format(tmpl->buffer_format) == PIPE_VIDEO_CHROMA_FORMAT_420)) {
56bf215546Sopenharmony_ci      debug_printf(
57bf215546Sopenharmony_ci         "[d3d12_video_buffer] tmpl->buffer_format only supported as a PIPE_VIDEO_CHROMA_FORMAT_420 format.\n");
58bf215546Sopenharmony_ci      return nullptr;
59bf215546Sopenharmony_ci   }
60bf215546Sopenharmony_ci
61bf215546Sopenharmony_ci   // Not using new doesn't call ctor and the initializations in the class declaration are lost
62bf215546Sopenharmony_ci   struct d3d12_video_buffer *pD3D12VideoBuffer = new d3d12_video_buffer;
63bf215546Sopenharmony_ci
64bf215546Sopenharmony_ci   // Fill base template
65bf215546Sopenharmony_ci   pD3D12VideoBuffer->base               = *tmpl;
66bf215546Sopenharmony_ci   pD3D12VideoBuffer->base.buffer_format = tmpl->buffer_format;
67bf215546Sopenharmony_ci   pD3D12VideoBuffer->base.context       = pipe;
68bf215546Sopenharmony_ci   pD3D12VideoBuffer->base.width         = tmpl->width;
69bf215546Sopenharmony_ci   pD3D12VideoBuffer->base.height        = tmpl->height;
70bf215546Sopenharmony_ci   pD3D12VideoBuffer->base.interlaced    = tmpl->interlaced;
71bf215546Sopenharmony_ci   pD3D12VideoBuffer->base.associated_data = nullptr;
72bf215546Sopenharmony_ci   pD3D12VideoBuffer->base.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET | PIPE_BIND_DISPLAY_TARGET;
73bf215546Sopenharmony_ci
74bf215546Sopenharmony_ci   // Fill vtable
75bf215546Sopenharmony_ci   pD3D12VideoBuffer->base.destroy                     = d3d12_video_buffer_destroy;
76bf215546Sopenharmony_ci   pD3D12VideoBuffer->base.get_sampler_view_planes     = d3d12_video_buffer_get_sampler_view_planes;
77bf215546Sopenharmony_ci   pD3D12VideoBuffer->base.get_sampler_view_components = d3d12_video_buffer_get_sampler_view_components;
78bf215546Sopenharmony_ci   pD3D12VideoBuffer->base.get_surfaces                = d3d12_video_buffer_get_surfaces;
79bf215546Sopenharmony_ci   pD3D12VideoBuffer->base.destroy_associated_data     = d3d12_video_buffer_destroy_associated_data;
80bf215546Sopenharmony_ci
81bf215546Sopenharmony_ci   struct pipe_resource templ;
82bf215546Sopenharmony_ci   memset(&templ, 0, sizeof(templ));
83bf215546Sopenharmony_ci   templ.target     = PIPE_TEXTURE_2D;
84bf215546Sopenharmony_ci   templ.bind       = pD3D12VideoBuffer->base.bind;
85bf215546Sopenharmony_ci   templ.format     = pD3D12VideoBuffer->base.buffer_format;
86bf215546Sopenharmony_ci   // YUV 4:2:0 formats in D3D12 need to have multiple of 2 dimensions
87bf215546Sopenharmony_ci   templ.width0     = align(pD3D12VideoBuffer->base.width, 2);
88bf215546Sopenharmony_ci   templ.height0    = align(pD3D12VideoBuffer->base.height, 2);
89bf215546Sopenharmony_ci   templ.depth0     = 1;
90bf215546Sopenharmony_ci   templ.array_size = 1;
91bf215546Sopenharmony_ci   templ.flags      = 0;
92bf215546Sopenharmony_ci
93bf215546Sopenharmony_ci   // This calls d3d12_create_resource as the function ptr is set in d3d12_screen.resource_create
94bf215546Sopenharmony_ci   pD3D12VideoBuffer->texture = (struct d3d12_resource *) pipe->screen->resource_create(pipe->screen, &templ);
95bf215546Sopenharmony_ci   d3d12_promote_to_permanent_residency((struct d3d12_screen*) pipe->screen, pD3D12VideoBuffer->texture);
96bf215546Sopenharmony_ci
97bf215546Sopenharmony_ci   if (pD3D12VideoBuffer->texture == nullptr) {
98bf215546Sopenharmony_ci      debug_printf("[d3d12_video_buffer] d3d12_video_buffer_create - Call to resource_create() to create "
99bf215546Sopenharmony_ci                      "d3d12_resource failed\n");
100bf215546Sopenharmony_ci      goto failed;
101bf215546Sopenharmony_ci   }
102bf215546Sopenharmony_ci
103bf215546Sopenharmony_ci   pD3D12VideoBuffer->num_planes = util_format_get_num_planes(pD3D12VideoBuffer->texture->overall_format);
104bf215546Sopenharmony_ci   assert(pD3D12VideoBuffer->num_planes == 2);
105bf215546Sopenharmony_ci   return &pD3D12VideoBuffer->base;
106bf215546Sopenharmony_ci
107bf215546Sopenharmony_cifailed:
108bf215546Sopenharmony_ci   d3d12_video_buffer_destroy((struct pipe_video_buffer *) pD3D12VideoBuffer);
109bf215546Sopenharmony_ci
110bf215546Sopenharmony_ci   return nullptr;
111bf215546Sopenharmony_ci}
112bf215546Sopenharmony_ci
113bf215546Sopenharmony_ci/**
114bf215546Sopenharmony_ci * destroy this video buffer
115bf215546Sopenharmony_ci */
116bf215546Sopenharmony_civoid
117bf215546Sopenharmony_cid3d12_video_buffer_destroy(struct pipe_video_buffer *buffer)
118bf215546Sopenharmony_ci{
119bf215546Sopenharmony_ci   struct d3d12_video_buffer *pD3D12VideoBuffer = (struct d3d12_video_buffer *) buffer;
120bf215546Sopenharmony_ci
121bf215546Sopenharmony_ci   // Destroy pD3D12VideoBuffer->texture (if any)
122bf215546Sopenharmony_ci   if (pD3D12VideoBuffer->texture) {
123bf215546Sopenharmony_ci      pipe_resource *pBaseResource = &pD3D12VideoBuffer->texture->base.b;
124bf215546Sopenharmony_ci      pipe_resource_reference(&pBaseResource, NULL);
125bf215546Sopenharmony_ci   }
126bf215546Sopenharmony_ci
127bf215546Sopenharmony_ci   // Destroy associated data (if any)
128bf215546Sopenharmony_ci   if (pD3D12VideoBuffer->base.associated_data != nullptr) {
129bf215546Sopenharmony_ci      d3d12_video_buffer_destroy_associated_data(pD3D12VideoBuffer->base.associated_data);
130bf215546Sopenharmony_ci      // Set to nullptr after cleanup, no dangling pointers
131bf215546Sopenharmony_ci      pD3D12VideoBuffer->base.associated_data = nullptr;
132bf215546Sopenharmony_ci   }
133bf215546Sopenharmony_ci
134bf215546Sopenharmony_ci   // Destroy (if any) codec where the associated data came from
135bf215546Sopenharmony_ci   if (pD3D12VideoBuffer->base.codec != nullptr) {
136bf215546Sopenharmony_ci      d3d12_video_decoder_destroy(pD3D12VideoBuffer->base.codec);
137bf215546Sopenharmony_ci      // Set to nullptr after cleanup, no dangling pointers
138bf215546Sopenharmony_ci      pD3D12VideoBuffer->base.codec = nullptr;
139bf215546Sopenharmony_ci   }
140bf215546Sopenharmony_ci
141bf215546Sopenharmony_ci   for (uint i = 0; i < pD3D12VideoBuffer->surfaces.size(); ++i) {
142bf215546Sopenharmony_ci      if (pD3D12VideoBuffer->surfaces[i] != NULL) {
143bf215546Sopenharmony_ci         pipe_surface_reference(&pD3D12VideoBuffer->surfaces[i], NULL);
144bf215546Sopenharmony_ci      }
145bf215546Sopenharmony_ci   }
146bf215546Sopenharmony_ci
147bf215546Sopenharmony_ci   for (uint i = 0; i < pD3D12VideoBuffer->sampler_view_planes.size(); ++i) {
148bf215546Sopenharmony_ci      if (pD3D12VideoBuffer->sampler_view_planes[i] != NULL) {
149bf215546Sopenharmony_ci         pipe_sampler_view_reference(&pD3D12VideoBuffer->sampler_view_planes[i], NULL);
150bf215546Sopenharmony_ci      }
151bf215546Sopenharmony_ci   }
152bf215546Sopenharmony_ci
153bf215546Sopenharmony_ci   for (uint i = 0; i < pD3D12VideoBuffer->sampler_view_components.size(); ++i) {
154bf215546Sopenharmony_ci      if (pD3D12VideoBuffer->sampler_view_components[i] != NULL) {
155bf215546Sopenharmony_ci         pipe_sampler_view_reference(&pD3D12VideoBuffer->sampler_view_components[i], NULL);
156bf215546Sopenharmony_ci      }
157bf215546Sopenharmony_ci   }
158bf215546Sopenharmony_ci
159bf215546Sopenharmony_ci   delete pD3D12VideoBuffer;
160bf215546Sopenharmony_ci}
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_ci/*
163bf215546Sopenharmony_ci * destroy the associated data
164bf215546Sopenharmony_ci */
165bf215546Sopenharmony_civoid
166bf215546Sopenharmony_cid3d12_video_buffer_destroy_associated_data(void *associated_data)
167bf215546Sopenharmony_ci{ }
168bf215546Sopenharmony_ci
169bf215546Sopenharmony_ci/**
170bf215546Sopenharmony_ci * get an individual surfaces for each plane
171bf215546Sopenharmony_ci */
172bf215546Sopenharmony_cistruct pipe_surface **
173bf215546Sopenharmony_cid3d12_video_buffer_get_surfaces(struct pipe_video_buffer *buffer)
174bf215546Sopenharmony_ci{
175bf215546Sopenharmony_ci   assert(buffer);
176bf215546Sopenharmony_ci   struct d3d12_video_buffer *pD3D12VideoBuffer = (struct d3d12_video_buffer *) buffer;
177bf215546Sopenharmony_ci   struct pipe_context *      pipe              = pD3D12VideoBuffer->base.context;
178bf215546Sopenharmony_ci   struct pipe_surface        surface_template  = {};
179bf215546Sopenharmony_ci
180bf215546Sopenharmony_ci   // Some video frameworks iterate over [0..VL_MAX_SURFACES) and ignore the nullptr entries
181bf215546Sopenharmony_ci   // So we have to null initialize the other surfaces not used from [num_planes..VL_MAX_SURFACES)
182bf215546Sopenharmony_ci   // Like in src/gallium/frontends/va/surface.c
183bf215546Sopenharmony_ci   pD3D12VideoBuffer->surfaces.resize(VL_MAX_SURFACES, nullptr);
184bf215546Sopenharmony_ci
185bf215546Sopenharmony_ci   // pCurPlaneResource refers to the planar resource, not the overall resource.
186bf215546Sopenharmony_ci   // in d3d12_resource this is handled by having a linked list of planes with
187bf215546Sopenharmony_ci   // d3dRes->base.next ptr to next plane resource
188bf215546Sopenharmony_ci   // starting with the plane 0 being the overall resource
189bf215546Sopenharmony_ci   struct pipe_resource *pCurPlaneResource = &pD3D12VideoBuffer->texture->base.b;
190bf215546Sopenharmony_ci
191bf215546Sopenharmony_ci   for (uint PlaneSlice = 0; PlaneSlice < pD3D12VideoBuffer->num_planes; ++PlaneSlice) {
192bf215546Sopenharmony_ci      if (!pD3D12VideoBuffer->surfaces[PlaneSlice]) {
193bf215546Sopenharmony_ci         memset(&surface_template, 0, sizeof(surface_template));
194bf215546Sopenharmony_ci         surface_template.format =
195bf215546Sopenharmony_ci            util_format_get_plane_format(pD3D12VideoBuffer->texture->overall_format, PlaneSlice);
196bf215546Sopenharmony_ci
197bf215546Sopenharmony_ci         pD3D12VideoBuffer->surfaces[PlaneSlice] =
198bf215546Sopenharmony_ci            pipe->create_surface(pipe, pCurPlaneResource, &surface_template);
199bf215546Sopenharmony_ci
200bf215546Sopenharmony_ci         if (!pD3D12VideoBuffer->surfaces[PlaneSlice]) {
201bf215546Sopenharmony_ci            goto error;
202bf215546Sopenharmony_ci         }
203bf215546Sopenharmony_ci      }
204bf215546Sopenharmony_ci      pCurPlaneResource = pCurPlaneResource->next;
205bf215546Sopenharmony_ci   }
206bf215546Sopenharmony_ci
207bf215546Sopenharmony_ci   return pD3D12VideoBuffer->surfaces.data();
208bf215546Sopenharmony_ci
209bf215546Sopenharmony_cierror:
210bf215546Sopenharmony_ci   for (uint PlaneSlice = 0; PlaneSlice < pD3D12VideoBuffer->num_planes; ++PlaneSlice) {
211bf215546Sopenharmony_ci      pipe_surface_reference(&pD3D12VideoBuffer->surfaces[PlaneSlice], NULL);
212bf215546Sopenharmony_ci   }
213bf215546Sopenharmony_ci
214bf215546Sopenharmony_ci   return nullptr;
215bf215546Sopenharmony_ci}
216bf215546Sopenharmony_ci
217bf215546Sopenharmony_ci/**
218bf215546Sopenharmony_ci * get an individual sampler view for each plane
219bf215546Sopenharmony_ci */
220bf215546Sopenharmony_cistruct pipe_sampler_view **
221bf215546Sopenharmony_cid3d12_video_buffer_get_sampler_view_planes(struct pipe_video_buffer *buffer)
222bf215546Sopenharmony_ci{
223bf215546Sopenharmony_ci   assert(buffer);
224bf215546Sopenharmony_ci   struct d3d12_video_buffer *pD3D12VideoBuffer = (struct d3d12_video_buffer *) buffer;
225bf215546Sopenharmony_ci   struct pipe_context *      pipe              = pD3D12VideoBuffer->base.context;
226bf215546Sopenharmony_ci   struct pipe_sampler_view   samplerViewTemplate;
227bf215546Sopenharmony_ci
228bf215546Sopenharmony_ci   // Some video frameworks iterate over [0..VL_MAX_SURFACES) and ignore the nullptr entries
229bf215546Sopenharmony_ci   // So we have to null initialize the other surfaces not used from [num_planes..VL_MAX_SURFACES)
230bf215546Sopenharmony_ci   // Like in src/gallium/frontends/vdpau/surface.c
231bf215546Sopenharmony_ci   pD3D12VideoBuffer->sampler_view_planes.resize(VL_MAX_SURFACES, nullptr);
232bf215546Sopenharmony_ci
233bf215546Sopenharmony_ci   // pCurPlaneResource refers to the planar resource, not the overall resource.
234bf215546Sopenharmony_ci   // in d3d12_resource this is handled by having a linked list of planes with
235bf215546Sopenharmony_ci   // d3dRes->base.next ptr to next plane resource
236bf215546Sopenharmony_ci   // starting with the plane 0 being the overall resource
237bf215546Sopenharmony_ci   struct pipe_resource *pCurPlaneResource = &pD3D12VideoBuffer->texture->base.b;
238bf215546Sopenharmony_ci
239bf215546Sopenharmony_ci   for (uint i = 0; i < pD3D12VideoBuffer->num_planes; ++i) {
240bf215546Sopenharmony_ci      if (!pD3D12VideoBuffer->sampler_view_planes[i]) {
241bf215546Sopenharmony_ci         assert(pCurPlaneResource);   // the d3d12_resource has a linked list with the exact name of number of elements
242bf215546Sopenharmony_ci                                      // as planes
243bf215546Sopenharmony_ci
244bf215546Sopenharmony_ci         memset(&samplerViewTemplate, 0, sizeof(samplerViewTemplate));
245bf215546Sopenharmony_ci         u_sampler_view_default_template(&samplerViewTemplate, pCurPlaneResource, pCurPlaneResource->format);
246bf215546Sopenharmony_ci
247bf215546Sopenharmony_ci         pD3D12VideoBuffer->sampler_view_planes[i] =
248bf215546Sopenharmony_ci            pipe->create_sampler_view(pipe, pCurPlaneResource, &samplerViewTemplate);
249bf215546Sopenharmony_ci
250bf215546Sopenharmony_ci         if (!pD3D12VideoBuffer->sampler_view_planes[i]) {
251bf215546Sopenharmony_ci            goto error;
252bf215546Sopenharmony_ci         }
253bf215546Sopenharmony_ci      }
254bf215546Sopenharmony_ci
255bf215546Sopenharmony_ci      pCurPlaneResource = pCurPlaneResource->next;
256bf215546Sopenharmony_ci   }
257bf215546Sopenharmony_ci
258bf215546Sopenharmony_ci   return pD3D12VideoBuffer->sampler_view_planes.data();
259bf215546Sopenharmony_ci
260bf215546Sopenharmony_cierror:
261bf215546Sopenharmony_ci   for (uint i = 0; i < pD3D12VideoBuffer->num_planes; ++i) {
262bf215546Sopenharmony_ci      pipe_sampler_view_reference(&pD3D12VideoBuffer->sampler_view_planes[i], NULL);
263bf215546Sopenharmony_ci   }
264bf215546Sopenharmony_ci
265bf215546Sopenharmony_ci   return nullptr;
266bf215546Sopenharmony_ci}
267bf215546Sopenharmony_ci
268bf215546Sopenharmony_ci/**
269bf215546Sopenharmony_ci * get an individual sampler view for each component
270bf215546Sopenharmony_ci */
271bf215546Sopenharmony_cistruct pipe_sampler_view **
272bf215546Sopenharmony_cid3d12_video_buffer_get_sampler_view_components(struct pipe_video_buffer *buffer)
273bf215546Sopenharmony_ci{
274bf215546Sopenharmony_ci   assert(buffer);
275bf215546Sopenharmony_ci   struct d3d12_video_buffer *pD3D12VideoBuffer = (struct d3d12_video_buffer *) buffer;
276bf215546Sopenharmony_ci   struct pipe_context *      pipe              = pD3D12VideoBuffer->base.context;
277bf215546Sopenharmony_ci   struct pipe_sampler_view   samplerViewTemplate;
278bf215546Sopenharmony_ci
279bf215546Sopenharmony_ci   // pCurPlaneResource refers to the planar resource, not the overall resource.
280bf215546Sopenharmony_ci   // in d3d12_resource this is handled by having a linked list of planes with
281bf215546Sopenharmony_ci   // d3dRes->base.next ptr to next plane resource
282bf215546Sopenharmony_ci   // starting with the plane 0 being the overall resource
283bf215546Sopenharmony_ci   struct pipe_resource *pCurPlaneResource = &pD3D12VideoBuffer->texture->base.b;
284bf215546Sopenharmony_ci
285bf215546Sopenharmony_ci   // At the end of the loop, "component" will have the total number of items valid in sampler_view_components
286bf215546Sopenharmony_ci   // since component can end up being <= VL_NUM_COMPONENTS, we assume VL_NUM_COMPONENTS first and then resize/adjust to
287bf215546Sopenharmony_ci   // fit the container size pD3D12VideoBuffer->sampler_view_components to the actual components number
288bf215546Sopenharmony_ci   pD3D12VideoBuffer->sampler_view_components.resize(VL_NUM_COMPONENTS, nullptr);
289bf215546Sopenharmony_ci   uint component = 0;
290bf215546Sopenharmony_ci
291bf215546Sopenharmony_ci   for (uint i = 0; i < pD3D12VideoBuffer->num_planes; ++i) {
292bf215546Sopenharmony_ci      // For example num_components would be 1 for the Y plane (R8 in NV12), 2 for the UV plane (R8G8 in NV12)
293bf215546Sopenharmony_ci      unsigned num_components = util_format_get_nr_components(pCurPlaneResource->format);
294bf215546Sopenharmony_ci
295bf215546Sopenharmony_ci      for (uint j = 0; j < num_components; ++j, ++component) {
296bf215546Sopenharmony_ci         assert(component < VL_NUM_COMPONENTS);
297bf215546Sopenharmony_ci
298bf215546Sopenharmony_ci         if (!pD3D12VideoBuffer->sampler_view_components[component]) {
299bf215546Sopenharmony_ci            memset(&samplerViewTemplate, 0, sizeof(samplerViewTemplate));
300bf215546Sopenharmony_ci            u_sampler_view_default_template(&samplerViewTemplate, pCurPlaneResource, pCurPlaneResource->format);
301bf215546Sopenharmony_ci            samplerViewTemplate.swizzle_r = samplerViewTemplate.swizzle_g = samplerViewTemplate.swizzle_b =
302bf215546Sopenharmony_ci               PIPE_SWIZZLE_X + j;
303bf215546Sopenharmony_ci            samplerViewTemplate.swizzle_a = PIPE_SWIZZLE_1;
304bf215546Sopenharmony_ci
305bf215546Sopenharmony_ci            pD3D12VideoBuffer->sampler_view_components[component] =
306bf215546Sopenharmony_ci               pipe->create_sampler_view(pipe, pCurPlaneResource, &samplerViewTemplate);
307bf215546Sopenharmony_ci            if (!pD3D12VideoBuffer->sampler_view_components[component]) {
308bf215546Sopenharmony_ci               goto error;
309bf215546Sopenharmony_ci            }
310bf215546Sopenharmony_ci         }
311bf215546Sopenharmony_ci      }
312bf215546Sopenharmony_ci
313bf215546Sopenharmony_ci      pCurPlaneResource = pCurPlaneResource->next;
314bf215546Sopenharmony_ci   }
315bf215546Sopenharmony_ci
316bf215546Sopenharmony_ci   // Adjust size to fit component <= VL_NUM_COMPONENTS
317bf215546Sopenharmony_ci   pD3D12VideoBuffer->sampler_view_components.resize(component);
318bf215546Sopenharmony_ci
319bf215546Sopenharmony_ci   return pD3D12VideoBuffer->sampler_view_components.data();
320bf215546Sopenharmony_ci
321bf215546Sopenharmony_cierror:
322bf215546Sopenharmony_ci   for (uint i = 0; i < pD3D12VideoBuffer->num_planes; ++i) {
323bf215546Sopenharmony_ci      pipe_sampler_view_reference(&pD3D12VideoBuffer->sampler_view_components[i], NULL);
324bf215546Sopenharmony_ci   }
325bf215546Sopenharmony_ci
326bf215546Sopenharmony_ci   return nullptr;
327bf215546Sopenharmony_ci}
328