st/va: add NV12 -> NV12 post processing v2
[mesa.git] / src / gallium / state_trackers / va / postproc.c
1 /**************************************************************************
2 *
3 * Copyright 2015 Advanced Micro Devices, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include "util/u_handle_table.h"
29
30 #include "vl/vl_defines.h"
31 #include "vl/vl_video_buffer.h"
32
33 #include "va_private.h"
34
35 static const VARectangle *
36 vlVaRegionDefault(const VARectangle *region, struct pipe_video_buffer *buf,
37 VARectangle *def)
38 {
39 if (region)
40 return region;
41
42 def->x = 0;
43 def->y = 0;
44 def->width = buf->width;
45 def->height = buf->height;
46
47 return def;
48 }
49
50 static VAStatus
51 vlVaPostProcCompositor(vlVaDriver *drv, vlVaContext *context,
52 const VARectangle *src_region,
53 const VARectangle *dst_region,
54 struct pipe_video_buffer *src,
55 struct pipe_video_buffer *dst)
56 {
57 struct pipe_surface **surfaces;
58 struct u_rect src_rect;
59 struct u_rect dst_rect;
60
61 surfaces = dst->get_surfaces(dst);
62 if (!surfaces || !surfaces[0])
63 return VA_STATUS_ERROR_INVALID_SURFACE;
64
65 src_rect.x0 = src_region->x;
66 src_rect.y0 = src_region->y;
67 src_rect.x1 = src_region->x + src_region->width;
68 src_rect.y1 = src_region->y + src_region->height;
69
70 dst_rect.x0 = dst_region->x;
71 dst_rect.y0 = dst_region->y;
72 dst_rect.x1 = dst_region->x + dst_region->width;
73 dst_rect.y1 = dst_region->y + dst_region->height;
74
75 vl_compositor_clear_layers(&drv->cstate);
76 vl_compositor_set_buffer_layer(&drv->cstate, &drv->compositor, 0, src,
77 &src_rect, NULL, VL_COMPOSITOR_WEAVE);
78 vl_compositor_set_layer_dst_area(&drv->cstate, 0, &dst_rect);
79 vl_compositor_render(&drv->cstate, &drv->compositor, surfaces[0], NULL, false);
80
81 return VA_STATUS_SUCCESS;
82 }
83
84 static void vlVaGetBox(struct pipe_video_buffer *buf, unsigned idx,
85 struct pipe_box *box, const VARectangle *region)
86 {
87 unsigned plane = buf->interlaced ? idx / 2: idx;
88 unsigned x, y, width, height;
89
90 x = abs(region->x);
91 y = abs(region->y);
92 width = region->width;
93 height = region->height;
94
95 vl_video_buffer_adjust_size(&x, &y, plane, buf->chroma_format,
96 buf->interlaced);
97 vl_video_buffer_adjust_size(&width, &height, plane, buf->chroma_format,
98 buf->interlaced);
99
100 box->x = region->x < 0 ? -x : x;
101 box->y = region->y < 0 ? -y : y;
102 box->width = width;
103 box->height = height;
104 }
105
106 static VAStatus vlVaPostProcBlit(vlVaDriver *drv, vlVaContext *context,
107 const VARectangle *src_region,
108 const VARectangle *dst_region,
109 struct pipe_video_buffer *src,
110 struct pipe_video_buffer *dst)
111 {
112 struct pipe_surface **src_surfaces;
113 struct pipe_surface **dst_surfaces;
114 unsigned i;
115
116 if (src->interlaced != dst->interlaced)
117 return VA_STATUS_ERROR_INVALID_SURFACE;
118
119 src_surfaces = src->get_surfaces(src);
120 if (!src_surfaces || !src_surfaces[0])
121 return VA_STATUS_ERROR_INVALID_SURFACE;
122
123 dst_surfaces = dst->get_surfaces(dst);
124 if (!dst_surfaces || !dst_surfaces[0])
125 return VA_STATUS_ERROR_INVALID_SURFACE;
126
127 for (i = 0; i < VL_MAX_SURFACES; ++i) {
128 struct pipe_blit_info blit;
129
130 if (!src_surfaces[i] || !dst_surfaces[i])
131 continue;
132
133 memset(&blit, 0, sizeof(blit));
134 blit.src.resource = src_surfaces[i]->texture;
135 blit.src.format = src_surfaces[i]->format;
136 blit.src.level = 0;
137 blit.src.box.z = src_surfaces[i]->u.tex.first_layer;
138 blit.src.box.depth = 1;
139 vlVaGetBox(src, i, &blit.src.box, src_region);
140
141 blit.dst.resource = dst_surfaces[i]->texture;
142 blit.dst.format = dst_surfaces[i]->format;
143 blit.dst.level = 0;
144 blit.dst.box.z = dst_surfaces[i]->u.tex.first_layer;
145 blit.dst.box.depth = 1;
146 vlVaGetBox(dst, i, &blit.dst.box, dst_region);
147
148 blit.mask = PIPE_MASK_RGBA;
149 blit.filter = PIPE_TEX_MIPFILTER_LINEAR;
150
151 drv->pipe->blit(drv->pipe, &blit);
152 }
153
154 // TODO: figure out why this is necessary for DMA-buf sharing
155 drv->pipe->flush(drv->pipe, NULL, 0);
156
157 return VA_STATUS_SUCCESS;
158 }
159
160 VAStatus
161 vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf)
162 {
163 VARectangle def_src_region, def_dst_region;
164 const VARectangle *src_region, *dst_region;
165 VAProcPipelineParameterBuffer *param;
166 vlVaSurface *src_surface;
167
168 if (!drv || !context)
169 return VA_STATUS_ERROR_INVALID_CONTEXT;
170
171 if (!buf || !buf->data)
172 return VA_STATUS_ERROR_INVALID_BUFFER;
173
174 if (!context->target)
175 return VA_STATUS_ERROR_INVALID_SURFACE;
176
177 param = buf->data;
178
179 src_surface = handle_table_get(drv->htab, param->surface);
180 if (!src_surface || !src_surface->buffer)
181 return VA_STATUS_ERROR_INVALID_SURFACE;
182
183 src_region = vlVaRegionDefault(param->surface_region, src_surface->buffer, &def_src_region);
184 dst_region = vlVaRegionDefault(param->output_region, context->target, &def_dst_region);
185
186 if (context->target->buffer_format != PIPE_FORMAT_NV12)
187 return vlVaPostProcCompositor(drv, context, src_region, dst_region,
188 src_surface->buffer, context->target);
189 else
190 return vlVaPostProcBlit(drv, context, src_region, dst_region,
191 src_surface->buffer, context->target);
192 }