1 /**************************************************************************
3 * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian.
4 * Copyright 2014 Advanced Micro Devices, Inc.
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:
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
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.
27 **************************************************************************/
29 #include "pipe/p_screen.h"
31 #include "util/u_memory.h"
32 #include "util/u_handle_table.h"
33 #include "util/u_surface.h"
34 #include "util/u_video.h"
36 #include "vl/vl_winsys.h"
38 #include "va_private.h"
40 static const VAImageFormat formats
[VL_VA_MAX_IMAGE_FORMATS
] =
42 {VA_FOURCC('N','V','1','2')},
43 {VA_FOURCC('I','4','2','0')},
44 {VA_FOURCC('Y','V','1','2')},
45 {VA_FOURCC('Y','U','Y','V')},
46 {VA_FOURCC('U','Y','V','Y')},
50 vlVaVideoSurfaceSize(vlVaSurface
*p_surf
, int component
,
51 unsigned *width
, unsigned *height
)
53 *width
= p_surf
->templat
.width
;
54 *height
= p_surf
->templat
.height
;
57 if (p_surf
->templat
.chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_420
) {
60 } else if (p_surf
->templat
.chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_422
)
63 if (p_surf
->templat
.interlaced
)
68 vlVaQueryImageFormats(VADriverContextP ctx
, VAImageFormat
*format_list
, int *num_formats
)
70 struct pipe_screen
*pscreen
;
71 enum pipe_format format
;
75 return VA_STATUS_ERROR_INVALID_CONTEXT
;
77 if (!(format_list
&& num_formats
))
78 return VA_STATUS_ERROR_INVALID_PARAMETER
;
81 pscreen
= VL_VA_PSCREEN(ctx
);
82 for (i
= 0; i
< VL_VA_MAX_IMAGE_FORMATS
; ++i
) {
83 format
= YCbCrToPipe(formats
[i
].fourcc
);
84 if (pscreen
->is_video_format_supported(pscreen
, format
,
85 PIPE_VIDEO_PROFILE_UNKNOWN
,
86 PIPE_VIDEO_ENTRYPOINT_BITSTREAM
))
87 format_list
[(*num_formats
)++] = formats
[i
];
90 return VA_STATUS_SUCCESS
;
94 vlVaCreateImage(VADriverContextP ctx
, VAImageFormat
*format
, int width
, int height
, VAImage
*image
)
100 return VA_STATUS_ERROR_INVALID_CONTEXT
;
102 if (!(format
&& image
&& width
&& height
))
103 return VA_STATUS_ERROR_INVALID_PARAMETER
;
105 drv
= VL_VA_DRIVER(ctx
);
107 image
->image_id
= handle_table_add(drv
->htab
, image
);
108 image
->format
= *format
;
109 image
->width
= width
;
110 image
->height
= height
;
114 switch (format
->fourcc
) {
115 case VA_FOURCC('N','V','1','2'):
116 image
->num_planes
= 2;
117 image
->pitches
[0] = w
;
118 image
->offsets
[0] = 0;
119 image
->pitches
[1] = w
;
120 image
->offsets
[1] = w
* h
;
121 image
->data_size
= w
* h
* 3 / 2;
124 case VA_FOURCC('I','4','2','0'):
125 case VA_FOURCC('Y','V','1','2'):
126 image
->num_planes
= 3;
127 image
->pitches
[0] = w
;
128 image
->offsets
[0] = 0;
129 image
->pitches
[1] = w
/ 2;
130 image
->offsets
[1] = w
* h
;
131 image
->pitches
[2] = w
/ 2;
132 image
->offsets
[2] = w
* h
* 5 / 4;
133 image
->data_size
= w
* h
* 3 / 2;
136 case VA_FOURCC('U','Y','V','Y'):
137 case VA_FOURCC('Y','U','Y','V'):
138 image
->num_planes
= 1;
139 image
->pitches
[0] = w
* 2;
140 image
->offsets
[0] = 0;
141 image
->data_size
= w
* h
* 2;
145 return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT
;
148 return vlVaCreateBuffer(ctx
, 0, VAImageBufferType
,
149 align(image
->data_size
, 16),
150 1, NULL
, &image
->buf
);
154 vlVaDeriveImage(VADriverContextP ctx
, VASurfaceID surface
, VAImage
*image
)
157 return VA_STATUS_ERROR_INVALID_CONTEXT
;
159 return VA_STATUS_ERROR_UNIMPLEMENTED
;
163 vlVaDestroyImage(VADriverContextP ctx
, VAImageID image
)
168 return VA_STATUS_ERROR_INVALID_CONTEXT
;
170 vaimage
= handle_table_get(VL_VA_DRIVER(ctx
)->htab
, image
);
172 return VA_STATUS_ERROR_INVALID_IMAGE
;
174 return vlVaDestroyBuffer(ctx
, vaimage
->buf
);
178 vlVaSetImagePalette(VADriverContextP ctx
, VAImageID image
, unsigned char *palette
)
181 return VA_STATUS_ERROR_INVALID_CONTEXT
;
183 return VA_STATUS_ERROR_UNIMPLEMENTED
;
187 vlVaGetImage(VADriverContextP ctx
, VASurfaceID surface
, int x
, int y
,
188 unsigned int width
, unsigned int height
, VAImageID image
)
194 struct pipe_sampler_view
**views
;
195 enum pipe_format format
;
196 bool convert
= false;
198 unsigned pitches
[3], i
, j
;
201 return VA_STATUS_ERROR_INVALID_CONTEXT
;
203 drv
= VL_VA_DRIVER(ctx
);
205 surf
= handle_table_get(drv
->htab
, surface
);
206 if (!surf
|| !surf
->buffer
)
207 return VA_STATUS_ERROR_INVALID_SURFACE
;
209 vaimage
= handle_table_get(drv
->htab
, image
);
211 return VA_STATUS_ERROR_INVALID_IMAGE
;
213 img_buf
= handle_table_get(drv
->htab
, vaimage
->buf
);
215 return VA_STATUS_ERROR_INVALID_BUFFER
;
217 format
= YCbCrToPipe(vaimage
->format
.fourcc
);
218 if (format
== PIPE_FORMAT_NONE
)
219 return VA_STATUS_ERROR_OPERATION_FAILED
;
221 if (format
!= surf
->buffer
->buffer_format
) {
222 /* support NV12 to YV12 conversion now only */
223 if (format
== PIPE_FORMAT_YV12
&&
224 surf
->buffer
->buffer_format
== PIPE_FORMAT_NV12
)
227 return VA_STATUS_ERROR_OPERATION_FAILED
;
230 views
= surf
->buffer
->get_sampler_view_planes(surf
->buffer
);
232 return VA_STATUS_ERROR_OPERATION_FAILED
;
234 for (i
= 0; i
< vaimage
->num_planes
; i
++) {
235 data
[i
] = img_buf
->data
+ vaimage
->offsets
[i
];
236 pitches
[i
] = vaimage
->pitches
[i
];
238 if (vaimage
->format
.fourcc
== VA_FOURCC('I','4','2','0')) {
245 pitches
[1] = pitches
[2];
249 for (i
= 0; i
< vaimage
->num_planes
; i
++) {
250 unsigned width
, height
;
251 if (!views
[i
]) continue;
252 vlVaVideoSurfaceSize(surf
, i
, &width
, &height
);
253 for (j
= 0; j
< views
[i
]->texture
->array_size
; ++j
) {
254 struct pipe_box box
= {0, 0, j
, width
, height
, 1};
255 struct pipe_transfer
*transfer
;
257 map
= drv
->pipe
->transfer_map(drv
->pipe
, views
[i
]->texture
, 0,
258 PIPE_TRANSFER_READ
, &box
, &transfer
);
260 return VA_STATUS_ERROR_OPERATION_FAILED
;
262 if (i
== 1 && convert
) {
263 u_copy_nv12_to_yv12(data
, pitches
, i
, j
,
264 transfer
->stride
, views
[i
]->texture
->array_size
,
265 map
, box
.width
, box
.height
);
267 util_copy_rect(data
[i
] + pitches
[i
] * j
,
268 views
[i
]->texture
->format
,
269 pitches
[i
] * views
[i
]->texture
->array_size
, 0, 0,
270 box
.width
, box
.height
, map
, transfer
->stride
, 0, 0);
272 pipe_transfer_unmap(drv
->pipe
, transfer
);
276 return VA_STATUS_SUCCESS
;
280 vlVaPutImage(VADriverContextP ctx
, VASurfaceID surface
, VAImageID image
,
281 int src_x
, int src_y
, unsigned int src_width
, unsigned int src_height
,
282 int dest_x
, int dest_y
, unsigned int dest_width
, unsigned int dest_height
)
288 struct pipe_sampler_view
**views
;
289 enum pipe_format format
;
291 unsigned pitches
[3], i
, j
;
294 return VA_STATUS_ERROR_INVALID_CONTEXT
;
296 drv
= VL_VA_DRIVER(ctx
);
298 surf
= handle_table_get(drv
->htab
, surface
);
299 if (!surf
|| !surf
->buffer
)
300 return VA_STATUS_ERROR_INVALID_SURFACE
;
302 vaimage
= handle_table_get(drv
->htab
, image
);
304 return VA_STATUS_ERROR_INVALID_IMAGE
;
306 img_buf
= handle_table_get(drv
->htab
, vaimage
->buf
);
308 return VA_STATUS_ERROR_INVALID_BUFFER
;
310 format
= YCbCrToPipe(vaimage
->format
.fourcc
);
311 if (format
== PIPE_FORMAT_NONE
)
312 return VA_STATUS_ERROR_OPERATION_FAILED
;
314 if (surf
->buffer
== NULL
|| format
!= surf
->buffer
->buffer_format
) {
316 surf
->buffer
->destroy(surf
->buffer
);
317 surf
->templat
.buffer_format
= format
;
318 surf
->buffer
= drv
->pipe
->create_video_buffer(drv
->pipe
, &surf
->templat
);
320 return VA_STATUS_ERROR_ALLOCATION_FAILED
;
323 views
= surf
->buffer
->get_sampler_view_planes(surf
->buffer
);
325 return VA_STATUS_ERROR_OPERATION_FAILED
;
327 for (i
= 0; i
< vaimage
->num_planes
; i
++) {
328 data
[i
] = img_buf
->data
+ vaimage
->offsets
[i
];
329 pitches
[i
] = vaimage
->pitches
[i
];
331 if (vaimage
->format
.fourcc
== VA_FOURCC('I','4','2','0')) {
338 pitches
[1] = pitches
[2];
342 for (i
= 0; i
< vaimage
->num_planes
; ++i
) {
343 unsigned width
, height
;
344 if (!views
[i
]) continue;
345 vlVaVideoSurfaceSize(surf
, i
, &width
, &height
);
346 for (j
= 0; j
< views
[i
]->texture
->array_size
; ++j
) {
347 struct pipe_box dst_box
= {0, 0, j
, width
, height
, 1};
348 drv
->pipe
->transfer_inline_write(drv
->pipe
, views
[i
]->texture
, 0,
349 PIPE_TRANSFER_WRITE
, &dst_box
,
350 data
[i
] + pitches
[i
] * j
,
351 pitches
[i
] * views
[i
]->texture
->array_size
, 0);
355 return VA_STATUS_SUCCESS
;