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 
35 static 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 
48 VAStatus
vlVaQuerySubpictureFormats(VADriverContextP ctx,VAImageFormat * format_list,unsigned int * flags,unsigned int * num_formats)49 vlVaQuerySubpictureFormats(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 
64 VAStatus
vlVaCreateSubpicture(VADriverContextP ctx,VAImageID image,VASubpictureID * subpicture)65 vlVaCreateSubpicture(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    mtx_lock(&drv->mutex);
77    img = handle_table_get(drv->htab, image);
78    if (!img) {
79       mtx_unlock(&drv->mutex);
80       return VA_STATUS_ERROR_INVALID_IMAGE;
81    }
82 
83    sub = CALLOC(1, sizeof(*sub));
84    if (!sub) {
85       mtx_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    mtx_unlock(&drv->mutex);
92 
93    return VA_STATUS_SUCCESS;
94 }
95 
96 VAStatus
vlVaDestroySubpicture(VADriverContextP ctx,VASubpictureID subpicture)97 vlVaDestroySubpicture(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    mtx_lock(&drv->mutex);
107 
108    sub = handle_table_get(drv->htab, subpicture);
109    if (!sub) {
110       mtx_unlock(&drv->mutex);
111       return VA_STATUS_ERROR_INVALID_SUBPICTURE;
112    }
113 
114    FREE(sub);
115    handle_table_remove(drv->htab, subpicture);
116    mtx_unlock(&drv->mutex);
117 
118    return VA_STATUS_SUCCESS;
119 }
120 
121 VAStatus
vlVaSubpictureImage(VADriverContextP ctx,VASubpictureID subpicture,VAImageID image)122 vlVaSubpictureImage(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    mtx_lock(&drv->mutex);
133 
134    img = handle_table_get(drv->htab, image);
135    if (!img) {
136       mtx_unlock(&drv->mutex);
137       return VA_STATUS_ERROR_INVALID_IMAGE;
138    }
139 
140    sub = handle_table_get(drv->htab, subpicture);
141    mtx_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 
150 VAStatus
vlVaSetSubpictureChromakey(VADriverContextP ctx,VASubpictureID subpicture,unsigned int chromakey_min,unsigned int chromakey_max,unsigned int chromakey_mask)151 vlVaSetSubpictureChromakey(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 
160 VAStatus
vlVaSetSubpictureGlobalAlpha(VADriverContextP ctx,VASubpictureID subpicture,float global_alpha)161 vlVaSetSubpictureGlobalAlpha(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 
169 VAStatus
vlVaAssociateSubpicture(VADriverContextP ctx,VASubpictureID subpicture,VASurfaceID * target_surfaces,int num_surfaces,short src_x,short src_y,unsigned short src_width,unsigned short src_height,short dest_x,short dest_y,unsigned short dest_width,unsigned short dest_height,unsigned int flags)170 vlVaAssociateSubpicture(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    mtx_lock(&drv->mutex);
190 
191    sub = handle_table_get(drv->htab, subpicture);
192    if (!sub) {
193       mtx_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          mtx_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.nr_storage_samples, tex_temp.bind)) {
222       mtx_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       mtx_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    mtx_unlock(&drv->mutex);
242 
243    return VA_STATUS_SUCCESS;
244 }
245 
246 VAStatus
vlVaDeassociateSubpicture(VADriverContextP ctx,VASubpictureID subpicture,VASurfaceID * target_surfaces,int num_surfaces)247 vlVaDeassociateSubpicture(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    mtx_lock(&drv->mutex);
260 
261    sub = handle_table_get(drv->htab, subpicture);
262    if (!sub) {
263       mtx_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          mtx_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_sampler_view_reference(&sub->sampler,NULL);
287    mtx_unlock(&drv->mutex);
288 
289    return VA_STATUS_SUCCESS;
290 }
291