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#include "pipe/p_video_codec.h" 31b8e80941Smrg 32b8e80941Smrg#include "state_tracker/drm_driver.h" 33b8e80941Smrg 34b8e80941Smrg#include "util/u_memory.h" 35b8e80941Smrg#include "util/u_handle_table.h" 36b8e80941Smrg#include "util/u_rect.h" 37b8e80941Smrg#include "util/u_sampler.h" 38b8e80941Smrg#include "util/u_surface.h" 39b8e80941Smrg#include "util/u_video.h" 40b8e80941Smrg 41b8e80941Smrg#include "vl/vl_compositor.h" 42b8e80941Smrg#include "vl/vl_video_buffer.h" 43b8e80941Smrg#include "vl/vl_winsys.h" 44b8e80941Smrg 45b8e80941Smrg#include "va_private.h" 46b8e80941Smrg 47b8e80941Smrg#include <va/va_drmcommon.h> 48b8e80941Smrg#include "drm-uapi/drm_fourcc.h" 49b8e80941Smrg 50b8e80941Smrgstatic const enum pipe_format vpp_surface_formats[] = { 51b8e80941Smrg PIPE_FORMAT_B8G8R8A8_UNORM, PIPE_FORMAT_R8G8B8A8_UNORM, 52b8e80941Smrg PIPE_FORMAT_B8G8R8X8_UNORM, PIPE_FORMAT_R8G8B8X8_UNORM 53b8e80941Smrg}; 54b8e80941Smrg 55b8e80941SmrgVAStatus 56b8e80941SmrgvlVaCreateSurfaces(VADriverContextP ctx, int width, int height, int format, 57b8e80941Smrg int num_surfaces, VASurfaceID *surfaces) 58b8e80941Smrg{ 59b8e80941Smrg return vlVaCreateSurfaces2(ctx, format, width, height, surfaces, num_surfaces, 60b8e80941Smrg NULL, 0); 61b8e80941Smrg} 62b8e80941Smrg 63b8e80941SmrgVAStatus 64b8e80941SmrgvlVaDestroySurfaces(VADriverContextP ctx, VASurfaceID *surface_list, int num_surfaces) 65b8e80941Smrg{ 66b8e80941Smrg vlVaDriver *drv; 67b8e80941Smrg int i; 68b8e80941Smrg 69b8e80941Smrg if (!ctx) 70b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 71b8e80941Smrg 72b8e80941Smrg drv = VL_VA_DRIVER(ctx); 73b8e80941Smrg mtx_lock(&drv->mutex); 74b8e80941Smrg for (i = 0; i < num_surfaces; ++i) { 75b8e80941Smrg vlVaSurface *surf = handle_table_get(drv->htab, surface_list[i]); 76b8e80941Smrg if (!surf) { 77b8e80941Smrg mtx_unlock(&drv->mutex); 78b8e80941Smrg return VA_STATUS_ERROR_INVALID_SURFACE; 79b8e80941Smrg } 80b8e80941Smrg if (surf->buffer) 81b8e80941Smrg surf->buffer->destroy(surf->buffer); 82b8e80941Smrg util_dynarray_fini(&surf->subpics); 83b8e80941Smrg FREE(surf); 84b8e80941Smrg handle_table_remove(drv->htab, surface_list[i]); 85b8e80941Smrg } 86b8e80941Smrg mtx_unlock(&drv->mutex); 87b8e80941Smrg 88b8e80941Smrg return VA_STATUS_SUCCESS; 89b8e80941Smrg} 90b8e80941Smrg 91b8e80941SmrgVAStatus 92b8e80941SmrgvlVaSyncSurface(VADriverContextP ctx, VASurfaceID render_target) 93b8e80941Smrg{ 94b8e80941Smrg vlVaDriver *drv; 95b8e80941Smrg vlVaContext *context; 96b8e80941Smrg vlVaSurface *surf; 97b8e80941Smrg 98b8e80941Smrg if (!ctx) 99b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 100b8e80941Smrg 101b8e80941Smrg drv = VL_VA_DRIVER(ctx); 102b8e80941Smrg if (!drv) 103b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 104b8e80941Smrg 105b8e80941Smrg mtx_lock(&drv->mutex); 106b8e80941Smrg surf = handle_table_get(drv->htab, render_target); 107b8e80941Smrg 108b8e80941Smrg if (!surf || !surf->buffer) { 109b8e80941Smrg mtx_unlock(&drv->mutex); 110b8e80941Smrg return VA_STATUS_ERROR_INVALID_SURFACE; 111b8e80941Smrg } 112b8e80941Smrg 113b8e80941Smrg if (!surf->feedback) { 114b8e80941Smrg // No outstanding operation: nothing to do. 115b8e80941Smrg mtx_unlock(&drv->mutex); 116b8e80941Smrg return VA_STATUS_SUCCESS; 117b8e80941Smrg } 118b8e80941Smrg 119b8e80941Smrg context = handle_table_get(drv->htab, surf->ctx); 120b8e80941Smrg if (!context) { 121b8e80941Smrg mtx_unlock(&drv->mutex); 122b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 123b8e80941Smrg } 124b8e80941Smrg 125b8e80941Smrg if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) { 126b8e80941Smrg if (u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC) { 127b8e80941Smrg int frame_diff; 128b8e80941Smrg if (context->desc.h264enc.frame_num_cnt >= surf->frame_num_cnt) 129b8e80941Smrg frame_diff = context->desc.h264enc.frame_num_cnt - surf->frame_num_cnt; 130b8e80941Smrg else 131b8e80941Smrg frame_diff = 0xFFFFFFFF - surf->frame_num_cnt + 1 + context->desc.h264enc.frame_num_cnt; 132b8e80941Smrg if ((frame_diff == 0) && 133b8e80941Smrg (surf->force_flushed == false) && 134b8e80941Smrg (context->desc.h264enc.frame_num_cnt % 2 != 0)) { 135b8e80941Smrg context->decoder->flush(context->decoder); 136b8e80941Smrg context->first_single_submitted = true; 137b8e80941Smrg } 138b8e80941Smrg } 139b8e80941Smrg context->decoder->get_feedback(context->decoder, surf->feedback, &(surf->coded_buf->coded_size)); 140b8e80941Smrg surf->feedback = NULL; 141b8e80941Smrg } 142b8e80941Smrg mtx_unlock(&drv->mutex); 143b8e80941Smrg return VA_STATUS_SUCCESS; 144b8e80941Smrg} 145b8e80941Smrg 146b8e80941SmrgVAStatus 147b8e80941SmrgvlVaQuerySurfaceStatus(VADriverContextP ctx, VASurfaceID render_target, VASurfaceStatus *status) 148b8e80941Smrg{ 149b8e80941Smrg vlVaDriver *drv; 150b8e80941Smrg vlVaSurface *surf; 151b8e80941Smrg vlVaContext *context; 152b8e80941Smrg 153b8e80941Smrg if (!ctx) 154b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 155b8e80941Smrg 156b8e80941Smrg drv = VL_VA_DRIVER(ctx); 157b8e80941Smrg if (!drv) 158b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 159b8e80941Smrg 160b8e80941Smrg mtx_lock(&drv->mutex); 161b8e80941Smrg 162b8e80941Smrg surf = handle_table_get(drv->htab, render_target); 163b8e80941Smrg if (!surf || !surf->buffer) { 164b8e80941Smrg mtx_unlock(&drv->mutex); 165b8e80941Smrg return VA_STATUS_ERROR_INVALID_SURFACE; 166b8e80941Smrg } 167b8e80941Smrg 168b8e80941Smrg context = handle_table_get(drv->htab, surf->ctx); 169b8e80941Smrg if (!context) { 170b8e80941Smrg mtx_unlock(&drv->mutex); 171b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 172b8e80941Smrg } 173b8e80941Smrg 174b8e80941Smrg if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) { 175b8e80941Smrg if(surf->feedback == NULL) 176b8e80941Smrg *status=VASurfaceReady; 177b8e80941Smrg else 178b8e80941Smrg *status=VASurfaceRendering; 179b8e80941Smrg } 180b8e80941Smrg 181b8e80941Smrg mtx_unlock(&drv->mutex); 182b8e80941Smrg 183b8e80941Smrg return VA_STATUS_SUCCESS; 184b8e80941Smrg} 185b8e80941Smrg 186b8e80941SmrgVAStatus 187b8e80941SmrgvlVaQuerySurfaceError(VADriverContextP ctx, VASurfaceID render_target, VAStatus error_status, void **error_info) 188b8e80941Smrg{ 189b8e80941Smrg if (!ctx) 190b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 191b8e80941Smrg 192b8e80941Smrg return VA_STATUS_ERROR_UNIMPLEMENTED; 193b8e80941Smrg} 194b8e80941Smrg 195b8e80941Smrgstatic void 196b8e80941Smrgupload_sampler(struct pipe_context *pipe, struct pipe_sampler_view *dst, 197b8e80941Smrg const struct pipe_box *dst_box, const void *src, unsigned src_stride, 198b8e80941Smrg unsigned src_x, unsigned src_y) 199b8e80941Smrg{ 200b8e80941Smrg struct pipe_transfer *transfer; 201b8e80941Smrg void *map; 202b8e80941Smrg 203b8e80941Smrg map = pipe->transfer_map(pipe, dst->texture, 0, PIPE_TRANSFER_WRITE, 204b8e80941Smrg dst_box, &transfer); 205b8e80941Smrg if (!map) 206b8e80941Smrg return; 207b8e80941Smrg 208b8e80941Smrg util_copy_rect(map, dst->texture->format, transfer->stride, 0, 0, 209b8e80941Smrg dst_box->width, dst_box->height, 210b8e80941Smrg src, src_stride, src_x, src_y); 211b8e80941Smrg 212b8e80941Smrg pipe->transfer_unmap(pipe, transfer); 213b8e80941Smrg} 214b8e80941Smrg 215b8e80941Smrgstatic VAStatus 216b8e80941SmrgvlVaPutSubpictures(vlVaSurface *surf, vlVaDriver *drv, 217b8e80941Smrg struct pipe_surface *surf_draw, struct u_rect *dirty_area, 218b8e80941Smrg struct u_rect *src_rect, struct u_rect *dst_rect) 219b8e80941Smrg{ 220b8e80941Smrg vlVaSubpicture *sub; 221b8e80941Smrg int i; 222b8e80941Smrg 223b8e80941Smrg if (!(surf->subpics.data || surf->subpics.size)) 224b8e80941Smrg return VA_STATUS_SUCCESS; 225b8e80941Smrg 226b8e80941Smrg for (i = 0; i < surf->subpics.size/sizeof(vlVaSubpicture *); i++) { 227b8e80941Smrg struct pipe_blend_state blend; 228b8e80941Smrg void *blend_state; 229b8e80941Smrg vlVaBuffer *buf; 230b8e80941Smrg struct pipe_box box; 231b8e80941Smrg struct u_rect *s, *d, sr, dr, c; 232b8e80941Smrg int sw, sh, dw, dh; 233b8e80941Smrg 234b8e80941Smrg sub = ((vlVaSubpicture **)surf->subpics.data)[i]; 235b8e80941Smrg if (!sub) 236b8e80941Smrg continue; 237b8e80941Smrg 238b8e80941Smrg buf = handle_table_get(drv->htab, sub->image->buf); 239b8e80941Smrg if (!buf) 240b8e80941Smrg return VA_STATUS_ERROR_INVALID_IMAGE; 241b8e80941Smrg 242b8e80941Smrg box.x = 0; 243b8e80941Smrg box.y = 0; 244b8e80941Smrg box.z = 0; 245b8e80941Smrg box.width = sub->dst_rect.x1 - sub->dst_rect.x0; 246b8e80941Smrg box.height = sub->dst_rect.y1 - sub->dst_rect.y0; 247b8e80941Smrg box.depth = 1; 248b8e80941Smrg 249b8e80941Smrg s = &sub->src_rect; 250b8e80941Smrg d = &sub->dst_rect; 251b8e80941Smrg sw = s->x1 - s->x0; 252b8e80941Smrg sh = s->y1 - s->y0; 253b8e80941Smrg dw = d->x1 - d->x0; 254b8e80941Smrg dh = d->y1 - d->y0; 255b8e80941Smrg c.x0 = MAX2(d->x0, s->x0); 256b8e80941Smrg c.y0 = MAX2(d->y0, s->y0); 257b8e80941Smrg c.x1 = MIN2(d->x0 + dw, src_rect->x1); 258b8e80941Smrg c.y1 = MIN2(d->y0 + dh, src_rect->y1); 259b8e80941Smrg sr.x0 = s->x0 + (c.x0 - d->x0)*(sw/(float)dw); 260b8e80941Smrg sr.y0 = s->y0 + (c.y0 - d->y0)*(sh/(float)dh); 261b8e80941Smrg sr.x1 = s->x0 + (c.x1 - d->x0)*(sw/(float)dw); 262b8e80941Smrg sr.y1 = s->y0 + (c.y1 - d->y0)*(sh/(float)dh); 263b8e80941Smrg 264b8e80941Smrg s = src_rect; 265b8e80941Smrg d = dst_rect; 266b8e80941Smrg sw = s->x1 - s->x0; 267b8e80941Smrg sh = s->y1 - s->y0; 268b8e80941Smrg dw = d->x1 - d->x0; 269b8e80941Smrg dh = d->y1 - d->y0; 270b8e80941Smrg dr.x0 = d->x0 + c.x0*(dw/(float)sw); 271b8e80941Smrg dr.y0 = d->y0 + c.y0*(dh/(float)sh); 272b8e80941Smrg dr.x1 = d->x0 + c.x1*(dw/(float)sw); 273b8e80941Smrg dr.y1 = d->y0 + c.y1*(dh/(float)sh); 274b8e80941Smrg 275b8e80941Smrg memset(&blend, 0, sizeof(blend)); 276b8e80941Smrg blend.independent_blend_enable = 0; 277b8e80941Smrg blend.rt[0].blend_enable = 1; 278b8e80941Smrg blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA; 279b8e80941Smrg blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; 280b8e80941Smrg blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO; 281b8e80941Smrg blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; 282b8e80941Smrg blend.rt[0].rgb_func = PIPE_BLEND_ADD; 283b8e80941Smrg blend.rt[0].alpha_func = PIPE_BLEND_ADD; 284b8e80941Smrg blend.rt[0].colormask = PIPE_MASK_RGBA; 285b8e80941Smrg blend.logicop_enable = 0; 286b8e80941Smrg blend.logicop_func = PIPE_LOGICOP_CLEAR; 287b8e80941Smrg blend.dither = 0; 288b8e80941Smrg blend_state = drv->pipe->create_blend_state(drv->pipe, &blend); 289b8e80941Smrg 290b8e80941Smrg vl_compositor_clear_layers(&drv->cstate); 291b8e80941Smrg vl_compositor_set_layer_blend(&drv->cstate, 0, blend_state, false); 292b8e80941Smrg upload_sampler(drv->pipe, sub->sampler, &box, buf->data, 293b8e80941Smrg sub->image->pitches[0], 0, 0); 294b8e80941Smrg vl_compositor_set_rgba_layer(&drv->cstate, &drv->compositor, 0, sub->sampler, 295b8e80941Smrg &sr, NULL, NULL); 296b8e80941Smrg vl_compositor_set_layer_dst_area(&drv->cstate, 0, &dr); 297b8e80941Smrg vl_compositor_render(&drv->cstate, &drv->compositor, surf_draw, dirty_area, false); 298b8e80941Smrg drv->pipe->delete_blend_state(drv->pipe, blend_state); 299b8e80941Smrg } 300b8e80941Smrg 301b8e80941Smrg return VA_STATUS_SUCCESS; 302b8e80941Smrg} 303b8e80941Smrg 304b8e80941SmrgVAStatus 305b8e80941SmrgvlVaPutSurface(VADriverContextP ctx, VASurfaceID surface_id, void* draw, short srcx, short srcy, 306b8e80941Smrg unsigned short srcw, unsigned short srch, short destx, short desty, 307b8e80941Smrg unsigned short destw, unsigned short desth, VARectangle *cliprects, 308b8e80941Smrg unsigned int number_cliprects, unsigned int flags) 309b8e80941Smrg{ 310b8e80941Smrg vlVaDriver *drv; 311b8e80941Smrg vlVaSurface *surf; 312b8e80941Smrg struct pipe_screen *screen; 313b8e80941Smrg struct pipe_resource *tex; 314b8e80941Smrg struct pipe_surface surf_templ, *surf_draw; 315b8e80941Smrg struct vl_screen *vscreen; 316b8e80941Smrg struct u_rect src_rect, *dirty_area; 317b8e80941Smrg struct u_rect dst_rect = {destx, destx + destw, desty, desty + desth}; 318b8e80941Smrg enum pipe_format format; 319b8e80941Smrg VAStatus status; 320b8e80941Smrg 321b8e80941Smrg if (!ctx) 322b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 323b8e80941Smrg 324b8e80941Smrg drv = VL_VA_DRIVER(ctx); 325b8e80941Smrg mtx_lock(&drv->mutex); 326b8e80941Smrg surf = handle_table_get(drv->htab, surface_id); 327b8e80941Smrg if (!surf) { 328b8e80941Smrg mtx_unlock(&drv->mutex); 329b8e80941Smrg return VA_STATUS_ERROR_INVALID_SURFACE; 330b8e80941Smrg } 331b8e80941Smrg 332b8e80941Smrg screen = drv->pipe->screen; 333b8e80941Smrg vscreen = drv->vscreen; 334b8e80941Smrg 335b8e80941Smrg tex = vscreen->texture_from_drawable(vscreen, draw); 336b8e80941Smrg if (!tex) { 337b8e80941Smrg mtx_unlock(&drv->mutex); 338b8e80941Smrg return VA_STATUS_ERROR_INVALID_DISPLAY; 339b8e80941Smrg } 340b8e80941Smrg 341b8e80941Smrg dirty_area = vscreen->get_dirty_area(vscreen); 342b8e80941Smrg 343b8e80941Smrg memset(&surf_templ, 0, sizeof(surf_templ)); 344b8e80941Smrg surf_templ.format = tex->format; 345b8e80941Smrg surf_draw = drv->pipe->create_surface(drv->pipe, tex, &surf_templ); 346b8e80941Smrg if (!surf_draw) { 347b8e80941Smrg pipe_resource_reference(&tex, NULL); 348b8e80941Smrg mtx_unlock(&drv->mutex); 349b8e80941Smrg return VA_STATUS_ERROR_INVALID_DISPLAY; 350b8e80941Smrg } 351b8e80941Smrg 352b8e80941Smrg src_rect.x0 = srcx; 353b8e80941Smrg src_rect.y0 = srcy; 354b8e80941Smrg src_rect.x1 = srcw + srcx; 355b8e80941Smrg src_rect.y1 = srch + srcy; 356b8e80941Smrg 357b8e80941Smrg format = surf->buffer->buffer_format; 358b8e80941Smrg 359b8e80941Smrg vl_compositor_clear_layers(&drv->cstate); 360b8e80941Smrg 361b8e80941Smrg if (format == PIPE_FORMAT_B8G8R8A8_UNORM || format == PIPE_FORMAT_B8G8R8X8_UNORM || 362b8e80941Smrg format == PIPE_FORMAT_R8G8B8A8_UNORM || format == PIPE_FORMAT_R8G8B8X8_UNORM) { 363b8e80941Smrg struct pipe_sampler_view **views; 364b8e80941Smrg 365b8e80941Smrg views = surf->buffer->get_sampler_view_planes(surf->buffer); 366b8e80941Smrg vl_compositor_set_rgba_layer(&drv->cstate, &drv->compositor, 0, views[0], &src_rect, NULL, NULL); 367b8e80941Smrg } else 368b8e80941Smrg vl_compositor_set_buffer_layer(&drv->cstate, &drv->compositor, 0, surf->buffer, &src_rect, NULL, VL_COMPOSITOR_WEAVE); 369b8e80941Smrg 370b8e80941Smrg vl_compositor_set_layer_dst_area(&drv->cstate, 0, &dst_rect); 371b8e80941Smrg vl_compositor_render(&drv->cstate, &drv->compositor, surf_draw, dirty_area, true); 372b8e80941Smrg 373b8e80941Smrg status = vlVaPutSubpictures(surf, drv, surf_draw, dirty_area, &src_rect, &dst_rect); 374b8e80941Smrg if (status) { 375b8e80941Smrg mtx_unlock(&drv->mutex); 376b8e80941Smrg return status; 377b8e80941Smrg } 378b8e80941Smrg 379b8e80941Smrg /* flush before calling flush_frontbuffer so that rendering is flushed 380b8e80941Smrg * to back buffer so the texture can be copied in flush_frontbuffer 381b8e80941Smrg */ 382b8e80941Smrg drv->pipe->flush(drv->pipe, NULL, 0); 383b8e80941Smrg 384b8e80941Smrg screen->flush_frontbuffer(screen, tex, 0, 0, 385b8e80941Smrg vscreen->get_private(vscreen), NULL); 386b8e80941Smrg 387b8e80941Smrg 388b8e80941Smrg pipe_resource_reference(&tex, NULL); 389b8e80941Smrg pipe_surface_reference(&surf_draw, NULL); 390b8e80941Smrg mtx_unlock(&drv->mutex); 391b8e80941Smrg 392b8e80941Smrg return VA_STATUS_SUCCESS; 393b8e80941Smrg} 394b8e80941Smrg 395b8e80941SmrgVAStatus 396b8e80941SmrgvlVaLockSurface(VADriverContextP ctx, VASurfaceID surface, unsigned int *fourcc, 397b8e80941Smrg unsigned int *luma_stride, unsigned int *chroma_u_stride, unsigned int *chroma_v_stride, 398b8e80941Smrg unsigned int *luma_offset, unsigned int *chroma_u_offset, unsigned int *chroma_v_offset, 399b8e80941Smrg unsigned int *buffer_name, void **buffer) 400b8e80941Smrg{ 401b8e80941Smrg if (!ctx) 402b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 403b8e80941Smrg 404b8e80941Smrg return VA_STATUS_ERROR_UNIMPLEMENTED; 405b8e80941Smrg} 406b8e80941Smrg 407b8e80941SmrgVAStatus 408b8e80941SmrgvlVaUnlockSurface(VADriverContextP ctx, VASurfaceID surface) 409b8e80941Smrg{ 410b8e80941Smrg if (!ctx) 411b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 412b8e80941Smrg 413b8e80941Smrg return VA_STATUS_ERROR_UNIMPLEMENTED; 414b8e80941Smrg} 415b8e80941Smrg 416b8e80941SmrgVAStatus 417b8e80941SmrgvlVaQuerySurfaceAttributes(VADriverContextP ctx, VAConfigID config_id, 418b8e80941Smrg VASurfaceAttrib *attrib_list, unsigned int *num_attribs) 419b8e80941Smrg{ 420b8e80941Smrg vlVaDriver *drv; 421b8e80941Smrg vlVaConfig *config; 422b8e80941Smrg VASurfaceAttrib *attribs; 423b8e80941Smrg struct pipe_screen *pscreen; 424b8e80941Smrg int i, j; 425b8e80941Smrg 426b8e80941Smrg STATIC_ASSERT(ARRAY_SIZE(vpp_surface_formats) <= VL_VA_MAX_IMAGE_FORMATS); 427b8e80941Smrg 428b8e80941Smrg if (config_id == VA_INVALID_ID) 429b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONFIG; 430b8e80941Smrg 431b8e80941Smrg if (!attrib_list && !num_attribs) 432b8e80941Smrg return VA_STATUS_ERROR_INVALID_PARAMETER; 433b8e80941Smrg 434b8e80941Smrg if (!attrib_list) { 435b8e80941Smrg *num_attribs = VL_VA_MAX_IMAGE_FORMATS + VASurfaceAttribCount; 436b8e80941Smrg return VA_STATUS_SUCCESS; 437b8e80941Smrg } 438b8e80941Smrg 439b8e80941Smrg if (!ctx) 440b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 441b8e80941Smrg 442b8e80941Smrg drv = VL_VA_DRIVER(ctx); 443b8e80941Smrg 444b8e80941Smrg if (!drv) 445b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 446b8e80941Smrg 447b8e80941Smrg mtx_lock(&drv->mutex); 448b8e80941Smrg config = handle_table_get(drv->htab, config_id); 449b8e80941Smrg mtx_unlock(&drv->mutex); 450b8e80941Smrg 451b8e80941Smrg if (!config) 452b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONFIG; 453b8e80941Smrg 454b8e80941Smrg pscreen = VL_VA_PSCREEN(ctx); 455b8e80941Smrg 456b8e80941Smrg if (!pscreen) 457b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 458b8e80941Smrg 459b8e80941Smrg attribs = CALLOC(VL_VA_MAX_IMAGE_FORMATS + VASurfaceAttribCount, 460b8e80941Smrg sizeof(VASurfaceAttrib)); 461b8e80941Smrg 462b8e80941Smrg if (!attribs) 463b8e80941Smrg return VA_STATUS_ERROR_ALLOCATION_FAILED; 464b8e80941Smrg 465b8e80941Smrg i = 0; 466b8e80941Smrg 467b8e80941Smrg /* vlVaCreateConfig returns PIPE_VIDEO_PROFILE_UNKNOWN 468b8e80941Smrg * only for VAEntrypointVideoProc. */ 469b8e80941Smrg if (config->profile == PIPE_VIDEO_PROFILE_UNKNOWN) { 470b8e80941Smrg if (config->rt_format & VA_RT_FORMAT_RGB32) { 471b8e80941Smrg for (j = 0; j < ARRAY_SIZE(vpp_surface_formats); ++j) { 472b8e80941Smrg attribs[i].type = VASurfaceAttribPixelFormat; 473b8e80941Smrg attribs[i].value.type = VAGenericValueTypeInteger; 474b8e80941Smrg attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE; 475b8e80941Smrg attribs[i].value.value.i = PipeFormatToVaFourcc(vpp_surface_formats[j]); 476b8e80941Smrg i++; 477b8e80941Smrg } 478b8e80941Smrg } 479b8e80941Smrg } 480b8e80941Smrg if (config->rt_format & VA_RT_FORMAT_YUV420) { 481b8e80941Smrg attribs[i].type = VASurfaceAttribPixelFormat; 482b8e80941Smrg attribs[i].value.type = VAGenericValueTypeInteger; 483b8e80941Smrg attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE; 484b8e80941Smrg attribs[i].value.value.i = VA_FOURCC_NV12; 485b8e80941Smrg i++; 486b8e80941Smrg } 487b8e80941Smrg if (config->rt_format & VA_RT_FORMAT_YUV420_10BPP) { 488b8e80941Smrg attribs[i].type = VASurfaceAttribPixelFormat; 489b8e80941Smrg attribs[i].value.type = VAGenericValueTypeInteger; 490b8e80941Smrg attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE; 491b8e80941Smrg attribs[i].value.value.i = VA_FOURCC_P010; 492b8e80941Smrg i++; 493b8e80941Smrg attribs[i].type = VASurfaceAttribPixelFormat; 494b8e80941Smrg attribs[i].value.type = VAGenericValueTypeInteger; 495b8e80941Smrg attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE; 496b8e80941Smrg attribs[i].value.value.i = VA_FOURCC_P016; 497b8e80941Smrg i++; 498b8e80941Smrg } 499b8e80941Smrg 500b8e80941Smrg attribs[i].type = VASurfaceAttribMemoryType; 501b8e80941Smrg attribs[i].value.type = VAGenericValueTypeInteger; 502b8e80941Smrg attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE; 503b8e80941Smrg attribs[i].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_VA | 504b8e80941Smrg VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME; 505b8e80941Smrg i++; 506b8e80941Smrg 507b8e80941Smrg attribs[i].type = VASurfaceAttribExternalBufferDescriptor; 508b8e80941Smrg attribs[i].value.type = VAGenericValueTypePointer; 509b8e80941Smrg attribs[i].flags = VA_SURFACE_ATTRIB_SETTABLE; 510b8e80941Smrg attribs[i].value.value.p = NULL; /* ignore */ 511b8e80941Smrg i++; 512b8e80941Smrg 513b8e80941Smrg if (config->entrypoint != PIPE_VIDEO_ENTRYPOINT_UNKNOWN) { 514b8e80941Smrg attribs[i].type = VASurfaceAttribMaxWidth; 515b8e80941Smrg attribs[i].value.type = VAGenericValueTypeInteger; 516b8e80941Smrg attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE; 517b8e80941Smrg attribs[i].value.value.i = 518b8e80941Smrg pscreen->get_video_param(pscreen, 519b8e80941Smrg config->profile, config->entrypoint, 520b8e80941Smrg PIPE_VIDEO_CAP_MAX_WIDTH); 521b8e80941Smrg i++; 522b8e80941Smrg 523b8e80941Smrg attribs[i].type = VASurfaceAttribMaxHeight; 524b8e80941Smrg attribs[i].value.type = VAGenericValueTypeInteger; 525b8e80941Smrg attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE; 526b8e80941Smrg attribs[i].value.value.i = 527b8e80941Smrg pscreen->get_video_param(pscreen, 528b8e80941Smrg config->profile, config->entrypoint, 529b8e80941Smrg PIPE_VIDEO_CAP_MAX_HEIGHT); 530b8e80941Smrg i++; 531b8e80941Smrg } else { 532b8e80941Smrg attribs[i].type = VASurfaceAttribMaxWidth; 533b8e80941Smrg attribs[i].value.type = VAGenericValueTypeInteger; 534b8e80941Smrg attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE; 535b8e80941Smrg attribs[i].value.value.i = vl_video_buffer_max_size(pscreen); 536b8e80941Smrg i++; 537b8e80941Smrg 538b8e80941Smrg attribs[i].type = VASurfaceAttribMaxHeight; 539b8e80941Smrg attribs[i].value.type = VAGenericValueTypeInteger; 540b8e80941Smrg attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE; 541b8e80941Smrg attribs[i].value.value.i = vl_video_buffer_max_size(pscreen); 542b8e80941Smrg i++; 543b8e80941Smrg } 544b8e80941Smrg 545b8e80941Smrg if (i > *num_attribs) { 546b8e80941Smrg *num_attribs = i; 547b8e80941Smrg FREE(attribs); 548b8e80941Smrg return VA_STATUS_ERROR_MAX_NUM_EXCEEDED; 549b8e80941Smrg } 550b8e80941Smrg 551b8e80941Smrg *num_attribs = i; 552b8e80941Smrg memcpy(attrib_list, attribs, i * sizeof(VASurfaceAttrib)); 553b8e80941Smrg FREE(attribs); 554b8e80941Smrg 555b8e80941Smrg return VA_STATUS_SUCCESS; 556b8e80941Smrg} 557b8e80941Smrg 558b8e80941Smrgstatic VAStatus 559b8e80941Smrgsurface_from_external_memory(VADriverContextP ctx, vlVaSurface *surface, 560b8e80941Smrg VASurfaceAttribExternalBuffers *memory_attribute, 561b8e80941Smrg unsigned index, struct pipe_video_buffer *templat) 562b8e80941Smrg{ 563b8e80941Smrg vlVaDriver *drv; 564b8e80941Smrg struct pipe_screen *pscreen; 565b8e80941Smrg struct pipe_resource res_templ; 566b8e80941Smrg struct winsys_handle whandle; 567b8e80941Smrg struct pipe_resource *resources[VL_NUM_COMPONENTS]; 568b8e80941Smrg const enum pipe_format *resource_formats = NULL; 569b8e80941Smrg VAStatus result; 570b8e80941Smrg int i; 571b8e80941Smrg 572b8e80941Smrg pscreen = VL_VA_PSCREEN(ctx); 573b8e80941Smrg drv = VL_VA_DRIVER(ctx); 574b8e80941Smrg 575b8e80941Smrg if (!memory_attribute || !memory_attribute->buffers || 576b8e80941Smrg index > memory_attribute->num_buffers) 577b8e80941Smrg return VA_STATUS_ERROR_INVALID_PARAMETER; 578b8e80941Smrg 579b8e80941Smrg if (surface->templat.width != memory_attribute->width || 580b8e80941Smrg surface->templat.height != memory_attribute->height || 581b8e80941Smrg memory_attribute->num_planes < 1) 582b8e80941Smrg return VA_STATUS_ERROR_INVALID_PARAMETER; 583b8e80941Smrg 584b8e80941Smrg if (memory_attribute->num_planes > VL_NUM_COMPONENTS) 585b8e80941Smrg return VA_STATUS_ERROR_INVALID_PARAMETER; 586b8e80941Smrg 587b8e80941Smrg resource_formats = vl_video_buffer_formats(pscreen, templat->buffer_format); 588b8e80941Smrg if (!resource_formats) 589b8e80941Smrg return VA_STATUS_ERROR_INVALID_PARAMETER; 590b8e80941Smrg 591b8e80941Smrg memset(&res_templ, 0, sizeof(res_templ)); 592b8e80941Smrg res_templ.target = PIPE_TEXTURE_2D; 593b8e80941Smrg res_templ.last_level = 0; 594b8e80941Smrg res_templ.depth0 = 1; 595b8e80941Smrg res_templ.array_size = 1; 596b8e80941Smrg res_templ.width0 = memory_attribute->width; 597b8e80941Smrg res_templ.height0 = memory_attribute->height; 598b8e80941Smrg res_templ.bind = PIPE_BIND_SAMPLER_VIEW; 599b8e80941Smrg res_templ.usage = PIPE_USAGE_DEFAULT; 600b8e80941Smrg 601b8e80941Smrg memset(&whandle, 0, sizeof(struct winsys_handle)); 602b8e80941Smrg whandle.type = WINSYS_HANDLE_TYPE_FD; 603b8e80941Smrg whandle.handle = memory_attribute->buffers[index]; 604b8e80941Smrg 605b8e80941Smrg // Create a resource for each plane. 606b8e80941Smrg memset(resources, 0, sizeof resources); 607b8e80941Smrg for (i = 0; i < memory_attribute->num_planes; i++) { 608b8e80941Smrg res_templ.format = resource_formats[i]; 609b8e80941Smrg if (res_templ.format == PIPE_FORMAT_NONE) { 610b8e80941Smrg result = VA_STATUS_ERROR_INVALID_PARAMETER; 611b8e80941Smrg goto fail; 612b8e80941Smrg } 613b8e80941Smrg 614b8e80941Smrg whandle.stride = memory_attribute->pitches[i]; 615b8e80941Smrg whandle.offset = memory_attribute->offsets[i]; 616b8e80941Smrg resources[i] = pscreen->resource_from_handle(pscreen, &res_templ, &whandle, 617b8e80941Smrg PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE); 618b8e80941Smrg if (!resources[i]) { 619b8e80941Smrg result = VA_STATUS_ERROR_ALLOCATION_FAILED; 620b8e80941Smrg goto fail; 621b8e80941Smrg } 622b8e80941Smrg } 623b8e80941Smrg 624b8e80941Smrg surface->buffer = vl_video_buffer_create_ex2(drv->pipe, templat, resources); 625b8e80941Smrg if (!surface->buffer) { 626b8e80941Smrg result = VA_STATUS_ERROR_ALLOCATION_FAILED; 627b8e80941Smrg goto fail; 628b8e80941Smrg } 629b8e80941Smrg return VA_STATUS_SUCCESS; 630b8e80941Smrg 631b8e80941Smrgfail: 632b8e80941Smrg for (i = 0; i < VL_NUM_COMPONENTS; i++) 633b8e80941Smrg pipe_resource_reference(&resources[i], NULL); 634b8e80941Smrg return result; 635b8e80941Smrg} 636b8e80941Smrg 637b8e80941SmrgVAStatus 638b8e80941SmrgvlVaHandleSurfaceAllocate(vlVaDriver *drv, vlVaSurface *surface, 639b8e80941Smrg struct pipe_video_buffer *templat) 640b8e80941Smrg{ 641b8e80941Smrg struct pipe_surface **surfaces; 642b8e80941Smrg unsigned i; 643b8e80941Smrg 644b8e80941Smrg surface->buffer = drv->pipe->create_video_buffer(drv->pipe, templat); 645b8e80941Smrg if (!surface->buffer) 646b8e80941Smrg return VA_STATUS_ERROR_ALLOCATION_FAILED; 647b8e80941Smrg 648b8e80941Smrg surfaces = surface->buffer->get_surfaces(surface->buffer); 649b8e80941Smrg for (i = 0; i < VL_MAX_SURFACES; ++i) { 650b8e80941Smrg union pipe_color_union c = {}; 651b8e80941Smrg 652b8e80941Smrg if (!surfaces[i]) 653b8e80941Smrg continue; 654b8e80941Smrg 655b8e80941Smrg if (i > !!surface->buffer->interlaced) 656b8e80941Smrg c.f[0] = c.f[1] = c.f[2] = c.f[3] = 0.5f; 657b8e80941Smrg 658b8e80941Smrg drv->pipe->clear_render_target(drv->pipe, surfaces[i], &c, 0, 0, 659b8e80941Smrg surfaces[i]->width, surfaces[i]->height, 660b8e80941Smrg false); 661b8e80941Smrg } 662b8e80941Smrg drv->pipe->flush(drv->pipe, NULL, 0); 663b8e80941Smrg 664b8e80941Smrg return VA_STATUS_SUCCESS; 665b8e80941Smrg} 666b8e80941Smrg 667b8e80941SmrgVAStatus 668b8e80941SmrgvlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format, 669b8e80941Smrg unsigned int width, unsigned int height, 670b8e80941Smrg VASurfaceID *surfaces, unsigned int num_surfaces, 671b8e80941Smrg VASurfaceAttrib *attrib_list, unsigned int num_attribs) 672b8e80941Smrg{ 673b8e80941Smrg vlVaDriver *drv; 674b8e80941Smrg VASurfaceAttribExternalBuffers *memory_attribute; 675b8e80941Smrg struct pipe_video_buffer templat; 676b8e80941Smrg struct pipe_screen *pscreen; 677b8e80941Smrg int i; 678b8e80941Smrg int memory_type; 679b8e80941Smrg int expected_fourcc; 680b8e80941Smrg VAStatus vaStatus; 681b8e80941Smrg vlVaSurface *surf; 682b8e80941Smrg 683b8e80941Smrg if (!ctx) 684b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 685b8e80941Smrg 686b8e80941Smrg if (!(width && height)) 687b8e80941Smrg return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT; 688b8e80941Smrg 689b8e80941Smrg drv = VL_VA_DRIVER(ctx); 690b8e80941Smrg 691b8e80941Smrg if (!drv) 692b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 693b8e80941Smrg 694b8e80941Smrg pscreen = VL_VA_PSCREEN(ctx); 695b8e80941Smrg 696b8e80941Smrg if (!pscreen) 697b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 698b8e80941Smrg 699b8e80941Smrg /* Default. */ 700b8e80941Smrg memory_attribute = NULL; 701b8e80941Smrg memory_type = VA_SURFACE_ATTRIB_MEM_TYPE_VA; 702b8e80941Smrg expected_fourcc = 0; 703b8e80941Smrg 704b8e80941Smrg for (i = 0; i < num_attribs && attrib_list; i++) { 705b8e80941Smrg if ((attrib_list[i].type == VASurfaceAttribPixelFormat) && 706b8e80941Smrg (attrib_list[i].flags & VA_SURFACE_ATTRIB_SETTABLE)) { 707b8e80941Smrg if (attrib_list[i].value.type != VAGenericValueTypeInteger) 708b8e80941Smrg return VA_STATUS_ERROR_INVALID_PARAMETER; 709b8e80941Smrg expected_fourcc = attrib_list[i].value.value.i; 710b8e80941Smrg } 711b8e80941Smrg 712b8e80941Smrg if ((attrib_list[i].type == VASurfaceAttribMemoryType) && 713b8e80941Smrg (attrib_list[i].flags & VA_SURFACE_ATTRIB_SETTABLE)) { 714b8e80941Smrg 715b8e80941Smrg if (attrib_list[i].value.type != VAGenericValueTypeInteger) 716b8e80941Smrg return VA_STATUS_ERROR_INVALID_PARAMETER; 717b8e80941Smrg 718b8e80941Smrg switch (attrib_list[i].value.value.i) { 719b8e80941Smrg case VA_SURFACE_ATTRIB_MEM_TYPE_VA: 720b8e80941Smrg case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: 721b8e80941Smrg memory_type = attrib_list[i].value.value.i; 722b8e80941Smrg break; 723b8e80941Smrg default: 724b8e80941Smrg return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE; 725b8e80941Smrg } 726b8e80941Smrg } 727b8e80941Smrg 728b8e80941Smrg if ((attrib_list[i].type == VASurfaceAttribExternalBufferDescriptor) && 729b8e80941Smrg (attrib_list[i].flags == VA_SURFACE_ATTRIB_SETTABLE)) { 730b8e80941Smrg if (attrib_list[i].value.type != VAGenericValueTypePointer) 731b8e80941Smrg return VA_STATUS_ERROR_INVALID_PARAMETER; 732b8e80941Smrg memory_attribute = (VASurfaceAttribExternalBuffers *)attrib_list[i].value.value.p; 733b8e80941Smrg } 734b8e80941Smrg } 735b8e80941Smrg 736b8e80941Smrg if (VA_RT_FORMAT_YUV420 != format && 737b8e80941Smrg VA_RT_FORMAT_YUV422 != format && 738b8e80941Smrg VA_RT_FORMAT_YUV444 != format && 739b8e80941Smrg VA_RT_FORMAT_YUV420_10BPP != format && 740b8e80941Smrg VA_RT_FORMAT_RGB32 != format) { 741b8e80941Smrg return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT; 742b8e80941Smrg } 743b8e80941Smrg 744b8e80941Smrg switch (memory_type) { 745b8e80941Smrg case VA_SURFACE_ATTRIB_MEM_TYPE_VA: 746b8e80941Smrg break; 747b8e80941Smrg case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: 748b8e80941Smrg if (!memory_attribute) 749b8e80941Smrg return VA_STATUS_ERROR_INVALID_PARAMETER; 750b8e80941Smrg 751b8e80941Smrg expected_fourcc = memory_attribute->pixel_format; 752b8e80941Smrg break; 753b8e80941Smrg default: 754b8e80941Smrg assert(0); 755b8e80941Smrg } 756b8e80941Smrg 757b8e80941Smrg memset(&templat, 0, sizeof(templat)); 758b8e80941Smrg 759b8e80941Smrg templat.buffer_format = pscreen->get_video_param( 760b8e80941Smrg pscreen, 761b8e80941Smrg PIPE_VIDEO_PROFILE_UNKNOWN, 762b8e80941Smrg PIPE_VIDEO_ENTRYPOINT_BITSTREAM, 763b8e80941Smrg PIPE_VIDEO_CAP_PREFERED_FORMAT 764b8e80941Smrg ); 765b8e80941Smrg templat.interlaced = pscreen->get_video_param( 766b8e80941Smrg pscreen, 767b8e80941Smrg PIPE_VIDEO_PROFILE_UNKNOWN, 768b8e80941Smrg PIPE_VIDEO_ENTRYPOINT_BITSTREAM, 769b8e80941Smrg PIPE_VIDEO_CAP_PREFERS_INTERLACED 770b8e80941Smrg ); 771b8e80941Smrg 772b8e80941Smrg if (expected_fourcc) { 773b8e80941Smrg enum pipe_format expected_format = VaFourccToPipeFormat(expected_fourcc); 774b8e80941Smrg 775b8e80941Smrg if (expected_format != templat.buffer_format || memory_attribute) 776b8e80941Smrg templat.interlaced = 0; 777b8e80941Smrg 778b8e80941Smrg templat.buffer_format = expected_format; 779b8e80941Smrg } 780b8e80941Smrg 781b8e80941Smrg templat.chroma_format = ChromaToPipe(format); 782b8e80941Smrg 783b8e80941Smrg templat.width = width; 784b8e80941Smrg templat.height = height; 785b8e80941Smrg 786b8e80941Smrg memset(surfaces, VA_INVALID_ID, num_surfaces * sizeof(VASurfaceID)); 787b8e80941Smrg 788b8e80941Smrg mtx_lock(&drv->mutex); 789b8e80941Smrg for (i = 0; i < num_surfaces; i++) { 790b8e80941Smrg surf = CALLOC(1, sizeof(vlVaSurface)); 791b8e80941Smrg if (!surf) { 792b8e80941Smrg vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; 793b8e80941Smrg goto no_res; 794b8e80941Smrg } 795b8e80941Smrg 796b8e80941Smrg surf->templat = templat; 797b8e80941Smrg 798b8e80941Smrg switch (memory_type) { 799b8e80941Smrg case VA_SURFACE_ATTRIB_MEM_TYPE_VA: 800b8e80941Smrg /* The application will clear the TILING flag when the surface is 801b8e80941Smrg * intended to be exported as dmabuf. Adding shared flag because not 802b8e80941Smrg * null memory_attribute means VASurfaceAttribExternalBuffers is used. 803b8e80941Smrg */ 804b8e80941Smrg if (memory_attribute && 805b8e80941Smrg !(memory_attribute->flags & VA_SURFACE_EXTBUF_DESC_ENABLE_TILING)) 806b8e80941Smrg templat.bind = PIPE_BIND_LINEAR | PIPE_BIND_SHARED; 807b8e80941Smrg 808b8e80941Smrg vaStatus = vlVaHandleSurfaceAllocate(drv, surf, &templat); 809b8e80941Smrg if (vaStatus != VA_STATUS_SUCCESS) 810b8e80941Smrg goto free_surf; 811b8e80941Smrg break; 812b8e80941Smrg 813b8e80941Smrg case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: 814b8e80941Smrg vaStatus = surface_from_external_memory(ctx, surf, memory_attribute, i, &templat); 815b8e80941Smrg if (vaStatus != VA_STATUS_SUCCESS) 816b8e80941Smrg goto free_surf; 817b8e80941Smrg break; 818b8e80941Smrg 819b8e80941Smrg default: 820b8e80941Smrg assert(0); 821b8e80941Smrg } 822b8e80941Smrg 823b8e80941Smrg util_dynarray_init(&surf->subpics, NULL); 824b8e80941Smrg surfaces[i] = handle_table_add(drv->htab, surf); 825b8e80941Smrg if (!surfaces[i]) { 826b8e80941Smrg vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; 827b8e80941Smrg goto destroy_surf; 828b8e80941Smrg } 829b8e80941Smrg } 830b8e80941Smrg mtx_unlock(&drv->mutex); 831b8e80941Smrg 832b8e80941Smrg return VA_STATUS_SUCCESS; 833b8e80941Smrg 834b8e80941Smrgdestroy_surf: 835b8e80941Smrg surf->buffer->destroy(surf->buffer); 836b8e80941Smrg 837b8e80941Smrgfree_surf: 838b8e80941Smrg FREE(surf); 839b8e80941Smrg 840b8e80941Smrgno_res: 841b8e80941Smrg mtx_unlock(&drv->mutex); 842b8e80941Smrg if (i) 843b8e80941Smrg vlVaDestroySurfaces(ctx, surfaces, i); 844b8e80941Smrg 845b8e80941Smrg return vaStatus; 846b8e80941Smrg} 847b8e80941Smrg 848b8e80941SmrgVAStatus 849b8e80941SmrgvlVaQueryVideoProcFilters(VADriverContextP ctx, VAContextID context, 850b8e80941Smrg VAProcFilterType *filters, unsigned int *num_filters) 851b8e80941Smrg{ 852b8e80941Smrg unsigned int num = 0; 853b8e80941Smrg 854b8e80941Smrg if (!ctx) 855b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 856b8e80941Smrg 857b8e80941Smrg if (!num_filters || !filters) 858b8e80941Smrg return VA_STATUS_ERROR_INVALID_PARAMETER; 859b8e80941Smrg 860b8e80941Smrg filters[num++] = VAProcFilterDeinterlacing; 861b8e80941Smrg 862b8e80941Smrg *num_filters = num; 863b8e80941Smrg 864b8e80941Smrg return VA_STATUS_SUCCESS; 865b8e80941Smrg} 866b8e80941Smrg 867b8e80941SmrgVAStatus 868b8e80941SmrgvlVaQueryVideoProcFilterCaps(VADriverContextP ctx, VAContextID context, 869b8e80941Smrg VAProcFilterType type, void *filter_caps, 870b8e80941Smrg unsigned int *num_filter_caps) 871b8e80941Smrg{ 872b8e80941Smrg unsigned int i; 873b8e80941Smrg 874b8e80941Smrg if (!ctx) 875b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 876b8e80941Smrg 877b8e80941Smrg if (!filter_caps || !num_filter_caps) 878b8e80941Smrg return VA_STATUS_ERROR_INVALID_PARAMETER; 879b8e80941Smrg 880b8e80941Smrg i = 0; 881b8e80941Smrg 882b8e80941Smrg switch (type) { 883b8e80941Smrg case VAProcFilterNone: 884b8e80941Smrg break; 885b8e80941Smrg case VAProcFilterDeinterlacing: { 886b8e80941Smrg VAProcFilterCapDeinterlacing *deint = filter_caps; 887b8e80941Smrg 888b8e80941Smrg if (*num_filter_caps < 3) { 889b8e80941Smrg *num_filter_caps = 3; 890b8e80941Smrg return VA_STATUS_ERROR_MAX_NUM_EXCEEDED; 891b8e80941Smrg } 892b8e80941Smrg 893b8e80941Smrg deint[i++].type = VAProcDeinterlacingBob; 894b8e80941Smrg deint[i++].type = VAProcDeinterlacingWeave; 895b8e80941Smrg deint[i++].type = VAProcDeinterlacingMotionAdaptive; 896b8e80941Smrg break; 897b8e80941Smrg } 898b8e80941Smrg 899b8e80941Smrg case VAProcFilterNoiseReduction: 900b8e80941Smrg case VAProcFilterSharpening: 901b8e80941Smrg case VAProcFilterColorBalance: 902b8e80941Smrg case VAProcFilterSkinToneEnhancement: 903b8e80941Smrg return VA_STATUS_ERROR_UNIMPLEMENTED; 904b8e80941Smrg default: 905b8e80941Smrg assert(0); 906b8e80941Smrg } 907b8e80941Smrg 908b8e80941Smrg *num_filter_caps = i; 909b8e80941Smrg 910b8e80941Smrg return VA_STATUS_SUCCESS; 911b8e80941Smrg} 912b8e80941Smrg 913b8e80941Smrgstatic VAProcColorStandardType vpp_input_color_standards[] = { 914b8e80941Smrg VAProcColorStandardBT601 915b8e80941Smrg}; 916b8e80941Smrg 917b8e80941Smrgstatic VAProcColorStandardType vpp_output_color_standards[] = { 918b8e80941Smrg VAProcColorStandardBT601 919b8e80941Smrg}; 920b8e80941Smrg 921b8e80941SmrgVAStatus 922b8e80941SmrgvlVaQueryVideoProcPipelineCaps(VADriverContextP ctx, VAContextID context, 923b8e80941Smrg VABufferID *filters, unsigned int num_filters, 924b8e80941Smrg VAProcPipelineCaps *pipeline_cap) 925b8e80941Smrg{ 926b8e80941Smrg unsigned int i = 0; 927b8e80941Smrg 928b8e80941Smrg if (!ctx) 929b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 930b8e80941Smrg 931b8e80941Smrg if (!pipeline_cap) 932b8e80941Smrg return VA_STATUS_ERROR_INVALID_PARAMETER; 933b8e80941Smrg 934b8e80941Smrg if (num_filters && !filters) 935b8e80941Smrg return VA_STATUS_ERROR_INVALID_PARAMETER; 936b8e80941Smrg 937b8e80941Smrg pipeline_cap->pipeline_flags = 0; 938b8e80941Smrg pipeline_cap->filter_flags = 0; 939b8e80941Smrg pipeline_cap->num_forward_references = 0; 940b8e80941Smrg pipeline_cap->num_backward_references = 0; 941b8e80941Smrg pipeline_cap->num_input_color_standards = ARRAY_SIZE(vpp_input_color_standards); 942b8e80941Smrg pipeline_cap->input_color_standards = vpp_input_color_standards; 943b8e80941Smrg pipeline_cap->num_output_color_standards = ARRAY_SIZE(vpp_output_color_standards); 944b8e80941Smrg pipeline_cap->output_color_standards = vpp_output_color_standards; 945b8e80941Smrg 946b8e80941Smrg for (i = 0; i < num_filters; i++) { 947b8e80941Smrg vlVaBuffer *buf = handle_table_get(VL_VA_DRIVER(ctx)->htab, filters[i]); 948b8e80941Smrg VAProcFilterParameterBufferBase *filter; 949b8e80941Smrg 950b8e80941Smrg if (!buf || buf->type != VAProcFilterParameterBufferType) 951b8e80941Smrg return VA_STATUS_ERROR_INVALID_BUFFER; 952b8e80941Smrg 953b8e80941Smrg filter = buf->data; 954b8e80941Smrg switch (filter->type) { 955b8e80941Smrg case VAProcFilterDeinterlacing: { 956b8e80941Smrg VAProcFilterParameterBufferDeinterlacing *deint = buf->data; 957b8e80941Smrg if (deint->algorithm == VAProcDeinterlacingMotionAdaptive) { 958b8e80941Smrg pipeline_cap->num_forward_references = 2; 959b8e80941Smrg pipeline_cap->num_backward_references = 1; 960b8e80941Smrg } 961b8e80941Smrg break; 962b8e80941Smrg } 963b8e80941Smrg default: 964b8e80941Smrg return VA_STATUS_ERROR_UNIMPLEMENTED; 965b8e80941Smrg } 966b8e80941Smrg } 967b8e80941Smrg 968b8e80941Smrg return VA_STATUS_SUCCESS; 969b8e80941Smrg} 970b8e80941Smrg 971b8e80941Smrg#if VA_CHECK_VERSION(1, 1, 0) 972b8e80941SmrgVAStatus 973b8e80941SmrgvlVaExportSurfaceHandle(VADriverContextP ctx, 974b8e80941Smrg VASurfaceID surface_id, 975b8e80941Smrg uint32_t mem_type, 976b8e80941Smrg uint32_t flags, 977b8e80941Smrg void *descriptor) 978b8e80941Smrg{ 979b8e80941Smrg vlVaDriver *drv; 980b8e80941Smrg vlVaSurface *surf; 981b8e80941Smrg struct pipe_surface **surfaces; 982b8e80941Smrg struct pipe_screen *screen; 983b8e80941Smrg VAStatus ret; 984b8e80941Smrg unsigned int usage; 985b8e80941Smrg int i, p; 986b8e80941Smrg 987b8e80941Smrg VADRMPRIMESurfaceDescriptor *desc = descriptor; 988b8e80941Smrg 989b8e80941Smrg if (mem_type != VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2) 990b8e80941Smrg return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE; 991b8e80941Smrg if (flags & VA_EXPORT_SURFACE_COMPOSED_LAYERS) 992b8e80941Smrg return VA_STATUS_ERROR_INVALID_SURFACE; 993b8e80941Smrg 994b8e80941Smrg drv = VL_VA_DRIVER(ctx); 995b8e80941Smrg screen = VL_VA_PSCREEN(ctx); 996b8e80941Smrg mtx_lock(&drv->mutex); 997b8e80941Smrg 998b8e80941Smrg surf = handle_table_get(drv->htab, surface_id); 999b8e80941Smrg if (!surf || !surf->buffer) { 1000b8e80941Smrg mtx_unlock(&drv->mutex); 1001b8e80941Smrg return VA_STATUS_ERROR_INVALID_SURFACE; 1002b8e80941Smrg } 1003b8e80941Smrg 1004b8e80941Smrg if (surf->buffer->interlaced) { 1005b8e80941Smrg struct pipe_video_buffer *interlaced = surf->buffer; 1006b8e80941Smrg struct u_rect src_rect, dst_rect; 1007b8e80941Smrg 1008b8e80941Smrg surf->templat.interlaced = false; 1009b8e80941Smrg 1010b8e80941Smrg ret = vlVaHandleSurfaceAllocate(drv, surf, &surf->templat); 1011b8e80941Smrg if (ret != VA_STATUS_SUCCESS) { 1012b8e80941Smrg mtx_unlock(&drv->mutex); 1013b8e80941Smrg return VA_STATUS_ERROR_ALLOCATION_FAILED; 1014b8e80941Smrg } 1015b8e80941Smrg 1016b8e80941Smrg src_rect.x0 = dst_rect.x0 = 0; 1017b8e80941Smrg src_rect.y0 = dst_rect.y0 = 0; 1018b8e80941Smrg src_rect.x1 = dst_rect.x1 = surf->templat.width; 1019b8e80941Smrg src_rect.y1 = dst_rect.y1 = surf->templat.height; 1020b8e80941Smrg 1021b8e80941Smrg vl_compositor_yuv_deint_full(&drv->cstate, &drv->compositor, 1022b8e80941Smrg interlaced, surf->buffer, 1023b8e80941Smrg &src_rect, &dst_rect, 1024b8e80941Smrg VL_COMPOSITOR_WEAVE); 1025b8e80941Smrg 1026b8e80941Smrg interlaced->destroy(interlaced); 1027b8e80941Smrg } 1028b8e80941Smrg 1029b8e80941Smrg surfaces = surf->buffer->get_surfaces(surf->buffer); 1030b8e80941Smrg 1031b8e80941Smrg usage = 0; 1032b8e80941Smrg if (flags & VA_EXPORT_SURFACE_WRITE_ONLY) 1033b8e80941Smrg usage |= PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE; 1034b8e80941Smrg 1035b8e80941Smrg desc->fourcc = PipeFormatToVaFourcc(surf->buffer->buffer_format); 1036b8e80941Smrg desc->width = surf->buffer->width; 1037b8e80941Smrg desc->height = surf->buffer->height; 1038b8e80941Smrg 1039b8e80941Smrg for (p = 0; p < VL_MAX_SURFACES; p++) { 1040b8e80941Smrg struct winsys_handle whandle; 1041b8e80941Smrg struct pipe_resource *resource; 1042b8e80941Smrg uint32_t drm_format; 1043b8e80941Smrg 1044b8e80941Smrg if (!surfaces[p]) 1045b8e80941Smrg break; 1046b8e80941Smrg 1047b8e80941Smrg resource = surfaces[p]->texture; 1048b8e80941Smrg 1049b8e80941Smrg switch (resource->format) { 1050b8e80941Smrg case PIPE_FORMAT_R8_UNORM: 1051b8e80941Smrg drm_format = DRM_FORMAT_R8; 1052b8e80941Smrg break; 1053b8e80941Smrg case PIPE_FORMAT_R8G8_UNORM: 1054b8e80941Smrg drm_format = DRM_FORMAT_GR88; 1055b8e80941Smrg break; 1056b8e80941Smrg case PIPE_FORMAT_R16_UNORM: 1057b8e80941Smrg drm_format = DRM_FORMAT_R16; 1058b8e80941Smrg break; 1059b8e80941Smrg case PIPE_FORMAT_R16G16_UNORM: 1060b8e80941Smrg drm_format = DRM_FORMAT_GR1616; 1061b8e80941Smrg break; 1062b8e80941Smrg case PIPE_FORMAT_B8G8R8A8_UNORM: 1063b8e80941Smrg drm_format = DRM_FORMAT_ARGB8888; 1064b8e80941Smrg break; 1065b8e80941Smrg case PIPE_FORMAT_R8G8B8A8_UNORM: 1066b8e80941Smrg drm_format = DRM_FORMAT_ABGR8888; 1067b8e80941Smrg break; 1068b8e80941Smrg case PIPE_FORMAT_B8G8R8X8_UNORM: 1069b8e80941Smrg drm_format = DRM_FORMAT_XRGB8888; 1070b8e80941Smrg break; 1071b8e80941Smrg case PIPE_FORMAT_R8G8B8X8_UNORM: 1072b8e80941Smrg drm_format = DRM_FORMAT_XBGR8888; 1073b8e80941Smrg break; 1074b8e80941Smrg default: 1075b8e80941Smrg ret = VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE; 1076b8e80941Smrg goto fail; 1077b8e80941Smrg } 1078b8e80941Smrg 1079b8e80941Smrg memset(&whandle, 0, sizeof(whandle)); 1080b8e80941Smrg whandle.type = WINSYS_HANDLE_TYPE_FD; 1081b8e80941Smrg 1082b8e80941Smrg if (!screen->resource_get_handle(screen, drv->pipe, resource, 1083b8e80941Smrg &whandle, usage)) { 1084b8e80941Smrg ret = VA_STATUS_ERROR_INVALID_SURFACE; 1085b8e80941Smrg goto fail; 1086b8e80941Smrg } 1087b8e80941Smrg 1088b8e80941Smrg desc->objects[p].fd = (int)whandle.handle; 1089b8e80941Smrg desc->objects[p].size = 0; 1090b8e80941Smrg desc->objects[p].drm_format_modifier = whandle.modifier; 1091b8e80941Smrg 1092b8e80941Smrg desc->layers[p].drm_format = drm_format; 1093b8e80941Smrg desc->layers[p].num_planes = 1; 1094b8e80941Smrg desc->layers[p].object_index[0] = p; 1095b8e80941Smrg desc->layers[p].offset[0] = whandle.offset; 1096b8e80941Smrg desc->layers[p].pitch[0] = whandle.stride; 1097b8e80941Smrg } 1098b8e80941Smrg 1099b8e80941Smrg desc->num_objects = p; 1100b8e80941Smrg desc->num_layers = p; 1101b8e80941Smrg 1102b8e80941Smrg mtx_unlock(&drv->mutex); 1103b8e80941Smrg 1104b8e80941Smrg return VA_STATUS_SUCCESS; 1105b8e80941Smrg 1106b8e80941Smrgfail: 1107b8e80941Smrg for (i = 0; i < p; i++) 1108b8e80941Smrg close(desc->objects[i].fd); 1109b8e80941Smrg 1110b8e80941Smrg mtx_unlock(&drv->mutex); 1111b8e80941Smrg 1112b8e80941Smrg return ret; 1113b8e80941Smrg} 1114b8e80941Smrg#endif 1115