1b8e80941Smrg/************************************************************************** 2b8e80941Smrg * 3b8e80941Smrg * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. 4b8e80941Smrg * Copyright 2014 Advanced Micro Devices, Inc. 5b8e80941Smrg * All Rights Reserved. 6b8e80941Smrg * 7b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a 8b8e80941Smrg * copy of this software and associated documentation files (the 9b8e80941Smrg * "Software"), to deal in the Software without restriction, including 10b8e80941Smrg * without limitation the rights to use, copy, modify, merge, publish, 11b8e80941Smrg * distribute, sub license, and/or sell copies of the Software, and to 12b8e80941Smrg * permit persons to whom the Software is furnished to do so, subject to 13b8e80941Smrg * the following conditions: 14b8e80941Smrg * 15b8e80941Smrg * The above copyright notice and this permission notice (including the 16b8e80941Smrg * next paragraph) shall be included in all copies or substantial portions 17b8e80941Smrg * of the Software. 18b8e80941Smrg * 19b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20b8e80941Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21b8e80941Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22b8e80941Smrg * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR 23b8e80941Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24b8e80941Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25b8e80941Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26b8e80941Smrg * 27b8e80941Smrg **************************************************************************/ 28b8e80941Smrg 29b8e80941Smrg#include "pipe/p_screen.h" 30b8e80941Smrg 31b8e80941Smrg#include "util/u_memory.h" 32b8e80941Smrg#include "util/u_handle_table.h" 33b8e80941Smrg#include "util/u_surface.h" 34b8e80941Smrg#include "util/u_video.h" 35b8e80941Smrg 36b8e80941Smrg#include "vl/vl_winsys.h" 37b8e80941Smrg#include "vl/vl_video_buffer.h" 38b8e80941Smrg 39b8e80941Smrg#include "va_private.h" 40b8e80941Smrg 41b8e80941Smrgstatic const VAImageFormat formats[] = 42b8e80941Smrg{ 43b8e80941Smrg {VA_FOURCC('N','V','1','2')}, 44b8e80941Smrg {VA_FOURCC('P','0','1','0')}, 45b8e80941Smrg {VA_FOURCC('P','0','1','6')}, 46b8e80941Smrg {VA_FOURCC('I','4','2','0')}, 47b8e80941Smrg {VA_FOURCC('Y','V','1','2')}, 48b8e80941Smrg {VA_FOURCC('Y','U','Y','V')}, 49b8e80941Smrg {VA_FOURCC('U','Y','V','Y')}, 50b8e80941Smrg {.fourcc = VA_FOURCC('B','G','R','A'), .byte_order = VA_LSB_FIRST, 32, 32, 51b8e80941Smrg 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000}, 52b8e80941Smrg {.fourcc = VA_FOURCC('R','G','B','A'), .byte_order = VA_LSB_FIRST, 32, 32, 53b8e80941Smrg 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000}, 54b8e80941Smrg {.fourcc = VA_FOURCC('B','G','R','X'), .byte_order = VA_LSB_FIRST, 32, 24, 55b8e80941Smrg 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000}, 56b8e80941Smrg {.fourcc = VA_FOURCC('R','G','B','X'), .byte_order = VA_LSB_FIRST, 32, 24, 57b8e80941Smrg 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000} 58b8e80941Smrg}; 59b8e80941Smrg 60b8e80941Smrgstatic void 61b8e80941SmrgvlVaVideoSurfaceSize(vlVaSurface *p_surf, int component, 62b8e80941Smrg unsigned *width, unsigned *height) 63b8e80941Smrg{ 64b8e80941Smrg *width = p_surf->templat.width; 65b8e80941Smrg *height = p_surf->templat.height; 66b8e80941Smrg 67b8e80941Smrg vl_video_buffer_adjust_size(width, height, component, 68b8e80941Smrg p_surf->templat.chroma_format, 69b8e80941Smrg p_surf->templat.interlaced); 70b8e80941Smrg} 71b8e80941Smrg 72b8e80941SmrgVAStatus 73b8e80941SmrgvlVaQueryImageFormats(VADriverContextP ctx, VAImageFormat *format_list, int *num_formats) 74b8e80941Smrg{ 75b8e80941Smrg struct pipe_screen *pscreen; 76b8e80941Smrg enum pipe_format format; 77b8e80941Smrg int i; 78b8e80941Smrg 79b8e80941Smrg STATIC_ASSERT(ARRAY_SIZE(formats) == VL_VA_MAX_IMAGE_FORMATS); 80b8e80941Smrg 81b8e80941Smrg if (!ctx) 82b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 83b8e80941Smrg 84b8e80941Smrg if (!(format_list && num_formats)) 85b8e80941Smrg return VA_STATUS_ERROR_INVALID_PARAMETER; 86b8e80941Smrg 87b8e80941Smrg *num_formats = 0; 88b8e80941Smrg pscreen = VL_VA_PSCREEN(ctx); 89b8e80941Smrg for (i = 0; i < ARRAY_SIZE(formats); ++i) { 90b8e80941Smrg format = VaFourccToPipeFormat(formats[i].fourcc); 91b8e80941Smrg if (pscreen->is_video_format_supported(pscreen, format, 92b8e80941Smrg PIPE_VIDEO_PROFILE_UNKNOWN, 93b8e80941Smrg PIPE_VIDEO_ENTRYPOINT_BITSTREAM)) 94b8e80941Smrg format_list[(*num_formats)++] = formats[i]; 95b8e80941Smrg } 96b8e80941Smrg 97b8e80941Smrg return VA_STATUS_SUCCESS; 98b8e80941Smrg} 99b8e80941Smrg 100b8e80941SmrgVAStatus 101b8e80941SmrgvlVaCreateImage(VADriverContextP ctx, VAImageFormat *format, int width, int height, VAImage *image) 102b8e80941Smrg{ 103b8e80941Smrg VAStatus status; 104b8e80941Smrg vlVaDriver *drv; 105b8e80941Smrg VAImage *img; 106b8e80941Smrg int w, h; 107b8e80941Smrg 108b8e80941Smrg if (!ctx) 109b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 110b8e80941Smrg 111b8e80941Smrg if (!(format && image && width && height)) 112b8e80941Smrg return VA_STATUS_ERROR_INVALID_PARAMETER; 113b8e80941Smrg 114b8e80941Smrg drv = VL_VA_DRIVER(ctx); 115b8e80941Smrg 116b8e80941Smrg img = CALLOC(1, sizeof(VAImage)); 117b8e80941Smrg if (!img) 118b8e80941Smrg return VA_STATUS_ERROR_ALLOCATION_FAILED; 119b8e80941Smrg mtx_lock(&drv->mutex); 120b8e80941Smrg img->image_id = handle_table_add(drv->htab, img); 121b8e80941Smrg mtx_unlock(&drv->mutex); 122b8e80941Smrg 123b8e80941Smrg img->format = *format; 124b8e80941Smrg img->width = width; 125b8e80941Smrg img->height = height; 126b8e80941Smrg w = align(width, 2); 127b8e80941Smrg h = align(height, 2); 128b8e80941Smrg 129b8e80941Smrg switch (format->fourcc) { 130b8e80941Smrg case VA_FOURCC('N','V','1','2'): 131b8e80941Smrg img->num_planes = 2; 132b8e80941Smrg img->pitches[0] = w; 133b8e80941Smrg img->offsets[0] = 0; 134b8e80941Smrg img->pitches[1] = w; 135b8e80941Smrg img->offsets[1] = w * h; 136b8e80941Smrg img->data_size = w * h * 3 / 2; 137b8e80941Smrg break; 138b8e80941Smrg 139b8e80941Smrg case VA_FOURCC('P','0','1','0'): 140b8e80941Smrg case VA_FOURCC('P','0','1','6'): 141b8e80941Smrg img->num_planes = 2; 142b8e80941Smrg img->pitches[0] = w * 2; 143b8e80941Smrg img->offsets[0] = 0; 144b8e80941Smrg img->pitches[1] = w * 2; 145b8e80941Smrg img->offsets[1] = w * h * 2; 146b8e80941Smrg img->data_size = w * h * 3; 147b8e80941Smrg break; 148b8e80941Smrg 149b8e80941Smrg case VA_FOURCC('I','4','2','0'): 150b8e80941Smrg case VA_FOURCC('Y','V','1','2'): 151b8e80941Smrg img->num_planes = 3; 152b8e80941Smrg img->pitches[0] = w; 153b8e80941Smrg img->offsets[0] = 0; 154b8e80941Smrg img->pitches[1] = w / 2; 155b8e80941Smrg img->offsets[1] = w * h; 156b8e80941Smrg img->pitches[2] = w / 2; 157b8e80941Smrg img->offsets[2] = w * h * 5 / 4; 158b8e80941Smrg img->data_size = w * h * 3 / 2; 159b8e80941Smrg break; 160b8e80941Smrg 161b8e80941Smrg case VA_FOURCC('U','Y','V','Y'): 162b8e80941Smrg case VA_FOURCC('Y','U','Y','V'): 163b8e80941Smrg img->num_planes = 1; 164b8e80941Smrg img->pitches[0] = w * 2; 165b8e80941Smrg img->offsets[0] = 0; 166b8e80941Smrg img->data_size = w * h * 2; 167b8e80941Smrg break; 168b8e80941Smrg 169b8e80941Smrg case VA_FOURCC('B','G','R','A'): 170b8e80941Smrg case VA_FOURCC('R','G','B','A'): 171b8e80941Smrg case VA_FOURCC('B','G','R','X'): 172b8e80941Smrg case VA_FOURCC('R','G','B','X'): 173b8e80941Smrg img->num_planes = 1; 174b8e80941Smrg img->pitches[0] = w * 4; 175b8e80941Smrg img->offsets[0] = 0; 176b8e80941Smrg img->data_size = w * h * 4; 177b8e80941Smrg break; 178b8e80941Smrg 179b8e80941Smrg default: 180b8e80941Smrg return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT; 181b8e80941Smrg } 182b8e80941Smrg 183b8e80941Smrg status = vlVaCreateBuffer(ctx, 0, VAImageBufferType, 184b8e80941Smrg align(img->data_size, 16), 185b8e80941Smrg 1, NULL, &img->buf); 186b8e80941Smrg if (status != VA_STATUS_SUCCESS) 187b8e80941Smrg return status; 188b8e80941Smrg *image = *img; 189b8e80941Smrg 190b8e80941Smrg return status; 191b8e80941Smrg} 192b8e80941Smrg 193b8e80941SmrgVAStatus 194b8e80941SmrgvlVaDeriveImage(VADriverContextP ctx, VASurfaceID surface, VAImage *image) 195b8e80941Smrg{ 196b8e80941Smrg vlVaDriver *drv; 197b8e80941Smrg vlVaSurface *surf; 198b8e80941Smrg vlVaBuffer *img_buf; 199b8e80941Smrg VAImage *img; 200b8e80941Smrg struct pipe_screen *screen; 201b8e80941Smrg struct pipe_surface **surfaces; 202b8e80941Smrg int w; 203b8e80941Smrg int h; 204b8e80941Smrg int i; 205b8e80941Smrg unsigned stride = 0; 206b8e80941Smrg unsigned offset = 0; 207b8e80941Smrg 208b8e80941Smrg if (!ctx) 209b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 210b8e80941Smrg 211b8e80941Smrg drv = VL_VA_DRIVER(ctx); 212b8e80941Smrg 213b8e80941Smrg if (!drv) 214b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 215b8e80941Smrg 216b8e80941Smrg screen = VL_VA_PSCREEN(ctx); 217b8e80941Smrg 218b8e80941Smrg if (!screen) 219b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 220b8e80941Smrg 221b8e80941Smrg surf = handle_table_get(drv->htab, surface); 222b8e80941Smrg 223b8e80941Smrg if (!surf || !surf->buffer) 224b8e80941Smrg return VA_STATUS_ERROR_INVALID_SURFACE; 225b8e80941Smrg 226b8e80941Smrg if (surf->buffer->interlaced) 227b8e80941Smrg return VA_STATUS_ERROR_OPERATION_FAILED; 228b8e80941Smrg 229b8e80941Smrg surfaces = surf->buffer->get_surfaces(surf->buffer); 230b8e80941Smrg if (!surfaces || !surfaces[0]->texture) 231b8e80941Smrg return VA_STATUS_ERROR_ALLOCATION_FAILED; 232b8e80941Smrg 233b8e80941Smrg img = CALLOC(1, sizeof(VAImage)); 234b8e80941Smrg if (!img) 235b8e80941Smrg return VA_STATUS_ERROR_ALLOCATION_FAILED; 236b8e80941Smrg 237b8e80941Smrg img->format.fourcc = PipeFormatToVaFourcc(surf->buffer->buffer_format); 238b8e80941Smrg img->buf = VA_INVALID_ID; 239b8e80941Smrg img->width = surf->buffer->width; 240b8e80941Smrg img->height = surf->buffer->height; 241b8e80941Smrg img->num_palette_entries = 0; 242b8e80941Smrg img->entry_bytes = 0; 243b8e80941Smrg w = align(surf->buffer->width, 2); 244b8e80941Smrg h = align(surf->buffer->height, 2); 245b8e80941Smrg 246b8e80941Smrg for (i = 0; i < ARRAY_SIZE(formats); ++i) { 247b8e80941Smrg if (img->format.fourcc == formats[i].fourcc) { 248b8e80941Smrg img->format = formats[i]; 249b8e80941Smrg break; 250b8e80941Smrg } 251b8e80941Smrg } 252b8e80941Smrg 253b8e80941Smrg mtx_lock(&drv->mutex); 254b8e80941Smrg if (screen->resource_get_info) { 255b8e80941Smrg screen->resource_get_info(screen, surfaces[0]->texture, &stride, 256b8e80941Smrg &offset); 257b8e80941Smrg if (!stride) 258b8e80941Smrg offset = 0; 259b8e80941Smrg } 260b8e80941Smrg 261b8e80941Smrg switch (img->format.fourcc) { 262b8e80941Smrg case VA_FOURCC('U','Y','V','Y'): 263b8e80941Smrg case VA_FOURCC('Y','U','Y','V'): 264b8e80941Smrg img->pitches[0] = stride > 0 ? stride : w * 2; 265b8e80941Smrg assert(img->pitches[0] >= (w * 2)); 266b8e80941Smrg break; 267b8e80941Smrg 268b8e80941Smrg case VA_FOURCC('B','G','R','A'): 269b8e80941Smrg case VA_FOURCC('R','G','B','A'): 270b8e80941Smrg case VA_FOURCC('B','G','R','X'): 271b8e80941Smrg case VA_FOURCC('R','G','B','X'): 272b8e80941Smrg img->pitches[0] = stride > 0 ? stride : w * 4; 273b8e80941Smrg assert(img->pitches[0] >= (w * 4)); 274b8e80941Smrg break; 275b8e80941Smrg 276b8e80941Smrg default: 277b8e80941Smrg /* VaDeriveImage only supports contiguous planes. But there is now a 278b8e80941Smrg more generic api vlVaExportSurfaceHandle. */ 279b8e80941Smrg FREE(img); 280b8e80941Smrg mtx_unlock(&drv->mutex); 281b8e80941Smrg return VA_STATUS_ERROR_OPERATION_FAILED; 282b8e80941Smrg } 283b8e80941Smrg 284b8e80941Smrg img->num_planes = 1; 285b8e80941Smrg img->offsets[0] = offset; 286b8e80941Smrg img->data_size = img->pitches[0] * h; 287b8e80941Smrg 288b8e80941Smrg img_buf = CALLOC(1, sizeof(vlVaBuffer)); 289b8e80941Smrg if (!img_buf) { 290b8e80941Smrg FREE(img); 291b8e80941Smrg mtx_unlock(&drv->mutex); 292b8e80941Smrg return VA_STATUS_ERROR_ALLOCATION_FAILED; 293b8e80941Smrg } 294b8e80941Smrg 295b8e80941Smrg img->image_id = handle_table_add(drv->htab, img); 296b8e80941Smrg 297b8e80941Smrg img_buf->type = VAImageBufferType; 298b8e80941Smrg img_buf->size = img->data_size; 299b8e80941Smrg img_buf->num_elements = 1; 300b8e80941Smrg 301b8e80941Smrg pipe_resource_reference(&img_buf->derived_surface.resource, surfaces[0]->texture); 302b8e80941Smrg 303b8e80941Smrg img->buf = handle_table_add(VL_VA_DRIVER(ctx)->htab, img_buf); 304b8e80941Smrg mtx_unlock(&drv->mutex); 305b8e80941Smrg 306b8e80941Smrg *image = *img; 307b8e80941Smrg 308b8e80941Smrg return VA_STATUS_SUCCESS; 309b8e80941Smrg} 310b8e80941Smrg 311b8e80941SmrgVAStatus 312b8e80941SmrgvlVaDestroyImage(VADriverContextP ctx, VAImageID image) 313b8e80941Smrg{ 314b8e80941Smrg vlVaDriver *drv; 315b8e80941Smrg VAImage *vaimage; 316b8e80941Smrg VAStatus status; 317b8e80941Smrg 318b8e80941Smrg if (!ctx) 319b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 320b8e80941Smrg 321b8e80941Smrg drv = VL_VA_DRIVER(ctx); 322b8e80941Smrg mtx_lock(&drv->mutex); 323b8e80941Smrg vaimage = handle_table_get(drv->htab, image); 324b8e80941Smrg if (!vaimage) { 325b8e80941Smrg mtx_unlock(&drv->mutex); 326b8e80941Smrg return VA_STATUS_ERROR_INVALID_IMAGE; 327b8e80941Smrg } 328b8e80941Smrg 329b8e80941Smrg handle_table_remove(VL_VA_DRIVER(ctx)->htab, image); 330b8e80941Smrg mtx_unlock(&drv->mutex); 331b8e80941Smrg status = vlVaDestroyBuffer(ctx, vaimage->buf); 332b8e80941Smrg FREE(vaimage); 333b8e80941Smrg return status; 334b8e80941Smrg} 335b8e80941Smrg 336b8e80941SmrgVAStatus 337b8e80941SmrgvlVaSetImagePalette(VADriverContextP ctx, VAImageID image, unsigned char *palette) 338b8e80941Smrg{ 339b8e80941Smrg if (!ctx) 340b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 341b8e80941Smrg 342b8e80941Smrg return VA_STATUS_ERROR_UNIMPLEMENTED; 343b8e80941Smrg} 344b8e80941Smrg 345b8e80941SmrgVAStatus 346b8e80941SmrgvlVaGetImage(VADriverContextP ctx, VASurfaceID surface, int x, int y, 347b8e80941Smrg unsigned int width, unsigned int height, VAImageID image) 348b8e80941Smrg{ 349b8e80941Smrg vlVaDriver *drv; 350b8e80941Smrg vlVaSurface *surf; 351b8e80941Smrg vlVaBuffer *img_buf; 352b8e80941Smrg VAImage *vaimage; 353b8e80941Smrg struct pipe_sampler_view **views; 354b8e80941Smrg enum pipe_format format; 355b8e80941Smrg bool convert = false; 356b8e80941Smrg void *data[3]; 357b8e80941Smrg unsigned pitches[3], i, j; 358b8e80941Smrg 359b8e80941Smrg if (!ctx) 360b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 361b8e80941Smrg 362b8e80941Smrg drv = VL_VA_DRIVER(ctx); 363b8e80941Smrg 364b8e80941Smrg mtx_lock(&drv->mutex); 365b8e80941Smrg surf = handle_table_get(drv->htab, surface); 366b8e80941Smrg if (!surf || !surf->buffer) { 367b8e80941Smrg mtx_unlock(&drv->mutex); 368b8e80941Smrg return VA_STATUS_ERROR_INVALID_SURFACE; 369b8e80941Smrg } 370b8e80941Smrg 371b8e80941Smrg vaimage = handle_table_get(drv->htab, image); 372b8e80941Smrg if (!vaimage) { 373b8e80941Smrg mtx_unlock(&drv->mutex); 374b8e80941Smrg return VA_STATUS_ERROR_INVALID_IMAGE; 375b8e80941Smrg } 376b8e80941Smrg 377b8e80941Smrg if (x < 0 || y < 0) { 378b8e80941Smrg mtx_unlock(&drv->mutex); 379b8e80941Smrg return VA_STATUS_ERROR_INVALID_PARAMETER; 380b8e80941Smrg } 381b8e80941Smrg 382b8e80941Smrg if (x + width > surf->templat.width || 383b8e80941Smrg y + height > surf->templat.height) { 384b8e80941Smrg mtx_unlock(&drv->mutex); 385b8e80941Smrg return VA_STATUS_ERROR_INVALID_PARAMETER; 386b8e80941Smrg } 387b8e80941Smrg 388b8e80941Smrg if (width > vaimage->width || 389b8e80941Smrg height > vaimage->height) { 390b8e80941Smrg mtx_unlock(&drv->mutex); 391b8e80941Smrg return VA_STATUS_ERROR_INVALID_PARAMETER; 392b8e80941Smrg } 393b8e80941Smrg 394b8e80941Smrg img_buf = handle_table_get(drv->htab, vaimage->buf); 395b8e80941Smrg if (!img_buf) { 396b8e80941Smrg mtx_unlock(&drv->mutex); 397b8e80941Smrg return VA_STATUS_ERROR_INVALID_BUFFER; 398b8e80941Smrg } 399b8e80941Smrg 400b8e80941Smrg format = VaFourccToPipeFormat(vaimage->format.fourcc); 401b8e80941Smrg if (format == PIPE_FORMAT_NONE) { 402b8e80941Smrg mtx_unlock(&drv->mutex); 403b8e80941Smrg return VA_STATUS_ERROR_OPERATION_FAILED; 404b8e80941Smrg } 405b8e80941Smrg 406b8e80941Smrg if (format != surf->buffer->buffer_format) { 407b8e80941Smrg /* support NV12 to YV12 and IYUV conversion now only */ 408b8e80941Smrg if ((format == PIPE_FORMAT_YV12 && 409b8e80941Smrg surf->buffer->buffer_format == PIPE_FORMAT_NV12) || 410b8e80941Smrg (format == PIPE_FORMAT_IYUV && 411b8e80941Smrg surf->buffer->buffer_format == PIPE_FORMAT_NV12)) 412b8e80941Smrg convert = true; 413b8e80941Smrg else { 414b8e80941Smrg mtx_unlock(&drv->mutex); 415b8e80941Smrg return VA_STATUS_ERROR_OPERATION_FAILED; 416b8e80941Smrg } 417b8e80941Smrg } 418b8e80941Smrg 419b8e80941Smrg views = surf->buffer->get_sampler_view_planes(surf->buffer); 420b8e80941Smrg if (!views) { 421b8e80941Smrg mtx_unlock(&drv->mutex); 422b8e80941Smrg return VA_STATUS_ERROR_OPERATION_FAILED; 423b8e80941Smrg } 424b8e80941Smrg 425b8e80941Smrg for (i = 0; i < vaimage->num_planes; i++) { 426b8e80941Smrg data[i] = img_buf->data + vaimage->offsets[i]; 427b8e80941Smrg pitches[i] = vaimage->pitches[i]; 428b8e80941Smrg } 429b8e80941Smrg if (vaimage->format.fourcc == VA_FOURCC('I','4','2','0')) { 430b8e80941Smrg void *tmp_d; 431b8e80941Smrg unsigned tmp_p; 432b8e80941Smrg tmp_d = data[1]; 433b8e80941Smrg data[1] = data[2]; 434b8e80941Smrg data[2] = tmp_d; 435b8e80941Smrg tmp_p = pitches[1]; 436b8e80941Smrg pitches[1] = pitches[2]; 437b8e80941Smrg pitches[2] = tmp_p; 438b8e80941Smrg } 439b8e80941Smrg 440b8e80941Smrg for (i = 0; i < vaimage->num_planes; i++) { 441b8e80941Smrg unsigned box_w = align(width, 2); 442b8e80941Smrg unsigned box_h = align(height, 2); 443b8e80941Smrg unsigned box_x = x & ~1; 444b8e80941Smrg unsigned box_y = y & ~1; 445b8e80941Smrg if (!views[i]) continue; 446b8e80941Smrg vl_video_buffer_adjust_size(&box_w, &box_h, i, 447b8e80941Smrg surf->templat.chroma_format, 448b8e80941Smrg surf->templat.interlaced); 449b8e80941Smrg vl_video_buffer_adjust_size(&box_x, &box_y, i, 450b8e80941Smrg surf->templat.chroma_format, 451b8e80941Smrg surf->templat.interlaced); 452b8e80941Smrg for (j = 0; j < views[i]->texture->array_size; ++j) { 453b8e80941Smrg struct pipe_box box = {box_x, box_y, j, box_w, box_h, 1}; 454b8e80941Smrg struct pipe_transfer *transfer; 455b8e80941Smrg uint8_t *map; 456b8e80941Smrg map = drv->pipe->transfer_map(drv->pipe, views[i]->texture, 0, 457b8e80941Smrg PIPE_TRANSFER_READ, &box, &transfer); 458b8e80941Smrg if (!map) { 459b8e80941Smrg mtx_unlock(&drv->mutex); 460b8e80941Smrg return VA_STATUS_ERROR_OPERATION_FAILED; 461b8e80941Smrg } 462b8e80941Smrg 463b8e80941Smrg if (i == 1 && convert) { 464b8e80941Smrg u_copy_nv12_to_yv12(data, pitches, i, j, 465b8e80941Smrg transfer->stride, views[i]->texture->array_size, 466b8e80941Smrg map, box.width, box.height); 467b8e80941Smrg } else { 468b8e80941Smrg util_copy_rect(data[i] + pitches[i] * j, 469b8e80941Smrg views[i]->texture->format, 470b8e80941Smrg pitches[i] * views[i]->texture->array_size, 0, 0, 471b8e80941Smrg box.width, box.height, map, transfer->stride, 0, 0); 472b8e80941Smrg } 473b8e80941Smrg pipe_transfer_unmap(drv->pipe, transfer); 474b8e80941Smrg } 475b8e80941Smrg } 476b8e80941Smrg mtx_unlock(&drv->mutex); 477b8e80941Smrg 478b8e80941Smrg return VA_STATUS_SUCCESS; 479b8e80941Smrg} 480b8e80941Smrg 481b8e80941SmrgVAStatus 482b8e80941SmrgvlVaPutImage(VADriverContextP ctx, VASurfaceID surface, VAImageID image, 483b8e80941Smrg int src_x, int src_y, unsigned int src_width, unsigned int src_height, 484b8e80941Smrg int dest_x, int dest_y, unsigned int dest_width, unsigned int dest_height) 485b8e80941Smrg{ 486b8e80941Smrg vlVaDriver *drv; 487b8e80941Smrg vlVaSurface *surf; 488b8e80941Smrg vlVaBuffer *img_buf; 489b8e80941Smrg VAImage *vaimage; 490b8e80941Smrg struct pipe_sampler_view **views; 491b8e80941Smrg enum pipe_format format; 492b8e80941Smrg void *data[3]; 493b8e80941Smrg unsigned pitches[3], i, j; 494b8e80941Smrg 495b8e80941Smrg if (!ctx) 496b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 497b8e80941Smrg 498b8e80941Smrg drv = VL_VA_DRIVER(ctx); 499b8e80941Smrg mtx_lock(&drv->mutex); 500b8e80941Smrg 501b8e80941Smrg surf = handle_table_get(drv->htab, surface); 502b8e80941Smrg if (!surf || !surf->buffer) { 503b8e80941Smrg mtx_unlock(&drv->mutex); 504b8e80941Smrg return VA_STATUS_ERROR_INVALID_SURFACE; 505b8e80941Smrg } 506b8e80941Smrg 507b8e80941Smrg vaimage = handle_table_get(drv->htab, image); 508b8e80941Smrg if (!vaimage) { 509b8e80941Smrg mtx_unlock(&drv->mutex); 510b8e80941Smrg return VA_STATUS_ERROR_INVALID_IMAGE; 511b8e80941Smrg } 512b8e80941Smrg 513b8e80941Smrg img_buf = handle_table_get(drv->htab, vaimage->buf); 514b8e80941Smrg if (!img_buf) { 515b8e80941Smrg mtx_unlock(&drv->mutex); 516b8e80941Smrg return VA_STATUS_ERROR_INVALID_BUFFER; 517b8e80941Smrg } 518b8e80941Smrg 519b8e80941Smrg if (img_buf->derived_surface.resource) { 520b8e80941Smrg /* Attempting to transfer derived image to surface */ 521b8e80941Smrg mtx_unlock(&drv->mutex); 522b8e80941Smrg return VA_STATUS_ERROR_UNIMPLEMENTED; 523b8e80941Smrg } 524b8e80941Smrg 525b8e80941Smrg format = VaFourccToPipeFormat(vaimage->format.fourcc); 526b8e80941Smrg 527b8e80941Smrg if (format == PIPE_FORMAT_NONE) { 528b8e80941Smrg mtx_unlock(&drv->mutex); 529b8e80941Smrg return VA_STATUS_ERROR_OPERATION_FAILED; 530b8e80941Smrg } 531b8e80941Smrg 532b8e80941Smrg if ((format != surf->buffer->buffer_format) && 533b8e80941Smrg ((format != PIPE_FORMAT_YV12) || (surf->buffer->buffer_format != PIPE_FORMAT_NV12)) && 534b8e80941Smrg ((format != PIPE_FORMAT_IYUV) || (surf->buffer->buffer_format != PIPE_FORMAT_NV12))) { 535b8e80941Smrg struct pipe_video_buffer *tmp_buf; 536b8e80941Smrg 537b8e80941Smrg surf->templat.buffer_format = format; 538b8e80941Smrg if (format == PIPE_FORMAT_YUYV || format == PIPE_FORMAT_UYVY || 539b8e80941Smrg format == PIPE_FORMAT_B8G8R8A8_UNORM || format == PIPE_FORMAT_B8G8R8X8_UNORM || 540b8e80941Smrg format == PIPE_FORMAT_R8G8B8A8_UNORM || format == PIPE_FORMAT_R8G8B8X8_UNORM) 541b8e80941Smrg surf->templat.interlaced = false; 542b8e80941Smrg tmp_buf = drv->pipe->create_video_buffer(drv->pipe, &surf->templat); 543b8e80941Smrg 544b8e80941Smrg if (!tmp_buf) { 545b8e80941Smrg mtx_unlock(&drv->mutex); 546b8e80941Smrg return VA_STATUS_ERROR_ALLOCATION_FAILED; 547b8e80941Smrg } 548b8e80941Smrg 549b8e80941Smrg surf->buffer->destroy(surf->buffer); 550b8e80941Smrg surf->buffer = tmp_buf; 551b8e80941Smrg } 552b8e80941Smrg 553b8e80941Smrg views = surf->buffer->get_sampler_view_planes(surf->buffer); 554b8e80941Smrg if (!views) { 555b8e80941Smrg mtx_unlock(&drv->mutex); 556b8e80941Smrg return VA_STATUS_ERROR_OPERATION_FAILED; 557b8e80941Smrg } 558b8e80941Smrg 559b8e80941Smrg for (i = 0; i < vaimage->num_planes; i++) { 560b8e80941Smrg data[i] = img_buf->data + vaimage->offsets[i]; 561b8e80941Smrg pitches[i] = vaimage->pitches[i]; 562b8e80941Smrg } 563b8e80941Smrg if (vaimage->format.fourcc == VA_FOURCC('I','4','2','0')) { 564b8e80941Smrg void *tmp_d; 565b8e80941Smrg unsigned tmp_p; 566b8e80941Smrg tmp_d = data[1]; 567b8e80941Smrg data[1] = data[2]; 568b8e80941Smrg data[2] = tmp_d; 569b8e80941Smrg tmp_p = pitches[1]; 570b8e80941Smrg pitches[1] = pitches[2]; 571b8e80941Smrg pitches[2] = tmp_p; 572b8e80941Smrg } 573b8e80941Smrg 574b8e80941Smrg for (i = 0; i < vaimage->num_planes; ++i) { 575b8e80941Smrg unsigned width, height; 576b8e80941Smrg struct pipe_resource *tex; 577b8e80941Smrg 578b8e80941Smrg if (!views[i]) continue; 579b8e80941Smrg tex = views[i]->texture; 580b8e80941Smrg 581b8e80941Smrg vlVaVideoSurfaceSize(surf, i, &width, &height); 582b8e80941Smrg for (j = 0; j < tex->array_size; ++j) { 583b8e80941Smrg struct pipe_box dst_box = {0, 0, j, width, height, 1}; 584b8e80941Smrg 585b8e80941Smrg if (((format == PIPE_FORMAT_YV12) || (format == PIPE_FORMAT_IYUV)) 586b8e80941Smrg && (surf->buffer->buffer_format == PIPE_FORMAT_NV12) 587b8e80941Smrg && i == 1) { 588b8e80941Smrg struct pipe_transfer *transfer = NULL; 589b8e80941Smrg uint8_t *map = NULL; 590b8e80941Smrg 591b8e80941Smrg map = drv->pipe->transfer_map(drv->pipe, 592b8e80941Smrg tex, 593b8e80941Smrg 0, 594b8e80941Smrg PIPE_TRANSFER_WRITE | 595b8e80941Smrg PIPE_TRANSFER_DISCARD_RANGE, 596b8e80941Smrg &dst_box, &transfer); 597b8e80941Smrg if (map == NULL) { 598b8e80941Smrg mtx_unlock(&drv->mutex); 599b8e80941Smrg return VA_STATUS_ERROR_OPERATION_FAILED; 600b8e80941Smrg } 601b8e80941Smrg 602b8e80941Smrg u_copy_nv12_from_yv12((const void * const*) data, pitches, i, j, 603b8e80941Smrg transfer->stride, tex->array_size, 604b8e80941Smrg map, dst_box.width, dst_box.height); 605b8e80941Smrg pipe_transfer_unmap(drv->pipe, transfer); 606b8e80941Smrg } else { 607b8e80941Smrg drv->pipe->texture_subdata(drv->pipe, tex, 0, 608b8e80941Smrg PIPE_TRANSFER_WRITE, &dst_box, 609b8e80941Smrg data[i] + pitches[i] * j, 610b8e80941Smrg pitches[i] * views[i]->texture->array_size, 0); 611b8e80941Smrg } 612b8e80941Smrg } 613b8e80941Smrg } 614b8e80941Smrg mtx_unlock(&drv->mutex); 615b8e80941Smrg 616b8e80941Smrg return VA_STATUS_SUCCESS; 617b8e80941Smrg} 618