1bf215546Sopenharmony_ci/**************************************************************************
2bf215546Sopenharmony_ci *
3bf215546Sopenharmony_ci * Copyright 2015 Advanced Micro Devices, Inc.
4bf215546Sopenharmony_ci * All Rights Reserved.
5bf215546Sopenharmony_ci *
6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the
8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
12bf215546Sopenharmony_ci * the following conditions:
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the
15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
16bf215546Sopenharmony_ci * of the Software.
17bf215546Sopenharmony_ci *
18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21bf215546Sopenharmony_ci * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25bf215546Sopenharmony_ci *
26bf215546Sopenharmony_ci **************************************************************************/
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci#include "util/u_handle_table.h"
29bf215546Sopenharmony_ci#include "util/u_memory.h"
30bf215546Sopenharmony_ci#include "util/u_compute.h"
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_ci#include "vl/vl_defines.h"
33bf215546Sopenharmony_ci#include "vl/vl_video_buffer.h"
34bf215546Sopenharmony_ci#include "vl/vl_deint_filter.h"
35bf215546Sopenharmony_ci#include "vl/vl_winsys.h"
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_ci#include "va_private.h"
38bf215546Sopenharmony_ci
39bf215546Sopenharmony_cistatic const VARectangle *
40bf215546Sopenharmony_civlVaRegionDefault(const VARectangle *region, vlVaSurface *surf,
41bf215546Sopenharmony_ci		  VARectangle *def)
42bf215546Sopenharmony_ci{
43bf215546Sopenharmony_ci   if (region)
44bf215546Sopenharmony_ci      return region;
45bf215546Sopenharmony_ci
46bf215546Sopenharmony_ci   def->x = 0;
47bf215546Sopenharmony_ci   def->y = 0;
48bf215546Sopenharmony_ci   def->width = surf->templat.width;
49bf215546Sopenharmony_ci   def->height = surf->templat.height;
50bf215546Sopenharmony_ci
51bf215546Sopenharmony_ci   return def;
52bf215546Sopenharmony_ci}
53bf215546Sopenharmony_ci
54bf215546Sopenharmony_cistatic VAStatus
55bf215546Sopenharmony_civlVaPostProcCompositor(vlVaDriver *drv, vlVaContext *context,
56bf215546Sopenharmony_ci                       const VARectangle *src_region,
57bf215546Sopenharmony_ci                       const VARectangle *dst_region,
58bf215546Sopenharmony_ci                       struct pipe_video_buffer *src,
59bf215546Sopenharmony_ci                       struct pipe_video_buffer *dst,
60bf215546Sopenharmony_ci                       enum vl_compositor_deinterlace deinterlace)
61bf215546Sopenharmony_ci{
62bf215546Sopenharmony_ci   struct pipe_surface **surfaces;
63bf215546Sopenharmony_ci   struct u_rect src_rect;
64bf215546Sopenharmony_ci   struct u_rect dst_rect;
65bf215546Sopenharmony_ci
66bf215546Sopenharmony_ci   surfaces = dst->get_surfaces(dst);
67bf215546Sopenharmony_ci   if (!surfaces || !surfaces[0])
68bf215546Sopenharmony_ci      return VA_STATUS_ERROR_INVALID_SURFACE;
69bf215546Sopenharmony_ci
70bf215546Sopenharmony_ci   src_rect.x0 = src_region->x;
71bf215546Sopenharmony_ci   src_rect.y0 = src_region->y;
72bf215546Sopenharmony_ci   src_rect.x1 = src_region->x + src_region->width;
73bf215546Sopenharmony_ci   src_rect.y1 = src_region->y + src_region->height;
74bf215546Sopenharmony_ci
75bf215546Sopenharmony_ci   dst_rect.x0 = dst_region->x;
76bf215546Sopenharmony_ci   dst_rect.y0 = dst_region->y;
77bf215546Sopenharmony_ci   dst_rect.x1 = dst_region->x + dst_region->width;
78bf215546Sopenharmony_ci   dst_rect.y1 = dst_region->y + dst_region->height;
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_ci   vl_compositor_clear_layers(&drv->cstate);
81bf215546Sopenharmony_ci   vl_compositor_set_buffer_layer(&drv->cstate, &drv->compositor, 0, src,
82bf215546Sopenharmony_ci				  &src_rect, NULL, deinterlace);
83bf215546Sopenharmony_ci   vl_compositor_set_layer_dst_area(&drv->cstate, 0, &dst_rect);
84bf215546Sopenharmony_ci   vl_compositor_render(&drv->cstate, &drv->compositor, surfaces[0], NULL, false);
85bf215546Sopenharmony_ci
86bf215546Sopenharmony_ci   drv->pipe->flush(drv->pipe, NULL, 0);
87bf215546Sopenharmony_ci   return VA_STATUS_SUCCESS;
88bf215546Sopenharmony_ci}
89bf215546Sopenharmony_ci
90bf215546Sopenharmony_cistatic void vlVaGetBox(struct pipe_video_buffer *buf, unsigned idx,
91bf215546Sopenharmony_ci                       struct pipe_box *box, const VARectangle *region)
92bf215546Sopenharmony_ci{
93bf215546Sopenharmony_ci   unsigned plane = buf->interlaced ? idx / 2: idx;
94bf215546Sopenharmony_ci   unsigned x, y, width, height;
95bf215546Sopenharmony_ci
96bf215546Sopenharmony_ci   x = abs(region->x);
97bf215546Sopenharmony_ci   y = abs(region->y);
98bf215546Sopenharmony_ci   width = region->width;
99bf215546Sopenharmony_ci   height = region->height;
100bf215546Sopenharmony_ci
101bf215546Sopenharmony_ci   vl_video_buffer_adjust_size(&x, &y, plane,
102bf215546Sopenharmony_ci                               pipe_format_to_chroma_format(buf->buffer_format),
103bf215546Sopenharmony_ci                               buf->interlaced);
104bf215546Sopenharmony_ci   vl_video_buffer_adjust_size(&width, &height, plane,
105bf215546Sopenharmony_ci                               pipe_format_to_chroma_format(buf->buffer_format),
106bf215546Sopenharmony_ci                               buf->interlaced);
107bf215546Sopenharmony_ci
108bf215546Sopenharmony_ci   box->x = region->x < 0 ? -x : x;
109bf215546Sopenharmony_ci   box->y = region->y < 0 ? -y : y;
110bf215546Sopenharmony_ci   box->width = width;
111bf215546Sopenharmony_ci   box->height = height;
112bf215546Sopenharmony_ci}
113bf215546Sopenharmony_ci
114bf215546Sopenharmony_cistatic VAStatus vlVaVidEngineBlit(vlVaDriver *drv, vlVaContext *context,
115bf215546Sopenharmony_ci                                 const VARectangle *src_region,
116bf215546Sopenharmony_ci                                 const VARectangle *dst_region,
117bf215546Sopenharmony_ci                                 struct pipe_video_buffer *src,
118bf215546Sopenharmony_ci                                 struct pipe_video_buffer *dst,
119bf215546Sopenharmony_ci                                 enum vl_compositor_deinterlace deinterlace,
120bf215546Sopenharmony_ci                                 VAProcPipelineParameterBuffer* param)
121bf215546Sopenharmony_ci{
122bf215546Sopenharmony_ci   if (deinterlace != VL_COMPOSITOR_NONE)
123bf215546Sopenharmony_ci      return VA_STATUS_ERROR_UNIMPLEMENTED;
124bf215546Sopenharmony_ci
125bf215546Sopenharmony_ci   if (src->buffer_format != PIPE_FORMAT_NV12 ||
126bf215546Sopenharmony_ci       dst->buffer_format != PIPE_FORMAT_NV12)
127bf215546Sopenharmony_ci      return VA_STATUS_ERROR_UNIMPLEMENTED;
128bf215546Sopenharmony_ci
129bf215546Sopenharmony_ci   struct u_rect src_rect;
130bf215546Sopenharmony_ci   struct u_rect dst_rect;
131bf215546Sopenharmony_ci
132bf215546Sopenharmony_ci   src_rect.x0 = src_region->x;
133bf215546Sopenharmony_ci   src_rect.y0 = src_region->y;
134bf215546Sopenharmony_ci   src_rect.x1 = src_region->x + src_region->width;
135bf215546Sopenharmony_ci   src_rect.y1 = src_region->y + src_region->height;
136bf215546Sopenharmony_ci
137bf215546Sopenharmony_ci   dst_rect.x0 = dst_region->x;
138bf215546Sopenharmony_ci   dst_rect.y0 = dst_region->y;
139bf215546Sopenharmony_ci   dst_rect.x1 = dst_region->x + dst_region->width;
140bf215546Sopenharmony_ci   dst_rect.y1 = dst_region->y + dst_region->height;
141bf215546Sopenharmony_ci
142bf215546Sopenharmony_ci   context->desc.vidproc.base.input_format = src->buffer_format;
143bf215546Sopenharmony_ci   context->desc.vidproc.base.output_format = dst->buffer_format;
144bf215546Sopenharmony_ci
145bf215546Sopenharmony_ci   context->desc.vidproc.src_region = src_rect;
146bf215546Sopenharmony_ci   context->desc.vidproc.dst_region = dst_rect;
147bf215546Sopenharmony_ci
148bf215546Sopenharmony_ci   if (param->rotation_state == VA_ROTATION_NONE)
149bf215546Sopenharmony_ci      context->desc.vidproc.orientation = PIPE_VIDEO_VPP_ORIENTATION_DEFAULT;
150bf215546Sopenharmony_ci   else if (param->rotation_state == VA_ROTATION_90)
151bf215546Sopenharmony_ci      context->desc.vidproc.orientation = PIPE_VIDEO_VPP_ROTATION_90;
152bf215546Sopenharmony_ci   else if (param->rotation_state == VA_ROTATION_180)
153bf215546Sopenharmony_ci      context->desc.vidproc.orientation = PIPE_VIDEO_VPP_ROTATION_180;
154bf215546Sopenharmony_ci   else if (param->rotation_state == VA_ROTATION_270)
155bf215546Sopenharmony_ci      context->desc.vidproc.orientation = PIPE_VIDEO_VPP_ROTATION_270;
156bf215546Sopenharmony_ci
157bf215546Sopenharmony_ci   if (param->mirror_state == VA_MIRROR_HORIZONTAL)
158bf215546Sopenharmony_ci      context->desc.vidproc.orientation |= PIPE_VIDEO_VPP_FLIP_HORIZONTAL;
159bf215546Sopenharmony_ci   if (param->mirror_state == VA_MIRROR_VERTICAL)
160bf215546Sopenharmony_ci      context->desc.vidproc.orientation |= PIPE_VIDEO_VPP_FLIP_VERTICAL;
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_ci   memset(&context->desc.vidproc.blend, 0, sizeof(context->desc.vidproc.blend));
163bf215546Sopenharmony_ci   context->desc.vidproc.blend.mode = PIPE_VIDEO_VPP_BLEND_MODE_NONE;
164bf215546Sopenharmony_ci   if (param->blend_state != NULL) {
165bf215546Sopenharmony_ci      if (param->blend_state->flags & VA_BLEND_GLOBAL_ALPHA) {
166bf215546Sopenharmony_ci         context->desc.vidproc.blend.mode = PIPE_VIDEO_VPP_BLEND_MODE_GLOBAL_ALPHA;
167bf215546Sopenharmony_ci         context->desc.vidproc.blend.global_alpha = param->blend_state->global_alpha;
168bf215546Sopenharmony_ci      }
169bf215546Sopenharmony_ci   }
170bf215546Sopenharmony_ci
171bf215546Sopenharmony_ci   if (context->needs_begin_frame) {
172bf215546Sopenharmony_ci      context->decoder->begin_frame(context->decoder, dst,
173bf215546Sopenharmony_ci                                    &context->desc.base);
174bf215546Sopenharmony_ci      context->needs_begin_frame = false;
175bf215546Sopenharmony_ci   }
176bf215546Sopenharmony_ci   context->decoder->process_frame(context->decoder, src, &context->desc.vidproc);
177bf215546Sopenharmony_ci   context->vpp_needs_flush_on_endpic = true;
178bf215546Sopenharmony_ci
179bf215546Sopenharmony_ci   return VA_STATUS_SUCCESS;
180bf215546Sopenharmony_ci}
181bf215546Sopenharmony_ci
182bf215546Sopenharmony_cistatic VAStatus vlVaPostProcBlit(vlVaDriver *drv, vlVaContext *context,
183bf215546Sopenharmony_ci                                 const VARectangle *src_region,
184bf215546Sopenharmony_ci                                 const VARectangle *dst_region,
185bf215546Sopenharmony_ci                                 struct pipe_video_buffer *src,
186bf215546Sopenharmony_ci                                 struct pipe_video_buffer *dst,
187bf215546Sopenharmony_ci                                 enum vl_compositor_deinterlace deinterlace)
188bf215546Sopenharmony_ci{
189bf215546Sopenharmony_ci   struct pipe_surface **src_surfaces;
190bf215546Sopenharmony_ci   struct pipe_surface **dst_surfaces;
191bf215546Sopenharmony_ci   struct u_rect src_rect;
192bf215546Sopenharmony_ci   struct u_rect dst_rect;
193bf215546Sopenharmony_ci   bool scale = false;
194bf215546Sopenharmony_ci   bool grab = false;
195bf215546Sopenharmony_ci   unsigned i;
196bf215546Sopenharmony_ci
197bf215546Sopenharmony_ci   if ((src->buffer_format == PIPE_FORMAT_B8G8R8X8_UNORM ||
198bf215546Sopenharmony_ci        src->buffer_format == PIPE_FORMAT_B8G8R8A8_UNORM ||
199bf215546Sopenharmony_ci        src->buffer_format == PIPE_FORMAT_R8G8B8X8_UNORM ||
200bf215546Sopenharmony_ci        src->buffer_format == PIPE_FORMAT_R8G8B8A8_UNORM) &&
201bf215546Sopenharmony_ci       !src->interlaced)
202bf215546Sopenharmony_ci      grab = true;
203bf215546Sopenharmony_ci
204bf215546Sopenharmony_ci   if ((src->width != dst->width || src->height != dst->height) &&
205bf215546Sopenharmony_ci       (src->interlaced && dst->interlaced))
206bf215546Sopenharmony_ci      scale = true;
207bf215546Sopenharmony_ci
208bf215546Sopenharmony_ci   src_surfaces = src->get_surfaces(src);
209bf215546Sopenharmony_ci   if (!src_surfaces || !src_surfaces[0])
210bf215546Sopenharmony_ci      return VA_STATUS_ERROR_INVALID_SURFACE;
211bf215546Sopenharmony_ci
212bf215546Sopenharmony_ci   if (scale || (src->interlaced != dst->interlaced && dst->interlaced)) {
213bf215546Sopenharmony_ci      vlVaSurface *surf;
214bf215546Sopenharmony_ci
215bf215546Sopenharmony_ci      surf = handle_table_get(drv->htab, context->target_id);
216bf215546Sopenharmony_ci      surf->templat.interlaced = false;
217bf215546Sopenharmony_ci      dst->destroy(dst);
218bf215546Sopenharmony_ci
219bf215546Sopenharmony_ci      if (vlVaHandleSurfaceAllocate(drv, surf, &surf->templat, NULL, 0) != VA_STATUS_SUCCESS)
220bf215546Sopenharmony_ci         return VA_STATUS_ERROR_ALLOCATION_FAILED;
221bf215546Sopenharmony_ci
222bf215546Sopenharmony_ci      dst = context->target = surf->buffer;
223bf215546Sopenharmony_ci   }
224bf215546Sopenharmony_ci
225bf215546Sopenharmony_ci   dst_surfaces = dst->get_surfaces(dst);
226bf215546Sopenharmony_ci   if (!dst_surfaces || !dst_surfaces[0])
227bf215546Sopenharmony_ci      return VA_STATUS_ERROR_INVALID_SURFACE;
228bf215546Sopenharmony_ci
229bf215546Sopenharmony_ci   src_rect.x0 = src_region->x;
230bf215546Sopenharmony_ci   src_rect.y0 = src_region->y;
231bf215546Sopenharmony_ci   src_rect.x1 = src_region->x + src_region->width;
232bf215546Sopenharmony_ci   src_rect.y1 = src_region->y + src_region->height;
233bf215546Sopenharmony_ci
234bf215546Sopenharmony_ci   dst_rect.x0 = dst_region->x;
235bf215546Sopenharmony_ci   dst_rect.y0 = dst_region->y;
236bf215546Sopenharmony_ci   dst_rect.x1 = dst_region->x + dst_region->width;
237bf215546Sopenharmony_ci   dst_rect.y1 = dst_region->y + dst_region->height;
238bf215546Sopenharmony_ci
239bf215546Sopenharmony_ci   if (grab) {
240bf215546Sopenharmony_ci      vl_compositor_convert_rgb_to_yuv(&drv->cstate, &drv->compositor, 0,
241bf215546Sopenharmony_ci                                       ((struct vl_video_buffer *)src)->resources[0],
242bf215546Sopenharmony_ci                                       dst, &src_rect, &dst_rect);
243bf215546Sopenharmony_ci
244bf215546Sopenharmony_ci      return VA_STATUS_SUCCESS;
245bf215546Sopenharmony_ci   }
246bf215546Sopenharmony_ci
247bf215546Sopenharmony_ci   if (src->interlaced != dst->interlaced) {
248bf215546Sopenharmony_ci      vl_compositor_yuv_deint_full(&drv->cstate, &drv->compositor,
249bf215546Sopenharmony_ci                                   src, dst, &src_rect, &dst_rect,
250bf215546Sopenharmony_ci                                   deinterlace);
251bf215546Sopenharmony_ci
252bf215546Sopenharmony_ci      return VA_STATUS_SUCCESS;
253bf215546Sopenharmony_ci   }
254bf215546Sopenharmony_ci
255bf215546Sopenharmony_ci   for (i = 0; i < VL_MAX_SURFACES; ++i) {
256bf215546Sopenharmony_ci      struct pipe_surface *from = src_surfaces[i];
257bf215546Sopenharmony_ci      struct pipe_blit_info blit;
258bf215546Sopenharmony_ci
259bf215546Sopenharmony_ci      if (src->interlaced) {
260bf215546Sopenharmony_ci         /* Not 100% accurate, but close enough */
261bf215546Sopenharmony_ci         switch (deinterlace) {
262bf215546Sopenharmony_ci         case VL_COMPOSITOR_BOB_TOP:
263bf215546Sopenharmony_ci            from = src_surfaces[i & ~1];
264bf215546Sopenharmony_ci            break;
265bf215546Sopenharmony_ci         case VL_COMPOSITOR_BOB_BOTTOM:
266bf215546Sopenharmony_ci            from = src_surfaces[(i & ~1) + 1];
267bf215546Sopenharmony_ci            break;
268bf215546Sopenharmony_ci         default:
269bf215546Sopenharmony_ci            break;
270bf215546Sopenharmony_ci         }
271bf215546Sopenharmony_ci      }
272bf215546Sopenharmony_ci
273bf215546Sopenharmony_ci      if (!from || !dst_surfaces[i])
274bf215546Sopenharmony_ci         continue;
275bf215546Sopenharmony_ci
276bf215546Sopenharmony_ci      memset(&blit, 0, sizeof(blit));
277bf215546Sopenharmony_ci      blit.src.resource = from->texture;
278bf215546Sopenharmony_ci      blit.src.format = from->format;
279bf215546Sopenharmony_ci      blit.src.level = 0;
280bf215546Sopenharmony_ci      blit.src.box.z = from->u.tex.first_layer;
281bf215546Sopenharmony_ci      blit.src.box.depth = 1;
282bf215546Sopenharmony_ci      vlVaGetBox(src, i, &blit.src.box, src_region);
283bf215546Sopenharmony_ci
284bf215546Sopenharmony_ci      blit.dst.resource = dst_surfaces[i]->texture;
285bf215546Sopenharmony_ci      blit.dst.format = dst_surfaces[i]->format;
286bf215546Sopenharmony_ci      blit.dst.level = 0;
287bf215546Sopenharmony_ci      blit.dst.box.z = dst_surfaces[i]->u.tex.first_layer;
288bf215546Sopenharmony_ci      blit.dst.box.depth = 1;
289bf215546Sopenharmony_ci      vlVaGetBox(dst, i, &blit.dst.box, dst_region);
290bf215546Sopenharmony_ci
291bf215546Sopenharmony_ci      blit.mask = PIPE_MASK_RGBA;
292bf215546Sopenharmony_ci      blit.filter = PIPE_TEX_MIPFILTER_LINEAR;
293bf215546Sopenharmony_ci
294bf215546Sopenharmony_ci      if (drv->pipe->screen->get_param(drv->pipe->screen,
295bf215546Sopenharmony_ci                                       PIPE_CAP_PREFER_COMPUTE_FOR_MULTIMEDIA))
296bf215546Sopenharmony_ci         util_compute_blit(drv->pipe, &blit, &context->blit_cs, !drv->compositor.deinterlace);
297bf215546Sopenharmony_ci      else
298bf215546Sopenharmony_ci         drv->pipe->blit(drv->pipe, &blit);
299bf215546Sopenharmony_ci   }
300bf215546Sopenharmony_ci
301bf215546Sopenharmony_ci   // TODO: figure out why this is necessary for DMA-buf sharing
302bf215546Sopenharmony_ci   drv->pipe->flush(drv->pipe, NULL, 0);
303bf215546Sopenharmony_ci
304bf215546Sopenharmony_ci   return VA_STATUS_SUCCESS;
305bf215546Sopenharmony_ci}
306bf215546Sopenharmony_ci
307bf215546Sopenharmony_cistatic struct pipe_video_buffer *
308bf215546Sopenharmony_civlVaApplyDeint(vlVaDriver *drv, vlVaContext *context,
309bf215546Sopenharmony_ci               VAProcPipelineParameterBuffer *param,
310bf215546Sopenharmony_ci               struct pipe_video_buffer *current,
311bf215546Sopenharmony_ci               unsigned field)
312bf215546Sopenharmony_ci{
313bf215546Sopenharmony_ci   vlVaSurface *prevprev, *prev, *next;
314bf215546Sopenharmony_ci
315bf215546Sopenharmony_ci   if (param->num_forward_references < 2 ||
316bf215546Sopenharmony_ci       param->num_backward_references < 1)
317bf215546Sopenharmony_ci      return current;
318bf215546Sopenharmony_ci
319bf215546Sopenharmony_ci   prevprev = handle_table_get(drv->htab, param->forward_references[1]);
320bf215546Sopenharmony_ci   prev = handle_table_get(drv->htab, param->forward_references[0]);
321bf215546Sopenharmony_ci   next = handle_table_get(drv->htab, param->backward_references[0]);
322bf215546Sopenharmony_ci
323bf215546Sopenharmony_ci   if (!prevprev || !prev || !next)
324bf215546Sopenharmony_ci      return current;
325bf215546Sopenharmony_ci
326bf215546Sopenharmony_ci   if (context->deint && (context->deint->video_width != current->width ||
327bf215546Sopenharmony_ci       context->deint->video_height != current->height)) {
328bf215546Sopenharmony_ci      vl_deint_filter_cleanup(context->deint);
329bf215546Sopenharmony_ci      FREE(context->deint);
330bf215546Sopenharmony_ci      context->deint = NULL;
331bf215546Sopenharmony_ci   }
332bf215546Sopenharmony_ci
333bf215546Sopenharmony_ci   if (!context->deint) {
334bf215546Sopenharmony_ci      context->deint = MALLOC(sizeof(struct vl_deint_filter));
335bf215546Sopenharmony_ci      if (!vl_deint_filter_init(context->deint, drv->pipe, current->width,
336bf215546Sopenharmony_ci                                current->height, false, false)) {
337bf215546Sopenharmony_ci         FREE(context->deint);
338bf215546Sopenharmony_ci         context->deint = NULL;
339bf215546Sopenharmony_ci         return current;
340bf215546Sopenharmony_ci      }
341bf215546Sopenharmony_ci   }
342bf215546Sopenharmony_ci
343bf215546Sopenharmony_ci   if (!vl_deint_filter_check_buffers(context->deint, prevprev->buffer,
344bf215546Sopenharmony_ci                                      prev->buffer, current, next->buffer))
345bf215546Sopenharmony_ci      return current;
346bf215546Sopenharmony_ci
347bf215546Sopenharmony_ci   vl_deint_filter_render(context->deint, prevprev->buffer, prev->buffer,
348bf215546Sopenharmony_ci                          current, next->buffer, field);
349bf215546Sopenharmony_ci   return context->deint->video_buffer;
350bf215546Sopenharmony_ci}
351bf215546Sopenharmony_ci
352bf215546Sopenharmony_ciVAStatus
353bf215546Sopenharmony_civlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf)
354bf215546Sopenharmony_ci{
355bf215546Sopenharmony_ci   enum vl_compositor_deinterlace deinterlace = VL_COMPOSITOR_NONE;
356bf215546Sopenharmony_ci   VARectangle def_src_region, def_dst_region;
357bf215546Sopenharmony_ci   const VARectangle *src_region, *dst_region;
358bf215546Sopenharmony_ci   VAProcPipelineParameterBuffer *param;
359bf215546Sopenharmony_ci   struct pipe_video_buffer *src, *dst;
360bf215546Sopenharmony_ci   vlVaSurface *src_surface, *dst_surface;
361bf215546Sopenharmony_ci   unsigned i;
362bf215546Sopenharmony_ci   struct pipe_screen *pscreen;
363bf215546Sopenharmony_ci
364bf215546Sopenharmony_ci   if (!drv || !context)
365bf215546Sopenharmony_ci      return VA_STATUS_ERROR_INVALID_CONTEXT;
366bf215546Sopenharmony_ci
367bf215546Sopenharmony_ci   if (!buf || !buf->data)
368bf215546Sopenharmony_ci      return VA_STATUS_ERROR_INVALID_BUFFER;
369bf215546Sopenharmony_ci
370bf215546Sopenharmony_ci   if (!context->target)
371bf215546Sopenharmony_ci      return VA_STATUS_ERROR_INVALID_SURFACE;
372bf215546Sopenharmony_ci
373bf215546Sopenharmony_ci   param = buf->data;
374bf215546Sopenharmony_ci
375bf215546Sopenharmony_ci   src_surface = handle_table_get(drv->htab, param->surface);
376bf215546Sopenharmony_ci   dst_surface = handle_table_get(drv->htab, context->target_id);
377bf215546Sopenharmony_ci
378bf215546Sopenharmony_ci   pscreen = drv->vscreen->pscreen;
379bf215546Sopenharmony_ci
380bf215546Sopenharmony_ci   if (src_surface->buffer->buffer_format != dst_surface->buffer->buffer_format &&
381bf215546Sopenharmony_ci       !src_surface->buffer->interlaced &&
382bf215546Sopenharmony_ci       (dst_surface->buffer->buffer_format == PIPE_FORMAT_NV12 ||
383bf215546Sopenharmony_ci        dst_surface->buffer->buffer_format == PIPE_FORMAT_P010 ||
384bf215546Sopenharmony_ci        dst_surface->buffer->buffer_format == PIPE_FORMAT_P016) &&
385bf215546Sopenharmony_ci       pscreen->get_video_param(pscreen,
386bf215546Sopenharmony_ci                                PIPE_VIDEO_PROFILE_UNKNOWN,
387bf215546Sopenharmony_ci                                PIPE_VIDEO_ENTRYPOINT_ENCODE,
388bf215546Sopenharmony_ci                                PIPE_VIDEO_CAP_EFC_SUPPORTED)) {
389bf215546Sopenharmony_ci
390bf215546Sopenharmony_ci      // EFC will convert the buffer to a format the encoder accepts
391bf215546Sopenharmony_ci      dst_surface->encoder_format = dst_surface->buffer->buffer_format;
392bf215546Sopenharmony_ci
393bf215546Sopenharmony_ci      vlVaSurface *surf;
394bf215546Sopenharmony_ci
395bf215546Sopenharmony_ci      surf = handle_table_get(drv->htab, context->target_id);
396bf215546Sopenharmony_ci      surf->templat.interlaced = src_surface->templat.interlaced;
397bf215546Sopenharmony_ci      surf->templat.buffer_format = src_surface->templat.buffer_format;
398bf215546Sopenharmony_ci      surf->buffer->destroy(surf->buffer);
399bf215546Sopenharmony_ci
400bf215546Sopenharmony_ci      if (vlVaHandleSurfaceAllocate(drv, surf, &surf->templat, NULL, 0) != VA_STATUS_SUCCESS)
401bf215546Sopenharmony_ci         return VA_STATUS_ERROR_ALLOCATION_FAILED;
402bf215546Sopenharmony_ci
403bf215546Sopenharmony_ci      pipe_resource_reference(&(((struct vl_video_buffer *)(surf->buffer))->resources[0]), ((struct vl_video_buffer *)(src_surface->buffer))->resources[0]);
404bf215546Sopenharmony_ci      context->target = surf->buffer;
405bf215546Sopenharmony_ci
406bf215546Sopenharmony_ci      return VA_STATUS_SUCCESS;
407bf215546Sopenharmony_ci   }
408bf215546Sopenharmony_ci
409bf215546Sopenharmony_ci   if (!src_surface || !src_surface->buffer)
410bf215546Sopenharmony_ci      return VA_STATUS_ERROR_INVALID_SURFACE;
411bf215546Sopenharmony_ci
412bf215546Sopenharmony_ci   src = src_surface->buffer;
413bf215546Sopenharmony_ci   dst = dst_surface->buffer;
414bf215546Sopenharmony_ci
415bf215546Sopenharmony_ci   /* convert the destination buffer to progressive if we're deinterlacing
416bf215546Sopenharmony_ci      otherwise we might end up deinterlacing twice */
417bf215546Sopenharmony_ci   if (param->num_filters && dst->interlaced) {
418bf215546Sopenharmony_ci      vlVaSurface *surf;
419bf215546Sopenharmony_ci      surf = dst_surface;
420bf215546Sopenharmony_ci      surf->templat.interlaced = false;
421bf215546Sopenharmony_ci      dst->destroy(dst);
422bf215546Sopenharmony_ci
423bf215546Sopenharmony_ci      if (vlVaHandleSurfaceAllocate(drv, surf, &surf->templat, NULL, 0) != VA_STATUS_SUCCESS)
424bf215546Sopenharmony_ci         return VA_STATUS_ERROR_ALLOCATION_FAILED;
425bf215546Sopenharmony_ci
426bf215546Sopenharmony_ci      dst = context->target = surf->buffer;
427bf215546Sopenharmony_ci   }
428bf215546Sopenharmony_ci
429bf215546Sopenharmony_ci   for (i = 0; i < param->num_filters; i++) {
430bf215546Sopenharmony_ci      vlVaBuffer *buf = handle_table_get(drv->htab, param->filters[i]);
431bf215546Sopenharmony_ci      VAProcFilterParameterBufferBase *filter;
432bf215546Sopenharmony_ci
433bf215546Sopenharmony_ci      if (!buf || buf->type != VAProcFilterParameterBufferType)
434bf215546Sopenharmony_ci         return VA_STATUS_ERROR_INVALID_BUFFER;
435bf215546Sopenharmony_ci
436bf215546Sopenharmony_ci      filter = buf->data;
437bf215546Sopenharmony_ci      switch (filter->type) {
438bf215546Sopenharmony_ci      case VAProcFilterDeinterlacing: {
439bf215546Sopenharmony_ci         VAProcFilterParameterBufferDeinterlacing *deint = buf->data;
440bf215546Sopenharmony_ci         switch (deint->algorithm) {
441bf215546Sopenharmony_ci         case VAProcDeinterlacingBob:
442bf215546Sopenharmony_ci            if (deint->flags & VA_DEINTERLACING_BOTTOM_FIELD)
443bf215546Sopenharmony_ci               deinterlace = VL_COMPOSITOR_BOB_BOTTOM;
444bf215546Sopenharmony_ci            else
445bf215546Sopenharmony_ci               deinterlace = VL_COMPOSITOR_BOB_TOP;
446bf215546Sopenharmony_ci            break;
447bf215546Sopenharmony_ci
448bf215546Sopenharmony_ci         case VAProcDeinterlacingWeave:
449bf215546Sopenharmony_ci            deinterlace = VL_COMPOSITOR_WEAVE;
450bf215546Sopenharmony_ci            break;
451bf215546Sopenharmony_ci
452bf215546Sopenharmony_ci         case VAProcDeinterlacingMotionAdaptive:
453bf215546Sopenharmony_ci            src = vlVaApplyDeint(drv, context, param, src,
454bf215546Sopenharmony_ci				 !!(deint->flags & VA_DEINTERLACING_BOTTOM_FIELD));
455bf215546Sopenharmony_ci             deinterlace = VL_COMPOSITOR_MOTION_ADAPTIVE;
456bf215546Sopenharmony_ci            break;
457bf215546Sopenharmony_ci
458bf215546Sopenharmony_ci         default:
459bf215546Sopenharmony_ci            return VA_STATUS_ERROR_UNIMPLEMENTED;
460bf215546Sopenharmony_ci         }
461bf215546Sopenharmony_ci         drv->compositor.deinterlace = deinterlace;
462bf215546Sopenharmony_ci         break;
463bf215546Sopenharmony_ci      }
464bf215546Sopenharmony_ci
465bf215546Sopenharmony_ci      default:
466bf215546Sopenharmony_ci         return VA_STATUS_ERROR_UNIMPLEMENTED;
467bf215546Sopenharmony_ci      }
468bf215546Sopenharmony_ci   }
469bf215546Sopenharmony_ci
470bf215546Sopenharmony_ci   src_region = vlVaRegionDefault(param->surface_region, src_surface, &def_src_region);
471bf215546Sopenharmony_ci   dst_region = vlVaRegionDefault(param->output_region, dst_surface, &def_dst_region);
472bf215546Sopenharmony_ci
473bf215546Sopenharmony_ci   /* If the driver supports video engine post proc, attempt to do that
474bf215546Sopenharmony_ci    * if it fails, fallback to the other existing implementations below
475bf215546Sopenharmony_ci    */
476bf215546Sopenharmony_ci   if (pscreen->get_video_param(pscreen,
477bf215546Sopenharmony_ci                                PIPE_VIDEO_PROFILE_UNKNOWN,
478bf215546Sopenharmony_ci                                PIPE_VIDEO_ENTRYPOINT_PROCESSING,
479bf215546Sopenharmony_ci                                PIPE_VIDEO_CAP_SUPPORTED)) {
480bf215546Sopenharmony_ci      if (!context->decoder) {
481bf215546Sopenharmony_ci         context->decoder = drv->pipe->create_video_codec(drv->pipe, &context->templat);
482bf215546Sopenharmony_ci         if (!context->decoder)
483bf215546Sopenharmony_ci            return VA_STATUS_ERROR_ALLOCATION_FAILED;
484bf215546Sopenharmony_ci      }
485bf215546Sopenharmony_ci
486bf215546Sopenharmony_ci      /* Perform VPBlit, if fail, fallback to other implementations below */
487bf215546Sopenharmony_ci      if (VA_STATUS_SUCCESS == vlVaVidEngineBlit(drv, context, src_region, dst_region,
488bf215546Sopenharmony_ci                                                 src, context->target, deinterlace, param))
489bf215546Sopenharmony_ci         return VA_STATUS_SUCCESS;
490bf215546Sopenharmony_ci   }
491bf215546Sopenharmony_ci
492bf215546Sopenharmony_ci   /* Try other post proc implementations */
493bf215546Sopenharmony_ci   if (context->target->buffer_format != PIPE_FORMAT_NV12 &&
494bf215546Sopenharmony_ci       context->target->buffer_format != PIPE_FORMAT_P010 &&
495bf215546Sopenharmony_ci       context->target->buffer_format != PIPE_FORMAT_P016)
496bf215546Sopenharmony_ci      return vlVaPostProcCompositor(drv, context, src_region, dst_region,
497bf215546Sopenharmony_ci                                    src, context->target, deinterlace);
498bf215546Sopenharmony_ci   else
499bf215546Sopenharmony_ci      return vlVaPostProcBlit(drv, context, src_region, dst_region,
500bf215546Sopenharmony_ci                              src, context->target, deinterlace);
501bf215546Sopenharmony_ci}
502