st/va: Fix leak in VAAPI subpictures
[mesa.git] / src / gallium / state_trackers / va / subpicture.c
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
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
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
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
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
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
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
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.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
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 }