1/**************************************************************************
2 *
3 * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian.
4 * Copyright 2014 Advanced Micro Devices, Inc.
5 * All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sub license, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
17 * of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22 * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 *
27 **************************************************************************/
28
29#include "util/u_memory.h"
30#include "util/u_handle_table.h"
31#include "util/u_sampler.h"
32
33#include "va_private.h"
34
35static VAImageFormat subpic_formats[] = {
36   {
37   .fourcc = VA_FOURCC_BGRA,
38   .byte_order = VA_LSB_FIRST,
39   .bits_per_pixel = 32,
40   .depth = 32,
41   .red_mask   = 0x00ff0000ul,
42   .green_mask = 0x0000ff00ul,
43   .blue_mask  = 0x000000fful,
44   .alpha_mask = 0xff000000ul,
45   },
46};
47
48VAStatus
49vlVaQuerySubpictureFormats(VADriverContextP ctx, VAImageFormat *format_list,
50                           unsigned int *flags, unsigned int *num_formats)
51{
52   if (!ctx)
53      return VA_STATUS_ERROR_INVALID_CONTEXT;
54
55   if (!(format_list && flags && num_formats))
56      return VA_STATUS_ERROR_UNKNOWN;
57
58   *num_formats = sizeof(subpic_formats)/sizeof(VAImageFormat);
59   memcpy(format_list, subpic_formats, sizeof(subpic_formats));
60
61   return VA_STATUS_SUCCESS;
62}
63
64VAStatus
65vlVaCreateSubpicture(VADriverContextP ctx, VAImageID image,
66                     VASubpictureID *subpicture)
67{
68   vlVaDriver *drv;
69   vlVaSubpicture *sub;
70   VAImage *img;
71
72   if (!ctx)
73      return VA_STATUS_ERROR_INVALID_CONTEXT;
74
75   drv = VL_VA_DRIVER(ctx);
76   pipe_mutex_lock(drv->mutex);
77   img = handle_table_get(drv->htab, image);
78   if (!img) {
79      pipe_mutex_unlock(drv->mutex);
80      return VA_STATUS_ERROR_INVALID_IMAGE;
81   }
82
83   sub = CALLOC(1, sizeof(*sub));
84   if (!sub) {
85      pipe_mutex_unlock(drv->mutex);
86      return VA_STATUS_ERROR_ALLOCATION_FAILED;
87   }
88
89   sub->image = img;
90   *subpicture = handle_table_add(VL_VA_DRIVER(ctx)->htab, sub);
91   pipe_mutex_unlock(drv->mutex);
92
93   return VA_STATUS_SUCCESS;
94}
95
96VAStatus
97vlVaDestroySubpicture(VADriverContextP ctx, VASubpictureID subpicture)
98{
99   vlVaDriver *drv;
100   vlVaSubpicture *sub;
101
102   if (!ctx)
103      return VA_STATUS_ERROR_INVALID_CONTEXT;
104
105   drv = VL_VA_DRIVER(ctx);
106   pipe_mutex_lock(drv->mutex);
107
108   sub = handle_table_get(drv->htab, subpicture);
109   if (!sub) {
110      pipe_mutex_unlock(drv->mutex);
111      return VA_STATUS_ERROR_INVALID_SUBPICTURE;
112   }
113
114   FREE(sub);
115   handle_table_remove(drv->htab, subpicture);
116   pipe_mutex_unlock(drv->mutex);
117
118   return VA_STATUS_SUCCESS;
119}
120
121VAStatus
122vlVaSubpictureImage(VADriverContextP ctx, VASubpictureID subpicture, VAImageID image)
123{
124   vlVaDriver *drv;
125   vlVaSubpicture *sub;
126   VAImage *img;
127
128   if (!ctx)
129      return VA_STATUS_ERROR_INVALID_CONTEXT;
130
131   drv = VL_VA_DRIVER(ctx);
132   pipe_mutex_lock(drv->mutex);
133
134   img = handle_table_get(drv->htab, image);
135   if (!img) {
136      pipe_mutex_unlock(drv->mutex);
137      return VA_STATUS_ERROR_INVALID_IMAGE;
138   }
139
140   sub = handle_table_get(drv->htab, subpicture);
141   pipe_mutex_unlock(drv->mutex);
142   if (!sub)
143      return VA_STATUS_ERROR_INVALID_SUBPICTURE;
144
145   sub->image = img;
146
147   return VA_STATUS_SUCCESS;
148}
149
150VAStatus
151vlVaSetSubpictureChromakey(VADriverContextP ctx, VASubpictureID subpicture,
152                           unsigned int chromakey_min, unsigned int chromakey_max, unsigned int chromakey_mask)
153{
154   if (!ctx)
155      return VA_STATUS_ERROR_INVALID_CONTEXT;
156
157   return VA_STATUS_ERROR_UNIMPLEMENTED;
158}
159
160VAStatus
161vlVaSetSubpictureGlobalAlpha(VADriverContextP ctx, VASubpictureID subpicture, float global_alpha)
162{
163   if (!ctx)
164      return VA_STATUS_ERROR_INVALID_CONTEXT;
165
166   return VA_STATUS_ERROR_UNIMPLEMENTED;
167}
168
169VAStatus
170vlVaAssociateSubpicture(VADriverContextP ctx, VASubpictureID subpicture,
171                        VASurfaceID *target_surfaces, int num_surfaces,
172                        short src_x, short src_y, unsigned short src_width,
173                        unsigned short src_height, short dest_x, short dest_y,
174                        unsigned short dest_width, unsigned short dest_height,
175                        unsigned int flags)
176{
177   vlVaSubpicture *sub;
178   struct pipe_resource tex_temp, *tex;
179   struct pipe_sampler_view sampler_templ;
180   vlVaDriver *drv;
181   vlVaSurface *surf;
182   int i;
183   struct u_rect src_rect = {src_x, src_x + src_width, src_y, src_y + src_height};
184   struct u_rect dst_rect = {dest_x, dest_x + dest_width, dest_y, dest_y + dest_height};
185
186   if (!ctx)
187      return VA_STATUS_ERROR_INVALID_CONTEXT;
188   drv = VL_VA_DRIVER(ctx);
189   pipe_mutex_lock(drv->mutex);
190
191   sub = handle_table_get(drv->htab, subpicture);
192   if (!sub) {
193      pipe_mutex_unlock(drv->mutex);
194      return VA_STATUS_ERROR_INVALID_SUBPICTURE;
195   }
196
197   for (i = 0; i < num_surfaces; i++) {
198      surf = handle_table_get(drv->htab, target_surfaces[i]);
199      if (!surf) {
200         pipe_mutex_unlock(drv->mutex);
201         return VA_STATUS_ERROR_INVALID_SURFACE;
202      }
203   }
204
205   sub->src_rect = src_rect;
206   sub->dst_rect = dst_rect;
207
208   memset(&tex_temp, 0, sizeof(tex_temp));
209   tex_temp.target = PIPE_TEXTURE_2D;
210   tex_temp.format = PIPE_FORMAT_B8G8R8A8_UNORM;
211   tex_temp.last_level = 0;
212   tex_temp.width0 = src_width;
213   tex_temp.height0 = src_height;
214   tex_temp.depth0 = 1;
215   tex_temp.array_size = 1;
216   tex_temp.usage = PIPE_USAGE_DYNAMIC;
217   tex_temp.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
218   tex_temp.flags = 0;
219   if (!drv->pipe->screen->is_format_supported(
220          drv->pipe->screen, tex_temp.format, tex_temp.target,
221          tex_temp.nr_samples, tex_temp.bind)) {
222      pipe_mutex_unlock(drv->mutex);
223      return VA_STATUS_ERROR_ALLOCATION_FAILED;
224   }
225
226   tex = drv->pipe->screen->resource_create(drv->pipe->screen, &tex_temp);
227
228   memset(&sampler_templ, 0, sizeof(sampler_templ));
229   u_sampler_view_default_template(&sampler_templ, tex, tex->format);
230   sub->sampler = drv->pipe->create_sampler_view(drv->pipe, tex, &sampler_templ);
231   pipe_resource_reference(&tex, NULL);
232   if (!sub->sampler) {
233      pipe_mutex_unlock(drv->mutex);
234      return VA_STATUS_ERROR_ALLOCATION_FAILED;
235   }
236
237   for (i = 0; i < num_surfaces; i++) {
238      surf = handle_table_get(drv->htab, target_surfaces[i]);
239      util_dynarray_append(&surf->subpics, vlVaSubpicture *, sub);
240   }
241   pipe_mutex_unlock(drv->mutex);
242
243   return VA_STATUS_SUCCESS;
244}
245
246VAStatus
247vlVaDeassociateSubpicture(VADriverContextP ctx, VASubpictureID subpicture,
248                          VASurfaceID *target_surfaces, int num_surfaces)
249{
250   int i;
251   int j;
252   vlVaSurface *surf;
253   vlVaSubpicture *sub, **array;
254   vlVaDriver *drv;
255
256   if (!ctx)
257      return VA_STATUS_ERROR_INVALID_CONTEXT;
258   drv = VL_VA_DRIVER(ctx);
259   pipe_mutex_lock(drv->mutex);
260
261   sub = handle_table_get(drv->htab, subpicture);
262   if (!sub) {
263      pipe_mutex_unlock(drv->mutex);
264      return VA_STATUS_ERROR_INVALID_SUBPICTURE;
265   }
266
267   for (i = 0; i < num_surfaces; i++) {
268      surf = handle_table_get(drv->htab, target_surfaces[i]);
269      if (!surf) {
270         pipe_mutex_unlock(drv->mutex);
271         return VA_STATUS_ERROR_INVALID_SURFACE;
272      }
273
274      array = surf->subpics.data;
275      if (!array)
276         continue;
277
278      for (j = 0; j < surf->subpics.size/sizeof(vlVaSubpicture *); j++) {
279         if (array[j] == sub)
280            array[j] = NULL;
281      }
282
283      while (surf->subpics.size && util_dynarray_top(&surf->subpics, vlVaSubpicture *) == NULL)
284         (void)util_dynarray_pop(&surf->subpics, vlVaSubpicture *);
285   }
286   pipe_mutex_unlock(drv->mutex);
287
288   return VA_STATUS_SUCCESS;
289}
290