1 /*
2 * vdpau_subpic.c - VDPAU backend for VA-API (VA subpictures)
3 *
4 * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include "sysdeps.h"
22 #include "vdpau_subpic.h"
23 #include "vdpau_video.h"
24 #include "vdpau_image.h"
25 #include "vdpau_buffer.h"
26 #include "utils.h"
27
28 #define DEBUG 1
29 #include "debug.h"
30
31
32 // List of supported subpicture formats
33 typedef struct {
34 VdpImageFormatType vdp_format_type;
35 uint32_t vdp_format;
36 VAImageFormat va_format;
37 unsigned int va_flags;
38 } vdpau_subpic_format_map_t;
39
40 static const vdpau_subpic_format_map_t
41 vdpau_subpic_formats_map[VDPAU_MAX_SUBPICTURE_FORMATS + 1] = {
42 { VDP_IMAGE_FORMAT_TYPE_INDEXED, VDP_INDEXED_FORMAT_A4I4,
43 { VA_FOURCC('A','I','4','4'), VA_MSB_FIRST, 8, },
44 0 },
45 { VDP_IMAGE_FORMAT_TYPE_INDEXED, VDP_INDEXED_FORMAT_I4A4,
46 { VA_FOURCC('I','A','4','4'), VA_MSB_FIRST, 8, },
47 0 },
48 { VDP_IMAGE_FORMAT_TYPE_INDEXED, VDP_INDEXED_FORMAT_A8I8,
49 { VA_FOURCC('A','I','8','8'), VA_MSB_FIRST, 16, },
50 0 },
51 { VDP_IMAGE_FORMAT_TYPE_INDEXED, VDP_INDEXED_FORMAT_I8A8,
52 { VA_FOURCC('I','A','8','8'), VA_MSB_FIRST, 16, },
53 0 },
54 #ifdef WORDS_BIGENDIAN
55 { VDP_IMAGE_FORMAT_TYPE_RGBA, VDP_RGBA_FORMAT_B8G8R8A8,
56 { VA_FOURCC('A','R','G','B'), VA_MSB_FIRST, 32,
57 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 },
58 VA_SUBPICTURE_GLOBAL_ALPHA },
59 { VDP_IMAGE_FORMAT_TYPE_RGBA, VDP_RGBA_FORMAT_R8G8B8A8,
60 { VA_FOURCC('A','B','G','R'), VA_MSB_FIRST, 32,
61 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 },
62 VA_SUBPICTURE_GLOBAL_ALPHA },
63 #else
64 { VDP_IMAGE_FORMAT_TYPE_RGBA, VDP_RGBA_FORMAT_B8G8R8A8,
65 { VA_FOURCC('B','G','R','A'), VA_LSB_FIRST, 32,
66 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 },
67 VA_SUBPICTURE_GLOBAL_ALPHA },
68 { VDP_IMAGE_FORMAT_TYPE_RGBA, VDP_RGBA_FORMAT_R8G8B8A8,
69 { VA_FOURCC('R','G','B','A'), VA_LSB_FIRST, 32,
70 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 },
71 VA_SUBPICTURE_GLOBAL_ALPHA },
72 #endif
73 { 0, VDP_INVALID_HANDLE, }
74 };
75
76 // Returns a suitable VDPAU subpicture format for the specified VA image format
get_format(const VAImageFormat * format)77 static const vdpau_subpic_format_map_t *get_format(const VAImageFormat *format)
78 {
79 unsigned int i;
80 for (i = 0; vdpau_subpic_formats_map[i].va_format.fourcc != 0; i++) {
81 const vdpau_subpic_format_map_t * const m = &vdpau_subpic_formats_map[i];
82 if (m->va_format.fourcc == format->fourcc &&
83 (m->vdp_format_type == VDP_IMAGE_FORMAT_TYPE_RGBA ?
84 (m->va_format.byte_order == format->byte_order &&
85 m->va_format.red_mask == format->red_mask &&
86 m->va_format.green_mask == format->green_mask &&
87 m->va_format.blue_mask == format->blue_mask &&
88 m->va_format.alpha_mask == format->alpha_mask) : 1))
89 return m;
90 }
91 return NULL;
92 }
93
94 // Checks whether the VDPAU implementation supports the specified image format
95 static inline VdpBool
is_supported_format(vdpau_driver_data_t * driver_data,const vdpau_subpic_format_map_t * format)96 is_supported_format(
97 vdpau_driver_data_t *driver_data,
98 const vdpau_subpic_format_map_t *format)
99 {
100 VdpBool is_supported = VDP_FALSE;
101 VdpStatus vdp_status;
102 uint32_t max_width, max_height;
103
104 switch (format->vdp_format_type) {
105 case VDP_IMAGE_FORMAT_TYPE_RGBA:
106 vdp_status = vdpau_bitmap_surface_query_capabilities(
107 driver_data,
108 driver_data->vdp_device,
109 format->vdp_format,
110 &is_supported,
111 &max_width,
112 &max_height
113 );
114 break;
115 case VDP_IMAGE_FORMAT_TYPE_INDEXED:
116 vdp_status = vdpau_output_surface_query_put_bits_indexed_capabilities(
117 driver_data,
118 driver_data->vdp_device,
119 VDP_RGBA_FORMAT_B8G8R8A8,
120 format->vdp_format,
121 VDP_COLOR_TABLE_FORMAT_B8G8R8X8,
122 &is_supported
123 );
124 break;
125 default:
126 vdp_status = VDP_STATUS_ERROR;
127 break;
128 }
129 return vdp_status == VDP_STATUS_OK && is_supported;
130 }
131
132 // Append association to the subpicture
133 static int
subpicture_add_association(object_subpicture_p obj_subpicture,SubpictureAssociationP assoc)134 subpicture_add_association(
135 object_subpicture_p obj_subpicture,
136 SubpictureAssociationP assoc
137 )
138 {
139 SubpictureAssociationP *assocs;
140 assocs = realloc_buffer(
141 (void **)&obj_subpicture->assocs,
142 &obj_subpicture->assocs_count_max,
143 1 + obj_subpicture->assocs_count,
144 sizeof(obj_subpicture->assocs[0])
145 );
146 if (!assocs)
147 return -1;
148
149 assocs[obj_subpicture->assocs_count++] = assoc;
150 return 0;
151 }
152
153 // Remove association at the specified index from the subpicture
154 static inline int
subpicture_remove_association_at(object_subpicture_p obj_subpicture,int index)155 subpicture_remove_association_at(object_subpicture_p obj_subpicture, int index)
156 {
157 ASSERT(obj_subpicture->assocs && obj_subpicture->assocs_count > 0);
158 if (!obj_subpicture->assocs || obj_subpicture->assocs_count == 0)
159 return -1;
160
161 /* Replace with the last association */
162 const unsigned int last = obj_subpicture->assocs_count - 1;
163 obj_subpicture->assocs[index] = obj_subpicture->assocs[last];
164 obj_subpicture->assocs[last] = NULL;
165 obj_subpicture->assocs_count--;
166 return 0;
167 }
168
169 #if 0
170 // Remove association from the subpicture
171 static int
172 subpicture_remove_association(
173 object_subpicture_p obj_subpicture,
174 SubpictureAssociationP assoc
175 )
176 {
177 ASSERT(obj_subpicture->assocs && obj_subpicture->assocs_count > 0);
178 if (!obj_subpicture->assocs || obj_subpicture->assocs_count == 0)
179 return -1;
180
181 unsigned int i;
182 for (i = 0; i < obj_subpicture->assocs_count; i++) {
183 if (obj_subpicture->assocs[i] == assoc)
184 return subpicture_remove_association_at(obj_subpicture, i);
185 }
186 return -1;
187 }
188 #endif
189
190 // Associate one surface to the subpicture
191 VAStatus
subpicture_associate_1(object_subpicture_p obj_subpicture,object_surface_p obj_surface,const VARectangle * src_rect,const VARectangle * dst_rect,unsigned int flags)192 subpicture_associate_1(
193 object_subpicture_p obj_subpicture,
194 object_surface_p obj_surface,
195 const VARectangle *src_rect,
196 const VARectangle *dst_rect,
197 unsigned int flags
198 )
199 {
200 /* we only support the VA_SUBPICTURE_GLOBAL_ALPHA flag */
201 if (flags & ~VA_SUBPICTURE_GLOBAL_ALPHA)
202 return VA_STATUS_ERROR_FLAG_NOT_SUPPORTED;
203
204 SubpictureAssociationP assoc = malloc(sizeof(*assoc));
205 if (!assoc)
206 return VA_STATUS_ERROR_ALLOCATION_FAILED;
207
208 assoc->subpicture = obj_subpicture->base.id;
209 assoc->surface = obj_surface->base.id;
210 assoc->src_rect = *src_rect;
211 assoc->dst_rect = *dst_rect;
212 assoc->flags = flags;
213
214 VAStatus status = surface_add_association(obj_surface, assoc);
215 if (status != VA_STATUS_SUCCESS) {
216 free(assoc);
217 return status;
218 }
219
220 if (subpicture_add_association(obj_subpicture, assoc) < 0) {
221 surface_remove_association(obj_surface, assoc);
222 free(assoc);
223 return VA_STATUS_ERROR_ALLOCATION_FAILED;
224 }
225 return VA_STATUS_SUCCESS;
226 }
227
228 // Associate surfaces to the subpicture
229 static VAStatus
associate_subpicture(vdpau_driver_data_t * driver_data,object_subpicture_p obj_subpicture,VASurfaceID * surfaces,unsigned int num_surfaces,const VARectangle * src_rect,const VARectangle * dst_rect,unsigned int flags)230 associate_subpicture(
231 vdpau_driver_data_t *driver_data,
232 object_subpicture_p obj_subpicture,
233 VASurfaceID *surfaces,
234 unsigned int num_surfaces,
235 const VARectangle *src_rect,
236 const VARectangle *dst_rect,
237 unsigned int flags
238 )
239 {
240 VAStatus status;
241 unsigned int i;
242
243 for (i = 0; i < num_surfaces; i++) {
244 object_surface_p const obj_surface = VDPAU_SURFACE(surfaces[i]);
245 if (!obj_surface)
246 return VA_STATUS_ERROR_INVALID_SURFACE;
247 status = subpicture_associate_1(obj_subpicture, obj_surface,
248 src_rect, dst_rect, flags);
249 if (status != VA_STATUS_SUCCESS)
250 return status;
251 }
252 return VA_STATUS_SUCCESS;
253 }
254
255 // Deassociate one surface from the subpicture
256 VAStatus
subpicture_deassociate_1(object_subpicture_p obj_subpicture,object_surface_p obj_surface)257 subpicture_deassociate_1(
258 object_subpicture_p obj_subpicture,
259 object_surface_p obj_surface
260 )
261 {
262 ASSERT(obj_subpicture->assocs && obj_subpicture->assocs_count > 0);
263 if (!obj_subpicture->assocs || obj_subpicture->assocs_count == 0)
264 return VA_STATUS_ERROR_OPERATION_FAILED;
265
266 unsigned int i;
267 for (i = 0; i < obj_subpicture->assocs_count; i++) {
268 SubpictureAssociationP const assoc = obj_subpicture->assocs[i];
269 ASSERT(assoc);
270 if (assoc && assoc->surface == obj_surface->base.id) {
271 surface_remove_association(obj_surface, assoc);
272 subpicture_remove_association_at(obj_subpicture, i);
273 free(assoc);
274 return VA_STATUS_SUCCESS;
275 }
276 }
277 return VA_STATUS_ERROR_OPERATION_FAILED;
278 }
279
280 // Deassociate surfaces from the subpicture
281 static VAStatus
deassociate_subpicture(vdpau_driver_data_t * driver_data,object_subpicture_p obj_subpicture,VASurfaceID * surfaces,unsigned int num_surfaces)282 deassociate_subpicture(
283 vdpau_driver_data_t *driver_data,
284 object_subpicture_p obj_subpicture,
285 VASurfaceID *surfaces,
286 unsigned int num_surfaces
287 )
288 {
289 VAStatus status, error = VA_STATUS_SUCCESS;
290 unsigned int i;
291
292 for (i = 0; i < num_surfaces; i++) {
293 object_surface_p const obj_surface = VDPAU_SURFACE(surfaces[i]);
294 if (!obj_surface)
295 return VA_STATUS_ERROR_INVALID_SURFACE;
296 status = subpicture_deassociate_1(obj_subpicture, obj_surface);
297 if (status != VA_STATUS_SUCCESS) {
298 /* Simply report the first error to the user */
299 if (error == VA_STATUS_SUCCESS)
300 error = status;
301 }
302 }
303 return error;
304 }
305
306 // Commit subpicture to VDPAU surface
307 VAStatus
commit_subpicture(vdpau_driver_data_p driver_data,object_subpicture_p obj_subpicture)308 commit_subpicture(
309 vdpau_driver_data_p driver_data,
310 object_subpicture_p obj_subpicture
311 )
312 {
313 object_image_p obj_image = VDPAU_IMAGE(obj_subpicture->image_id);
314 if (!obj_image)
315 return VA_STATUS_ERROR_INVALID_IMAGE;
316
317 ASSERT(obj_subpicture->width == obj_image->image.width);
318 if (obj_subpicture->width != obj_image->image.width)
319 return VA_STATUS_ERROR_OPERATION_FAILED;
320
321 ASSERT(obj_subpicture->height == obj_image->image.height);
322 if (obj_subpicture->height != obj_image->image.height)
323 return VA_STATUS_ERROR_OPERATION_FAILED;
324
325 object_buffer_p obj_buffer = VDPAU_BUFFER(obj_image->image.buf);
326 if (!obj_buffer)
327 return VA_STATUS_ERROR_INVALID_BUFFER;
328
329 /* Update video surface only if the image (hence its buffer) was
330 updated since our last synchronisation.
331
332 NOTE: this assumes the user really unmaps the buffer when he is
333 done with it, as it is actually required */
334 if (obj_subpicture->last_commit >= obj_buffer->mtime)
335 return VA_STATUS_SUCCESS;
336
337 VdpRect dirty_rect;
338 dirty_rect.x0 = obj_subpicture->width;
339 dirty_rect.y0 = obj_subpicture->height;
340 dirty_rect.x1 = 0;
341 dirty_rect.y1 = 0;
342
343 unsigned int i;
344 for (i = 0; i < obj_subpicture->assocs_count; i++) {
345 const VARectangle * const rect = &obj_subpicture->assocs[i]->src_rect;
346 dirty_rect.x0 = MIN(dirty_rect.x0, rect->x);
347 dirty_rect.y0 = MIN(dirty_rect.y0, rect->y);
348 dirty_rect.x1 = MAX(dirty_rect.x1, rect->x + rect->width);
349 dirty_rect.y1 = MAX(dirty_rect.y1, rect->y + rect->height);
350 }
351
352 const uint8_t *src;
353 uint32_t src_stride;
354 src_stride = obj_image->image.pitches[0];
355 src = ((uint8_t *)obj_buffer->buffer_data + obj_image->image.offsets[0] +
356 dirty_rect.y0 * obj_image->image.pitches[0] +
357 dirty_rect.x0 * ((obj_image->image.format.bits_per_pixel + 7) / 8));
358
359 VdpStatus vdp_status;
360 switch (obj_subpicture->vdp_format_type) {
361 case VDP_IMAGE_FORMAT_TYPE_RGBA:
362 vdp_status = vdpau_bitmap_surface_put_bits_native(
363 driver_data,
364 obj_subpicture->vdp_bitmap_surface,
365 &src, &src_stride,
366 &dirty_rect
367 );
368 break;
369 case VDP_IMAGE_FORMAT_TYPE_INDEXED:
370 vdp_status = vdpau_output_surface_put_bits_indexed(
371 driver_data,
372 obj_subpicture->vdp_output_surface,
373 obj_subpicture->vdp_format,
374 &src, &src_stride,
375 &dirty_rect,
376 VDP_COLOR_TABLE_FORMAT_B8G8R8X8,
377 obj_image->vdp_palette
378 );
379 break;
380 default:
381 vdp_status = VDP_STATUS_ERROR;
382 break;
383 }
384 if (vdp_status != VDP_STATUS_OK)
385 return vdpau_get_VAStatus(vdp_status);
386
387 obj_subpicture->last_commit = obj_buffer->mtime;
388 return VA_STATUS_SUCCESS;
389 }
390
391 // Create subpicture with image
392 static VAStatus
create_subpicture(vdpau_driver_data_t * driver_data,object_image_p obj_image,VASubpictureID * subpicture)393 create_subpicture(
394 vdpau_driver_data_t *driver_data,
395 object_image_p obj_image,
396 VASubpictureID *subpicture
397 )
398 {
399 *subpicture = object_heap_allocate(&driver_data->subpicture_heap);
400 if (*subpicture == VA_INVALID_ID)
401 return VA_STATUS_ERROR_ALLOCATION_FAILED;
402
403 object_subpicture_p obj_subpicture = VDPAU_SUBPICTURE(*subpicture);
404 if (!obj_subpicture)
405 return VA_STATUS_ERROR_ALLOCATION_FAILED;
406
407 const vdpau_subpic_format_map_t *m = get_format(&obj_image->image.format);
408 if (!is_supported_format(driver_data, m))
409 return VA_STATUS_ERROR_UNKNOWN; /* VA_STATUS_ERROR_UNSUPPORTED_FORMAT */
410
411 obj_subpicture->image_id = obj_image->base.id;
412 obj_subpicture->assocs = NULL;
413 obj_subpicture->assocs_count = 0;
414 obj_subpicture->assocs_count_max = 0;
415 obj_subpicture->width = obj_image->image.width;
416 obj_subpicture->height = obj_image->image.height;
417 obj_subpicture->vdp_bitmap_surface = VDP_INVALID_HANDLE;
418 obj_subpicture->vdp_output_surface = VDP_INVALID_HANDLE;
419 obj_subpicture->last_commit = 0;
420 obj_subpicture->vdp_format_type = m->vdp_format_type;
421 obj_subpicture->vdp_format = m->vdp_format;
422 obj_subpicture->alpha = 1.0;
423
424 VdpStatus vdp_status;
425 switch (obj_subpicture->vdp_format_type) {
426 case VDP_IMAGE_FORMAT_TYPE_RGBA:
427 vdp_status = vdpau_bitmap_surface_create(
428 driver_data,
429 driver_data->vdp_device,
430 obj_subpicture->vdp_format,
431 obj_subpicture->width,
432 obj_subpicture->height,
433 VDP_FALSE,
434 &obj_subpicture->vdp_bitmap_surface
435 );
436 break;
437 case VDP_IMAGE_FORMAT_TYPE_INDEXED:
438 vdp_status = vdpau_output_surface_create(
439 driver_data,
440 driver_data->vdp_device,
441 VDP_RGBA_FORMAT_B8G8R8A8,
442 obj_subpicture->width,
443 obj_subpicture->height,
444 &obj_subpicture->vdp_output_surface
445 );
446 break;
447 default:
448 vdp_status = VDP_STATUS_ERROR;
449 break;
450 }
451 return vdpau_get_VAStatus(vdp_status);
452 }
453
454 // Destroy subpicture
455 static void
destroy_subpicture(vdpau_driver_data_t * driver_data,object_subpicture_p obj_subpicture)456 destroy_subpicture(
457 vdpau_driver_data_t *driver_data,
458 object_subpicture_p obj_subpicture
459 )
460 {
461 object_surface_p obj_surface;
462 VAStatus status;
463 unsigned int i, n;
464
465 if (obj_subpicture->assocs) {
466 const unsigned int n_assocs = obj_subpicture->assocs_count;
467 for (i = 0, n = 0; i < n_assocs; i++) {
468 SubpictureAssociationP const assoc = obj_subpicture->assocs[0];
469 if (!assoc)
470 continue;
471 obj_surface = VDPAU_SURFACE(assoc->surface);
472 if (!obj_surface)
473 continue;
474 status = subpicture_deassociate_1(obj_subpicture, obj_surface);
475 if (status == VA_STATUS_SUCCESS)
476 ++n;
477 }
478 if (n != n_assocs)
479 vdpau_error_message("vaDestroySubpicture(): subpicture 0x%08x still "
480 "has %d surfaces associated to it\n",
481 obj_subpicture->base.id, n_assocs - n);
482 free(obj_subpicture->assocs);
483 obj_subpicture->assocs = NULL;
484 }
485 obj_subpicture->assocs_count = 0;
486 obj_subpicture->assocs_count_max = 0;
487
488 if (obj_subpicture->vdp_bitmap_surface != VDP_INVALID_HANDLE) {
489 vdpau_bitmap_surface_destroy(
490 driver_data,
491 obj_subpicture->vdp_bitmap_surface
492 );
493 obj_subpicture->vdp_bitmap_surface = VDP_INVALID_HANDLE;
494 }
495
496 if (obj_subpicture->vdp_output_surface != VDP_INVALID_HANDLE) {
497 vdpau_output_surface_destroy(
498 driver_data,
499 obj_subpicture->vdp_output_surface
500 );
501 obj_subpicture->vdp_output_surface = VDP_INVALID_HANDLE;
502 }
503
504 obj_subpicture->image_id = VA_INVALID_ID;
505 object_heap_free(&driver_data->subpicture_heap,
506 (object_base_p)obj_subpicture);
507 }
508
509 // vaQuerySubpictureFormats
510 VAStatus
vdpau_QuerySubpictureFormats(VADriverContextP ctx,VAImageFormat * format_list,unsigned int * flags,unsigned int * num_formats)511 vdpau_QuerySubpictureFormats(
512 VADriverContextP ctx,
513 VAImageFormat *format_list,
514 unsigned int *flags,
515 unsigned int *num_formats
516 )
517 {
518 VDPAU_DRIVER_DATA_INIT;
519
520 int n;
521 for (n = 0; vdpau_subpic_formats_map[n].va_format.fourcc != 0; n++) {
522 const vdpau_subpic_format_map_t * const m = &vdpau_subpic_formats_map[n];
523 if (is_supported_format(driver_data, m)) {
524 if (format_list)
525 format_list[n] = m->va_format;
526 if (flags)
527 flags[n] = m->va_flags;
528 }
529 }
530
531 if (num_formats)
532 *num_formats = n;
533
534 return VA_STATUS_SUCCESS;
535 }
536
537 // vaCreateSubpicture
538 VAStatus
vdpau_CreateSubpicture(VADriverContextP ctx,VAImageID image,VASubpictureID * subpicture)539 vdpau_CreateSubpicture(
540 VADriverContextP ctx,
541 VAImageID image,
542 VASubpictureID *subpicture
543 )
544 {
545 VDPAU_DRIVER_DATA_INIT;
546
547 if (!subpicture)
548 return VA_STATUS_ERROR_INVALID_PARAMETER;
549
550 object_image_p obj_image = VDPAU_IMAGE(image);
551 if (!obj_image)
552 return VA_STATUS_ERROR_INVALID_IMAGE;
553
554 return create_subpicture(driver_data, obj_image, subpicture);
555 }
556
557 // vaDestroySubpicture
558 VAStatus
vdpau_DestroySubpicture(VADriverContextP ctx,VASubpictureID subpicture)559 vdpau_DestroySubpicture(
560 VADriverContextP ctx,
561 VASubpictureID subpicture
562 )
563 {
564 VDPAU_DRIVER_DATA_INIT;
565
566 object_subpicture_p obj_subpicture = VDPAU_SUBPICTURE(subpicture);
567 if (!obj_subpicture)
568 return VA_STATUS_ERROR_INVALID_SUBPICTURE;
569
570 destroy_subpicture(driver_data, obj_subpicture);
571 return VA_STATUS_SUCCESS;
572 }
573
574 // vaSetSubpictureImage
575 VAStatus
vdpau_SetSubpictureImage(VADriverContextP ctx,VASubpictureID subpicture,VAImageID image)576 vdpau_SetSubpictureImage(
577 VADriverContextP ctx,
578 VASubpictureID subpicture,
579 VAImageID image
580 )
581 {
582 VDPAU_DRIVER_DATA_INIT;
583
584 object_subpicture_p obj_subpicture = VDPAU_SUBPICTURE(subpicture);
585 if (!obj_subpicture)
586 return VA_STATUS_ERROR_INVALID_SUBPICTURE;
587
588 object_image_p obj_image = VDPAU_IMAGE(image);
589 if (!obj_image)
590 return VA_STATUS_ERROR_INVALID_IMAGE;
591
592 obj_subpicture->image_id = obj_image->base.id;
593 return VA_STATUS_SUCCESS;
594 }
595
596 // vaSetSubpicturePalette (not a PUBLIC interface)
597 VAStatus
vdpau_SetSubpicturePalette(VADriverContextP ctx,VASubpictureID subpicture,unsigned char * palette)598 vdpau_SetSubpicturePalette(
599 VADriverContextP ctx,
600 VASubpictureID subpicture,
601 unsigned char *palette
602 )
603 {
604 /* TODO */
605 return VA_STATUS_ERROR_OPERATION_FAILED;
606 }
607
608 // vaSetSubpictureChromaKey
609 VAStatus
vdpau_SetSubpictureChromakey(VADriverContextP ctx,VASubpictureID subpicture,unsigned int chromakey_min,unsigned int chromakey_max,unsigned int chromakey_mask)610 vdpau_SetSubpictureChromakey(
611 VADriverContextP ctx,
612 VASubpictureID subpicture,
613 unsigned int chromakey_min,
614 unsigned int chromakey_max,
615 unsigned int chromakey_mask
616 )
617 {
618 VDPAU_DRIVER_DATA_INIT;
619
620 object_subpicture_p obj_subpicture = VDPAU_SUBPICTURE(subpicture);
621 if (!obj_subpicture)
622 return VA_STATUS_ERROR_INVALID_SUBPICTURE;
623
624 obj_subpicture->chromakey_min = chromakey_min;
625 obj_subpicture->chromakey_max = chromakey_max;
626 obj_subpicture->chromakey_mask = chromakey_mask;
627 return VA_STATUS_SUCCESS;
628 }
629
630 // vaSetSubpictureGlobalAlpha
631 VAStatus
vdpau_SetSubpictureGlobalAlpha(VADriverContextP ctx,VASubpictureID subpicture,float global_alpha)632 vdpau_SetSubpictureGlobalAlpha(
633 VADriverContextP ctx,
634 VASubpictureID subpicture,
635 float global_alpha
636 )
637 {
638 VDPAU_DRIVER_DATA_INIT;
639
640 object_subpicture_p obj_subpicture = VDPAU_SUBPICTURE(subpicture);
641 if (!obj_subpicture)
642 return VA_STATUS_ERROR_INVALID_SUBPICTURE;
643
644 obj_subpicture->alpha = global_alpha;
645 return VA_STATUS_SUCCESS;
646 }
647
648 // vaAssociateSubpicture
649 VAStatus
vdpau_AssociateSubpicture(VADriverContextP ctx,VASubpictureID subpicture,VASurfaceID * target_surfaces,int num_surfaces,short src_x,short src_y,short dest_x,short dest_y,unsigned short width,unsigned short height,unsigned int flags)650 vdpau_AssociateSubpicture(
651 VADriverContextP ctx,
652 VASubpictureID subpicture,
653 VASurfaceID *target_surfaces,
654 int num_surfaces,
655 short src_x,
656 short src_y,
657 short dest_x,
658 short dest_y,
659 unsigned short width,
660 unsigned short height,
661 unsigned int flags
662 )
663 {
664 VDPAU_DRIVER_DATA_INIT;
665
666 if (!target_surfaces || num_surfaces == 0)
667 return VA_STATUS_SUCCESS;
668
669 object_subpicture_p obj_subpicture = VDPAU_SUBPICTURE(subpicture);
670 if (!obj_subpicture)
671 return VA_STATUS_ERROR_INVALID_SUBPICTURE;
672
673 VARectangle src_rect, dst_rect;
674 src_rect.x = src_x;
675 src_rect.y = src_y;
676 src_rect.width = width;
677 src_rect.height = height;
678 dst_rect.x = dest_x;
679 dst_rect.y = dest_y;
680 dst_rect.width = width;
681 dst_rect.height = height;
682 return associate_subpicture(driver_data, obj_subpicture,
683 target_surfaces, num_surfaces,
684 &src_rect, &dst_rect, flags);
685 }
686
687 // vaAssociateSubpicture2
688 VAStatus
vdpau_AssociateSubpicture_full(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)689 vdpau_AssociateSubpicture_full(
690 VADriverContextP ctx,
691 VASubpictureID subpicture,
692 VASurfaceID *target_surfaces,
693 int num_surfaces,
694 short src_x,
695 short src_y,
696 unsigned short src_width,
697 unsigned short src_height,
698 short dest_x,
699 short dest_y,
700 unsigned short dest_width,
701 unsigned short dest_height,
702 unsigned int flags
703 )
704 {
705 VDPAU_DRIVER_DATA_INIT;
706
707 if (!target_surfaces || num_surfaces == 0)
708 return VA_STATUS_SUCCESS;
709
710 object_subpicture_p obj_subpicture = VDPAU_SUBPICTURE(subpicture);
711 if (!obj_subpicture)
712 return VA_STATUS_ERROR_INVALID_SUBPICTURE;
713
714 VARectangle src_rect, dst_rect;
715 src_rect.x = src_x;
716 src_rect.y = src_y;
717 src_rect.width = src_width;
718 src_rect.height = src_height;
719 dst_rect.x = dest_x;
720 dst_rect.y = dest_y;
721 dst_rect.width = dest_width;
722 dst_rect.height = dest_height;
723 return associate_subpicture(driver_data, obj_subpicture,
724 target_surfaces, num_surfaces,
725 &src_rect, &dst_rect, flags);
726 }
727
728 // vaDeassociateSubpicture
729 VAStatus
vdpau_DeassociateSubpicture(VADriverContextP ctx,VASubpictureID subpicture,VASurfaceID * target_surfaces,int num_surfaces)730 vdpau_DeassociateSubpicture(
731 VADriverContextP ctx,
732 VASubpictureID subpicture,
733 VASurfaceID *target_surfaces,
734 int num_surfaces
735 )
736 {
737 VDPAU_DRIVER_DATA_INIT;
738
739 if (!target_surfaces || num_surfaces == 0)
740 return VA_STATUS_SUCCESS;
741
742 object_subpicture_p obj_subpicture = VDPAU_SUBPICTURE(subpicture);
743 if (!obj_subpicture)
744 return VA_STATUS_ERROR_INVALID_SUBPICTURE;
745
746 return deassociate_subpicture(driver_data, obj_subpicture,
747 target_surfaces, num_surfaces);
748 }
749