Home | History | Annotate | Download | only in va
      1 /**************************************************************************
      2  *
      3  * Copyright 2010 Thomas Balling Srensen & Orasanu Lucian.
      4  * Copyright 2014 Advanced Micro Devices, Inc.
      5  * All Rights Reserved.
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining a
      8  * copy of this software and associated documentation files (the
      9  * "Software"), to deal in the Software without restriction, including
     10  * without limitation the rights to use, copy, modify, merge, publish,
     11  * distribute, sub license, and/or sell copies of the Software, and to
     12  * permit persons to whom the Software is furnished to do so, subject to
     13  * the following conditions:
     14  *
     15  * The above copyright notice and this permission notice (including the
     16  * next paragraph) shall be included in all copies or substantial portions
     17  * of the Software.
     18  *
     19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     20  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     21  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     22  * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
     23  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     24  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     25  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     26  *
     27  **************************************************************************/
     28 
     29 #include "pipe/p_screen.h"
     30 #include "pipe/p_video_codec.h"
     31 
     32 #include "state_tracker/drm_driver.h"
     33 
     34 #include "util/u_memory.h"
     35 #include "util/u_handle_table.h"
     36 #include "util/u_rect.h"
     37 #include "util/u_sampler.h"
     38 #include "util/u_surface.h"
     39 
     40 #include "vl/vl_compositor.h"
     41 #include "vl/vl_video_buffer.h"
     42 #include "vl/vl_winsys.h"
     43 
     44 #include "va_private.h"
     45 
     46 DEBUG_GET_ONCE_BOOL_OPTION(nointerlace, "VAAPI_DISABLE_INTERLACE", FALSE);
     47 
     48 #include <va/va_drmcommon.h>
     49 
     50 static const enum pipe_format vpp_surface_formats[] = {
     51    PIPE_FORMAT_B8G8R8A8_UNORM, PIPE_FORMAT_R8G8B8A8_UNORM,
     52    PIPE_FORMAT_B8G8R8X8_UNORM, PIPE_FORMAT_R8G8B8X8_UNORM
     53 };
     54 
     55 VAStatus
     56 vlVaCreateSurfaces(VADriverContextP ctx, int width, int height, int format,
     57                    int num_surfaces, VASurfaceID *surfaces)
     58 {
     59    return vlVaCreateSurfaces2(ctx, format, width, height, surfaces, num_surfaces,
     60                               NULL, 0);
     61 }
     62 
     63 VAStatus
     64 vlVaDestroySurfaces(VADriverContextP ctx, VASurfaceID *surface_list, int num_surfaces)
     65 {
     66    vlVaDriver *drv;
     67    int i;
     68 
     69    if (!ctx)
     70       return VA_STATUS_ERROR_INVALID_CONTEXT;
     71 
     72    drv = VL_VA_DRIVER(ctx);
     73    pipe_mutex_lock(drv->mutex);
     74    for (i = 0; i < num_surfaces; ++i) {
     75       vlVaSurface *surf = handle_table_get(drv->htab, surface_list[i]);
     76       if (!surf) {
     77          pipe_mutex_unlock(drv->mutex);
     78          return VA_STATUS_ERROR_INVALID_SURFACE;
     79       }
     80       if (surf->buffer)
     81          surf->buffer->destroy(surf->buffer);
     82       util_dynarray_fini(&surf->subpics);
     83       FREE(surf);
     84       handle_table_remove(drv->htab, surface_list[i]);
     85    }
     86    pipe_mutex_unlock(drv->mutex);
     87 
     88    return VA_STATUS_SUCCESS;
     89 }
     90 
     91 VAStatus
     92 vlVaSyncSurface(VADriverContextP ctx, VASurfaceID render_target)
     93 {
     94    vlVaDriver *drv;
     95    vlVaContext *context;
     96    vlVaSurface *surf;
     97 
     98    if (!ctx)
     99       return VA_STATUS_ERROR_INVALID_CONTEXT;
    100 
    101    drv = VL_VA_DRIVER(ctx);
    102    if (!drv)
    103       return VA_STATUS_ERROR_INVALID_CONTEXT;
    104 
    105    pipe_mutex_lock(drv->mutex);
    106    surf = handle_table_get(drv->htab, render_target);
    107 
    108    if (!surf || !surf->buffer) {
    109       pipe_mutex_unlock(drv->mutex);
    110       return VA_STATUS_ERROR_INVALID_SURFACE;
    111    }
    112 
    113    if (!surf->feedback) {
    114       // No outstanding operation: nothing to do.
    115       pipe_mutex_unlock(drv->mutex);
    116       return VA_STATUS_SUCCESS;
    117    }
    118 
    119    context = handle_table_get(drv->htab, surf->ctx);
    120    if (!context) {
    121       pipe_mutex_unlock(drv->mutex);
    122       return VA_STATUS_ERROR_INVALID_CONTEXT;
    123    }
    124 
    125    if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) {
    126       int frame_diff;
    127       if (context->desc.h264enc.frame_num_cnt >= surf->frame_num_cnt)
    128          frame_diff = context->desc.h264enc.frame_num_cnt - surf->frame_num_cnt;
    129       else
    130          frame_diff = 0xFFFFFFFF - surf->frame_num_cnt + 1 + context->desc.h264enc.frame_num_cnt;
    131       if ((frame_diff == 0) &&
    132           (surf->force_flushed == false) &&
    133           (context->desc.h264enc.frame_num_cnt % 2 != 0)) {
    134          context->decoder->flush(context->decoder);
    135          context->first_single_submitted = true;
    136       }
    137       context->decoder->get_feedback(context->decoder, surf->feedback, &(surf->coded_buf->coded_size));
    138       surf->feedback = NULL;
    139    }
    140    pipe_mutex_unlock(drv->mutex);
    141    return VA_STATUS_SUCCESS;
    142 }
    143 
    144 VAStatus
    145 vlVaQuerySurfaceStatus(VADriverContextP ctx, VASurfaceID render_target, VASurfaceStatus *status)
    146 {
    147    if (!ctx)
    148       return VA_STATUS_ERROR_INVALID_CONTEXT;
    149 
    150    return VA_STATUS_SUCCESS;
    151 }
    152 
    153 VAStatus
    154 vlVaQuerySurfaceError(VADriverContextP ctx, VASurfaceID render_target, VAStatus error_status, void **error_info)
    155 {
    156    if (!ctx)
    157       return VA_STATUS_ERROR_INVALID_CONTEXT;
    158 
    159    return VA_STATUS_ERROR_UNIMPLEMENTED;
    160 }
    161 
    162 static void
    163 upload_sampler(struct pipe_context *pipe, struct pipe_sampler_view *dst,
    164                const struct pipe_box *dst_box, const void *src, unsigned src_stride,
    165                unsigned src_x, unsigned src_y)
    166 {
    167    struct pipe_transfer *transfer;
    168    void *map;
    169 
    170    map = pipe->transfer_map(pipe, dst->texture, 0, PIPE_TRANSFER_WRITE,
    171                             dst_box, &transfer);
    172    if (!map)
    173       return;
    174 
    175    util_copy_rect(map, dst->texture->format, transfer->stride, 0, 0,
    176                   dst_box->width, dst_box->height,
    177                   src, src_stride, src_x, src_y);
    178 
    179    pipe->transfer_unmap(pipe, transfer);
    180 }
    181 
    182 static VAStatus
    183 vlVaPutSubpictures(vlVaSurface *surf, vlVaDriver *drv,
    184                    struct pipe_surface *surf_draw, struct u_rect *dirty_area,
    185                    struct u_rect *src_rect, struct u_rect *dst_rect)
    186 {
    187    vlVaSubpicture *sub;
    188    int i;
    189 
    190    if (!(surf->subpics.data || surf->subpics.size))
    191       return VA_STATUS_SUCCESS;
    192 
    193    for (i = 0; i < surf->subpics.size/sizeof(vlVaSubpicture *); i++) {
    194       struct pipe_blend_state blend;
    195       void *blend_state;
    196       vlVaBuffer *buf;
    197       struct pipe_box box;
    198       struct u_rect *s, *d, sr, dr, c;
    199       int sw, sh, dw, dh;
    200 
    201       sub = ((vlVaSubpicture **)surf->subpics.data)[i];
    202       if (!sub)
    203          continue;
    204 
    205       buf = handle_table_get(drv->htab, sub->image->buf);
    206       if (!buf)
    207          return VA_STATUS_ERROR_INVALID_IMAGE;
    208 
    209       box.x = 0;
    210       box.y = 0;
    211       box.z = 0;
    212       box.width = sub->dst_rect.x1 - sub->dst_rect.x0;
    213       box.height = sub->dst_rect.y1 - sub->dst_rect.y0;
    214       box.depth = 1;
    215 
    216       s = &sub->src_rect;
    217       d = &sub->dst_rect;
    218       sw = s->x1 - s->x0;
    219       sh = s->y1 - s->y0;
    220       dw = d->x1 - d->x0;
    221       dh = d->y1 - d->y0;
    222       c.x0 = MAX2(d->x0, s->x0);
    223       c.y0 = MAX2(d->y0, s->y0);
    224       c.x1 = MIN2(d->x0 + dw, src_rect->x1);
    225       c.y1 = MIN2(d->y0 + dh, src_rect->y1);
    226       sr.x0 = s->x0 + (c.x0 - d->x0)*(sw/(float)dw);
    227       sr.y0 = s->y0 + (c.y0 - d->y0)*(sh/(float)dh);
    228       sr.x1 = s->x0 + (c.x1 - d->x0)*(sw/(float)dw);
    229       sr.y1 = s->y0 + (c.y1 - d->y0)*(sh/(float)dh);
    230 
    231       s = src_rect;
    232       d = dst_rect;
    233       sw = s->x1 - s->x0;
    234       sh = s->y1 - s->y0;
    235       dw = d->x1 - d->x0;
    236       dh = d->y1 - d->y0;
    237       dr.x0 = d->x0 + c.x0*(dw/(float)sw);
    238       dr.y0 = d->y0 + c.y0*(dh/(float)sh);
    239       dr.x1 = d->x0 + c.x1*(dw/(float)sw);
    240       dr.y1 = d->y0 + c.y1*(dh/(float)sh);
    241 
    242       memset(&blend, 0, sizeof(blend));
    243       blend.independent_blend_enable = 0;
    244       blend.rt[0].blend_enable = 1;
    245       blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
    246       blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
    247       blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO;
    248       blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
    249       blend.rt[0].rgb_func = PIPE_BLEND_ADD;
    250       blend.rt[0].alpha_func = PIPE_BLEND_ADD;
    251       blend.rt[0].colormask = PIPE_MASK_RGBA;
    252       blend.logicop_enable = 0;
    253       blend.logicop_func = PIPE_LOGICOP_CLEAR;
    254       blend.dither = 0;
    255       blend_state = drv->pipe->create_blend_state(drv->pipe, &blend);
    256 
    257       vl_compositor_clear_layers(&drv->cstate);
    258       vl_compositor_set_layer_blend(&drv->cstate, 0, blend_state, false);
    259       upload_sampler(drv->pipe, sub->sampler, &box, buf->data,
    260                      sub->image->pitches[0], 0, 0);
    261       vl_compositor_set_rgba_layer(&drv->cstate, &drv->compositor, 0, sub->sampler,
    262                                    &sr, NULL, NULL);
    263       vl_compositor_set_layer_dst_area(&drv->cstate, 0, &dr);
    264       vl_compositor_render(&drv->cstate, &drv->compositor, surf_draw, dirty_area, false);
    265       drv->pipe->delete_blend_state(drv->pipe, blend_state);
    266    }
    267 
    268    return VA_STATUS_SUCCESS;
    269 }
    270 
    271 VAStatus
    272 vlVaPutSurface(VADriverContextP ctx, VASurfaceID surface_id, void* draw, short srcx, short srcy,
    273                unsigned short srcw, unsigned short srch, short destx, short desty,
    274                unsigned short destw, unsigned short desth, VARectangle *cliprects,
    275                unsigned int number_cliprects,  unsigned int flags)
    276 {
    277    vlVaDriver *drv;
    278    vlVaSurface *surf;
    279    struct pipe_screen *screen;
    280    struct pipe_resource *tex;
    281    struct pipe_surface surf_templ, *surf_draw;
    282    struct vl_screen *vscreen;
    283    struct u_rect src_rect, *dirty_area;
    284    struct u_rect dst_rect = {destx, destx + destw, desty, desty + desth};
    285    VAStatus status;
    286 
    287    if (!ctx)
    288       return VA_STATUS_ERROR_INVALID_CONTEXT;
    289 
    290    drv = VL_VA_DRIVER(ctx);
    291    pipe_mutex_lock(drv->mutex);
    292    surf = handle_table_get(drv->htab, surface_id);
    293    if (!surf) {
    294       pipe_mutex_unlock(drv->mutex);
    295       return VA_STATUS_ERROR_INVALID_SURFACE;
    296    }
    297 
    298    screen = drv->pipe->screen;
    299    vscreen = drv->vscreen;
    300 
    301    tex = vscreen->texture_from_drawable(vscreen, draw);
    302    if (!tex) {
    303       pipe_mutex_unlock(drv->mutex);
    304       return VA_STATUS_ERROR_INVALID_DISPLAY;
    305    }
    306 
    307    dirty_area = vscreen->get_dirty_area(vscreen);
    308 
    309    memset(&surf_templ, 0, sizeof(surf_templ));
    310    surf_templ.format = tex->format;
    311    surf_draw = drv->pipe->create_surface(drv->pipe, tex, &surf_templ);
    312    if (!surf_draw) {
    313       pipe_resource_reference(&tex, NULL);
    314       pipe_mutex_unlock(drv->mutex);
    315       return VA_STATUS_ERROR_INVALID_DISPLAY;
    316    }
    317 
    318    src_rect.x0 = srcx;
    319    src_rect.y0 = srcy;
    320    src_rect.x1 = srcw + srcx;
    321    src_rect.y1 = srch + srcy;
    322 
    323    vl_compositor_clear_layers(&drv->cstate);
    324    vl_compositor_set_buffer_layer(&drv->cstate, &drv->compositor, 0, surf->buffer, &src_rect, NULL, VL_COMPOSITOR_WEAVE);
    325    vl_compositor_set_layer_dst_area(&drv->cstate, 0, &dst_rect);
    326    vl_compositor_render(&drv->cstate, &drv->compositor, surf_draw, dirty_area, true);
    327 
    328    status = vlVaPutSubpictures(surf, drv, surf_draw, dirty_area, &src_rect, &dst_rect);
    329    if (status) {
    330       pipe_mutex_unlock(drv->mutex);
    331       return status;
    332    }
    333 
    334    /* flush before calling flush_frontbuffer so that rendering is flushed
    335     * to back buffer so the texture can be copied in flush_frontbuffer
    336     */
    337    drv->pipe->flush(drv->pipe, NULL, 0);
    338 
    339    screen->flush_frontbuffer(screen, tex, 0, 0,
    340                              vscreen->get_private(vscreen), NULL);
    341 
    342 
    343    pipe_resource_reference(&tex, NULL);
    344    pipe_surface_reference(&surf_draw, NULL);
    345    pipe_mutex_unlock(drv->mutex);
    346 
    347    return VA_STATUS_SUCCESS;
    348 }
    349 
    350 VAStatus
    351 vlVaLockSurface(VADriverContextP ctx, VASurfaceID surface, unsigned int *fourcc,
    352                 unsigned int *luma_stride, unsigned int *chroma_u_stride, unsigned int *chroma_v_stride,
    353                 unsigned int *luma_offset, unsigned int *chroma_u_offset, unsigned int *chroma_v_offset,
    354                 unsigned int *buffer_name, void **buffer)
    355 {
    356    if (!ctx)
    357       return VA_STATUS_ERROR_INVALID_CONTEXT;
    358 
    359    return VA_STATUS_ERROR_UNIMPLEMENTED;
    360 }
    361 
    362 VAStatus
    363 vlVaUnlockSurface(VADriverContextP ctx, VASurfaceID surface)
    364 {
    365    if (!ctx)
    366       return VA_STATUS_ERROR_INVALID_CONTEXT;
    367 
    368    return VA_STATUS_ERROR_UNIMPLEMENTED;
    369 }
    370 
    371 VAStatus
    372 vlVaQuerySurfaceAttributes(VADriverContextP ctx, VAConfigID config_id,
    373                            VASurfaceAttrib *attrib_list, unsigned int *num_attribs)
    374 {
    375    vlVaDriver *drv;
    376    vlVaConfig *config;
    377    VASurfaceAttrib *attribs;
    378    struct pipe_screen *pscreen;
    379    int i, j;
    380 
    381    STATIC_ASSERT(ARRAY_SIZE(vpp_surface_formats) <= VL_VA_MAX_IMAGE_FORMATS);
    382 
    383    if (config_id == VA_INVALID_ID)
    384       return VA_STATUS_ERROR_INVALID_CONFIG;
    385 
    386    if (!attrib_list && !num_attribs)
    387       return VA_STATUS_ERROR_INVALID_PARAMETER;
    388 
    389    if (!attrib_list) {
    390       *num_attribs = VL_VA_MAX_IMAGE_FORMATS + VASurfaceAttribCount;
    391       return VA_STATUS_SUCCESS;
    392    }
    393 
    394    if (!ctx)
    395       return VA_STATUS_ERROR_INVALID_CONTEXT;
    396 
    397    drv = VL_VA_DRIVER(ctx);
    398 
    399    if (!drv)
    400       return VA_STATUS_ERROR_INVALID_CONTEXT;
    401 
    402    pipe_mutex_lock(drv->mutex);
    403    config = handle_table_get(drv->htab, config_id);
    404    pipe_mutex_unlock(drv->mutex);
    405 
    406    if (!config)
    407       return VA_STATUS_ERROR_INVALID_CONFIG;
    408 
    409    pscreen = VL_VA_PSCREEN(ctx);
    410 
    411    if (!pscreen)
    412       return VA_STATUS_ERROR_INVALID_CONTEXT;
    413 
    414    attribs = CALLOC(VL_VA_MAX_IMAGE_FORMATS + VASurfaceAttribCount,
    415                     sizeof(VASurfaceAttrib));
    416 
    417    if (!attribs)
    418       return VA_STATUS_ERROR_ALLOCATION_FAILED;
    419 
    420    i = 0;
    421 
    422    /* vlVaCreateConfig returns PIPE_VIDEO_PROFILE_UNKNOWN
    423     * only for VAEntrypointVideoProc. */
    424    if (config->profile == PIPE_VIDEO_PROFILE_UNKNOWN) {
    425       if (config->rt_format & VA_RT_FORMAT_RGB32) {
    426          for (j = 0; j < ARRAY_SIZE(vpp_surface_formats); ++j) {
    427             attribs[i].type = VASurfaceAttribPixelFormat;
    428             attribs[i].value.type = VAGenericValueTypeInteger;
    429             attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
    430             attribs[i].value.value.i = PipeFormatToVaFourcc(vpp_surface_formats[j]);
    431             i++;
    432          }
    433       }
    434       if (config->rt_format & VA_RT_FORMAT_YUV420) {
    435          attribs[i].type = VASurfaceAttribPixelFormat;
    436          attribs[i].value.type = VAGenericValueTypeInteger;
    437          attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
    438          attribs[i].value.value.i = VA_FOURCC_NV12;
    439          i++;
    440       }
    441    } else {
    442       /* Assume VAEntrypointVLD for now. */
    443       attribs[i].type = VASurfaceAttribPixelFormat;
    444       attribs[i].value.type = VAGenericValueTypeInteger;
    445       attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
    446       attribs[i].value.value.i = VA_FOURCC_NV12;
    447       i++;
    448    }
    449 
    450    attribs[i].type = VASurfaceAttribMemoryType;
    451    attribs[i].value.type = VAGenericValueTypeInteger;
    452    attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
    453    attribs[i].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_VA |
    454          VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
    455    i++;
    456 
    457    attribs[i].type = VASurfaceAttribExternalBufferDescriptor;
    458    attribs[i].value.type = VAGenericValueTypePointer;
    459    attribs[i].flags = VA_SURFACE_ATTRIB_SETTABLE;
    460    attribs[i].value.value.p = NULL; /* ignore */
    461    i++;
    462 
    463    attribs[i].type = VASurfaceAttribMaxWidth;
    464    attribs[i].value.type = VAGenericValueTypeInteger;
    465    attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE;
    466    attribs[i].value.value.i = vl_video_buffer_max_size(pscreen);
    467    i++;
    468 
    469    attribs[i].type = VASurfaceAttribMaxHeight;
    470    attribs[i].value.type = VAGenericValueTypeInteger;
    471    attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE;
    472    attribs[i].value.value.i = vl_video_buffer_max_size(pscreen);
    473    i++;
    474 
    475    if (i > *num_attribs) {
    476       *num_attribs = i;
    477       FREE(attribs);
    478       return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
    479    }
    480 
    481    *num_attribs = i;
    482    memcpy(attrib_list, attribs, i * sizeof(VASurfaceAttrib));
    483    FREE(attribs);
    484 
    485    return VA_STATUS_SUCCESS;
    486 }
    487 
    488 static VAStatus
    489 suface_from_external_memory(VADriverContextP ctx, vlVaSurface *surface,
    490                             VASurfaceAttribExternalBuffers *memory_attibute,
    491                             int index, VASurfaceID *surfaces,
    492                             struct pipe_video_buffer *templat)
    493 {
    494    vlVaDriver *drv;
    495    struct pipe_screen *pscreen;
    496    struct pipe_resource *resource;
    497    struct pipe_resource res_templ;
    498    struct winsys_handle whandle;
    499    struct pipe_resource *resources[VL_NUM_COMPONENTS];
    500 
    501    if (!ctx)
    502       return VA_STATUS_ERROR_INVALID_PARAMETER;
    503 
    504    pscreen = VL_VA_PSCREEN(ctx);
    505    drv = VL_VA_DRIVER(ctx);
    506 
    507    if (!memory_attibute || !memory_attibute->buffers ||
    508        index > memory_attibute->num_buffers)
    509       return VA_STATUS_ERROR_INVALID_PARAMETER;
    510 
    511    if (surface->templat.width != memory_attibute->width ||
    512        surface->templat.height != memory_attibute->height ||
    513        memory_attibute->num_planes < 1)
    514       return VA_STATUS_ERROR_INVALID_PARAMETER;
    515 
    516    switch (memory_attibute->pixel_format) {
    517    case VA_FOURCC_RGBA:
    518    case VA_FOURCC_RGBX:
    519    case VA_FOURCC_BGRA:
    520    case VA_FOURCC_BGRX:
    521       if (memory_attibute->num_planes != 1)
    522          return VA_STATUS_ERROR_INVALID_PARAMETER;
    523       break;
    524    default:
    525       return VA_STATUS_ERROR_INVALID_PARAMETER;
    526    }
    527 
    528    memset(&res_templ, 0, sizeof(res_templ));
    529    res_templ.target = PIPE_TEXTURE_2D;
    530    res_templ.last_level = 0;
    531    res_templ.depth0 = 1;
    532    res_templ.array_size = 1;
    533    res_templ.width0 = memory_attibute->width;
    534    res_templ.height0 = memory_attibute->height;
    535    res_templ.format = surface->templat.buffer_format;
    536    res_templ.bind = PIPE_BIND_SAMPLER_VIEW;
    537    res_templ.usage = PIPE_USAGE_DEFAULT;
    538 
    539    memset(&whandle, 0, sizeof(struct winsys_handle));
    540    whandle.type = DRM_API_HANDLE_TYPE_FD;
    541    whandle.handle = memory_attibute->buffers[index];
    542    whandle.stride = memory_attibute->pitches[index];
    543 
    544    resource = pscreen->resource_from_handle(pscreen, &res_templ, &whandle,
    545                                             PIPE_HANDLE_USAGE_READ_WRITE);
    546 
    547    if (!resource)
    548       return VA_STATUS_ERROR_ALLOCATION_FAILED;
    549 
    550    memset(resources, 0, sizeof resources);
    551    resources[0] = resource;
    552 
    553    surface->buffer = vl_video_buffer_create_ex2(drv->pipe, templat, resources);
    554    if (!surface->buffer)
    555       return VA_STATUS_ERROR_ALLOCATION_FAILED;
    556 
    557    util_dynarray_init(&surface->subpics);
    558    surfaces[index] = handle_table_add(drv->htab, surface);
    559 
    560    if (!surfaces[index]) {
    561       surface->buffer->destroy(surface->buffer);
    562       return VA_STATUS_ERROR_ALLOCATION_FAILED;
    563    }
    564 
    565    return VA_STATUS_SUCCESS;
    566 }
    567 
    568 VAStatus
    569 vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format,
    570                     unsigned int width, unsigned int height,
    571                     VASurfaceID *surfaces, unsigned int num_surfaces,
    572                     VASurfaceAttrib *attrib_list, unsigned int num_attribs)
    573 {
    574    vlVaDriver *drv;
    575    VASurfaceAttribExternalBuffers *memory_attibute;
    576    struct pipe_video_buffer templat;
    577    struct pipe_screen *pscreen;
    578    int i;
    579    int memory_type;
    580    int expected_fourcc;
    581    VAStatus vaStatus;
    582 
    583    if (!ctx)
    584       return VA_STATUS_ERROR_INVALID_CONTEXT;
    585 
    586    if (!(width && height))
    587       return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT;
    588 
    589    drv = VL_VA_DRIVER(ctx);
    590 
    591    if (!drv)
    592       return VA_STATUS_ERROR_INVALID_CONTEXT;
    593 
    594    pscreen = VL_VA_PSCREEN(ctx);
    595 
    596    if (!pscreen)
    597       return VA_STATUS_ERROR_INVALID_CONTEXT;
    598 
    599    /* Default. */
    600    memory_attibute = NULL;
    601    memory_type = VA_SURFACE_ATTRIB_MEM_TYPE_VA;
    602    expected_fourcc = 0;
    603 
    604    for (i = 0; i < num_attribs && attrib_list; i++) {
    605       if ((attrib_list[i].type == VASurfaceAttribPixelFormat) &&
    606           (attrib_list[i].flags & VA_SURFACE_ATTRIB_SETTABLE)) {
    607          if (attrib_list[i].value.type != VAGenericValueTypeInteger)
    608             return VA_STATUS_ERROR_INVALID_PARAMETER;
    609          expected_fourcc = attrib_list[i].value.value.i;
    610       }
    611 
    612       if ((attrib_list[i].type == VASurfaceAttribMemoryType) &&
    613           (attrib_list[i].flags & VA_SURFACE_ATTRIB_SETTABLE)) {
    614 
    615          if (attrib_list[i].value.type != VAGenericValueTypeInteger)
    616             return VA_STATUS_ERROR_INVALID_PARAMETER;
    617 
    618          switch (attrib_list[i].value.value.i) {
    619          case VA_SURFACE_ATTRIB_MEM_TYPE_VA:
    620          case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME:
    621             memory_type = attrib_list[i].value.value.i;
    622             break;
    623          default:
    624             return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;
    625          }
    626       }
    627 
    628       if ((attrib_list[i].type == VASurfaceAttribExternalBufferDescriptor) &&
    629           (attrib_list[i].flags == VA_SURFACE_ATTRIB_SETTABLE)) {
    630          if (attrib_list[i].value.type != VAGenericValueTypePointer)
    631             return VA_STATUS_ERROR_INVALID_PARAMETER;
    632          memory_attibute = (VASurfaceAttribExternalBuffers *)attrib_list[i].value.value.p;
    633       }
    634    }
    635 
    636    if (VA_RT_FORMAT_YUV420 != format &&
    637        VA_RT_FORMAT_YUV422 != format &&
    638        VA_RT_FORMAT_YUV444 != format &&
    639        VA_RT_FORMAT_RGB32  != format) {
    640       return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
    641    }
    642 
    643    switch (memory_type) {
    644    case VA_SURFACE_ATTRIB_MEM_TYPE_VA:
    645       break;
    646    case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME:
    647       if (!memory_attibute)
    648          return VA_STATUS_ERROR_INVALID_PARAMETER;
    649 
    650       expected_fourcc = memory_attibute->pixel_format;
    651       break;
    652    default:
    653       assert(0);
    654    }
    655 
    656    memset(&templat, 0, sizeof(templat));
    657 
    658    templat.buffer_format = pscreen->get_video_param(
    659       pscreen,
    660       PIPE_VIDEO_PROFILE_UNKNOWN,
    661       PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
    662       PIPE_VIDEO_CAP_PREFERED_FORMAT
    663    );
    664    templat.interlaced = pscreen->get_video_param(
    665       pscreen,
    666       PIPE_VIDEO_PROFILE_UNKNOWN,
    667       PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
    668       PIPE_VIDEO_CAP_PREFERS_INTERLACED
    669    );
    670 
    671    if (expected_fourcc) {
    672       enum pipe_format expected_format = VaFourccToPipeFormat(expected_fourcc);
    673 
    674       if (expected_format != templat.buffer_format || memory_attibute)
    675         templat.interlaced = 0;
    676 
    677       templat.buffer_format = expected_format;
    678    }
    679 
    680    templat.chroma_format = ChromaToPipe(format);
    681 
    682    templat.width = width;
    683    templat.height = height;
    684    if (debug_get_option_nointerlace())
    685       templat.interlaced = false;
    686 
    687    memset(surfaces, VA_INVALID_ID, num_surfaces * sizeof(VASurfaceID));
    688 
    689    pipe_mutex_lock(drv->mutex);
    690    for (i = 0; i < num_surfaces; i++) {
    691       vlVaSurface *surf = CALLOC(1, sizeof(vlVaSurface));
    692       if (!surf)
    693          goto no_res;
    694 
    695       surf->templat = templat;
    696 
    697       switch (memory_type) {
    698       case VA_SURFACE_ATTRIB_MEM_TYPE_VA:
    699          /* The application will clear the TILING flag when the surface is
    700           * intended to be exported as dmabuf. Adding shared flag because not
    701           * null memory_attibute means VASurfaceAttribExternalBuffers is used.
    702           */
    703          if (memory_attibute &&
    704              !(memory_attibute->flags & VA_SURFACE_EXTBUF_DESC_ENABLE_TILING))
    705             templat.bind = PIPE_BIND_LINEAR | PIPE_BIND_SHARED;
    706 
    707          surf->buffer = drv->pipe->create_video_buffer(drv->pipe, &templat);
    708          if (!surf->buffer) {
    709             FREE(surf);
    710             goto no_res;
    711          }
    712          util_dynarray_init(&surf->subpics);
    713          surfaces[i] = handle_table_add(drv->htab, surf);
    714          break;
    715       case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME:
    716          vaStatus = suface_from_external_memory(ctx, surf, memory_attibute, i, surfaces, &templat);
    717          if (vaStatus != VA_STATUS_SUCCESS) {
    718             FREE(surf);
    719             goto no_res;
    720          }
    721          break;
    722       default:
    723          assert(0);
    724       }
    725    }
    726    pipe_mutex_unlock(drv->mutex);
    727 
    728    return VA_STATUS_SUCCESS;
    729 
    730 no_res:
    731    pipe_mutex_unlock(drv->mutex);
    732    if (i)
    733       vlVaDestroySurfaces(ctx, surfaces, i);
    734 
    735    return VA_STATUS_ERROR_ALLOCATION_FAILED;
    736 }
    737 
    738 VAStatus
    739 vlVaQueryVideoProcFilters(VADriverContextP ctx, VAContextID context,
    740                           VAProcFilterType *filters, unsigned int *num_filters)
    741 {
    742    unsigned int num = 0;
    743 
    744    if (!ctx)
    745       return VA_STATUS_ERROR_INVALID_CONTEXT;
    746 
    747    if (!num_filters || !filters)
    748       return VA_STATUS_ERROR_INVALID_PARAMETER;
    749 
    750    filters[num++] = VAProcFilterDeinterlacing;
    751 
    752    *num_filters = num;
    753 
    754    return VA_STATUS_SUCCESS;
    755 }
    756 
    757 VAStatus
    758 vlVaQueryVideoProcFilterCaps(VADriverContextP ctx, VAContextID context,
    759                              VAProcFilterType type, void *filter_caps,
    760                              unsigned int *num_filter_caps)
    761 {
    762    unsigned int i;
    763 
    764    if (!ctx)
    765       return VA_STATUS_ERROR_INVALID_CONTEXT;
    766 
    767    if (!filter_caps || !num_filter_caps)
    768       return VA_STATUS_ERROR_INVALID_PARAMETER;
    769 
    770    i = 0;
    771 
    772    switch (type) {
    773    case VAProcFilterNone:
    774       break;
    775    case VAProcFilterDeinterlacing: {
    776       VAProcFilterCapDeinterlacing *deint = filter_caps;
    777 
    778       if (*num_filter_caps < 3) {
    779          *num_filter_caps = 3;
    780          return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
    781       }
    782 
    783       deint[i++].type = VAProcDeinterlacingBob;
    784       deint[i++].type = VAProcDeinterlacingWeave;
    785       deint[i++].type = VAProcDeinterlacingMotionAdaptive;
    786       break;
    787    }
    788 
    789    case VAProcFilterNoiseReduction:
    790    case VAProcFilterSharpening:
    791    case VAProcFilterColorBalance:
    792    case VAProcFilterSkinToneEnhancement:
    793       return VA_STATUS_ERROR_UNIMPLEMENTED;
    794    default:
    795       assert(0);
    796    }
    797 
    798    *num_filter_caps = i;
    799 
    800    return VA_STATUS_SUCCESS;
    801 }
    802 
    803 static VAProcColorStandardType vpp_input_color_standards[] = {
    804    VAProcColorStandardBT601
    805 };
    806 
    807 static VAProcColorStandardType vpp_output_color_standards[] = {
    808    VAProcColorStandardBT601
    809 };
    810 
    811 VAStatus
    812 vlVaQueryVideoProcPipelineCaps(VADriverContextP ctx, VAContextID context,
    813                                VABufferID *filters, unsigned int num_filters,
    814                                VAProcPipelineCaps *pipeline_cap)
    815 {
    816    unsigned int i = 0;
    817 
    818    if (!ctx)
    819       return VA_STATUS_ERROR_INVALID_CONTEXT;
    820 
    821    if (!pipeline_cap)
    822       return VA_STATUS_ERROR_INVALID_PARAMETER;
    823 
    824    if (num_filters && !filters)
    825       return VA_STATUS_ERROR_INVALID_PARAMETER;
    826 
    827    pipeline_cap->pipeline_flags = 0;
    828    pipeline_cap->filter_flags = 0;
    829    pipeline_cap->num_forward_references = 0;
    830    pipeline_cap->num_backward_references = 0;
    831    pipeline_cap->num_input_color_standards = ARRAY_SIZE(vpp_input_color_standards);
    832    pipeline_cap->input_color_standards = vpp_input_color_standards;
    833    pipeline_cap->num_output_color_standards = ARRAY_SIZE(vpp_output_color_standards);
    834    pipeline_cap->output_color_standards = vpp_output_color_standards;
    835 
    836    for (i = 0; i < num_filters; i++) {
    837       vlVaBuffer *buf = handle_table_get(VL_VA_DRIVER(ctx)->htab, filters[i]);
    838       VAProcFilterParameterBufferBase *filter;
    839 
    840       if (!buf || buf->type != VAProcFilterParameterBufferType)
    841          return VA_STATUS_ERROR_INVALID_BUFFER;
    842 
    843       filter = buf->data;
    844       switch (filter->type) {
    845       case VAProcFilterDeinterlacing: {
    846          VAProcFilterParameterBufferDeinterlacing *deint = buf->data;
    847          if (deint->algorithm == VAProcDeinterlacingMotionAdaptive) {
    848             pipeline_cap->num_forward_references = 1;
    849             pipeline_cap->num_backward_references = 2;
    850          }
    851          break;
    852       }
    853       default:
    854          return VA_STATUS_ERROR_UNIMPLEMENTED;
    855       }
    856    }
    857 
    858    return VA_STATUS_SUCCESS;
    859 }
    860