Path: blob/21.2-virgl/src/gallium/frontends/va/surface.c
4561 views
/**************************************************************************1*2* Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian.3* Copyright 2014 Advanced Micro Devices, Inc.4* All Rights Reserved.5*6* Permission is hereby granted, free of charge, to any person obtaining a7* copy of this software and associated documentation files (the8* "Software"), to deal in the Software without restriction, including9* without limitation the rights to use, copy, modify, merge, publish,10* distribute, sub license, and/or sell copies of the Software, and to11* permit persons to whom the Software is furnished to do so, subject to12* the following conditions:13*14* The above copyright notice and this permission notice (including the15* next paragraph) shall be included in all copies or substantial portions16* of the Software.17*18* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS19* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF20* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.21* IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR22* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,23* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE24* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.25*26**************************************************************************/2728#include "pipe/p_screen.h"29#include "pipe/p_video_codec.h"3031#include "frontend/drm_driver.h"3233#include "util/u_memory.h"34#include "util/u_handle_table.h"35#include "util/u_rect.h"36#include "util/u_sampler.h"37#include "util/u_surface.h"38#include "util/u_video.h"3940#include "vl/vl_compositor.h"41#include "vl/vl_video_buffer.h"42#include "vl/vl_winsys.h"4344#include "va_private.h"4546#include <va/va_drmcommon.h>47#include "drm-uapi/drm_fourcc.h"4849static const enum pipe_format vpp_surface_formats[] = {50PIPE_FORMAT_B8G8R8A8_UNORM, PIPE_FORMAT_R8G8B8A8_UNORM,51PIPE_FORMAT_B8G8R8X8_UNORM, PIPE_FORMAT_R8G8B8X8_UNORM52};5354VAStatus55vlVaCreateSurfaces(VADriverContextP ctx, int width, int height, int format,56int num_surfaces, VASurfaceID *surfaces)57{58return vlVaCreateSurfaces2(ctx, format, width, height, surfaces, num_surfaces,59NULL, 0);60}6162VAStatus63vlVaDestroySurfaces(VADriverContextP ctx, VASurfaceID *surface_list, int num_surfaces)64{65vlVaDriver *drv;66int i;6768if (!ctx)69return VA_STATUS_ERROR_INVALID_CONTEXT;7071drv = VL_VA_DRIVER(ctx);72mtx_lock(&drv->mutex);73for (i = 0; i < num_surfaces; ++i) {74vlVaSurface *surf = handle_table_get(drv->htab, surface_list[i]);75if (!surf) {76mtx_unlock(&drv->mutex);77return VA_STATUS_ERROR_INVALID_SURFACE;78}79if (surf->buffer)80surf->buffer->destroy(surf->buffer);81util_dynarray_fini(&surf->subpics);82FREE(surf);83handle_table_remove(drv->htab, surface_list[i]);84}85mtx_unlock(&drv->mutex);8687return VA_STATUS_SUCCESS;88}8990VAStatus91vlVaSyncSurface(VADriverContextP ctx, VASurfaceID render_target)92{93vlVaDriver *drv;94vlVaContext *context;95vlVaSurface *surf;9697if (!ctx)98return VA_STATUS_ERROR_INVALID_CONTEXT;99100drv = VL_VA_DRIVER(ctx);101if (!drv)102return VA_STATUS_ERROR_INVALID_CONTEXT;103104mtx_lock(&drv->mutex);105surf = handle_table_get(drv->htab, render_target);106107if (!surf || !surf->buffer) {108mtx_unlock(&drv->mutex);109return VA_STATUS_ERROR_INVALID_SURFACE;110}111112if (!surf->feedback) {113// No outstanding operation: nothing to do.114mtx_unlock(&drv->mutex);115return VA_STATUS_SUCCESS;116}117118context = handle_table_get(drv->htab, surf->ctx);119if (!context) {120mtx_unlock(&drv->mutex);121return VA_STATUS_ERROR_INVALID_CONTEXT;122}123124if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) {125if (u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC) {126int frame_diff;127if (context->desc.h264enc.frame_num_cnt >= surf->frame_num_cnt)128frame_diff = context->desc.h264enc.frame_num_cnt - surf->frame_num_cnt;129else130frame_diff = 0xFFFFFFFF - surf->frame_num_cnt + 1 + context->desc.h264enc.frame_num_cnt;131if ((frame_diff == 0) &&132(surf->force_flushed == false) &&133(context->desc.h264enc.frame_num_cnt % 2 != 0)) {134context->decoder->flush(context->decoder);135context->first_single_submitted = true;136}137}138context->decoder->get_feedback(context->decoder, surf->feedback, &(surf->coded_buf->coded_size));139surf->feedback = NULL;140}141mtx_unlock(&drv->mutex);142return VA_STATUS_SUCCESS;143}144145VAStatus146vlVaQuerySurfaceStatus(VADriverContextP ctx, VASurfaceID render_target, VASurfaceStatus *status)147{148vlVaDriver *drv;149vlVaSurface *surf;150vlVaContext *context;151152if (!ctx)153return VA_STATUS_ERROR_INVALID_CONTEXT;154155drv = VL_VA_DRIVER(ctx);156if (!drv)157return VA_STATUS_ERROR_INVALID_CONTEXT;158159mtx_lock(&drv->mutex);160161surf = handle_table_get(drv->htab, render_target);162if (!surf || !surf->buffer) {163mtx_unlock(&drv->mutex);164return VA_STATUS_ERROR_INVALID_SURFACE;165}166167context = handle_table_get(drv->htab, surf->ctx);168if (!context) {169mtx_unlock(&drv->mutex);170return VA_STATUS_ERROR_INVALID_CONTEXT;171}172173if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) {174if(surf->feedback == NULL)175*status=VASurfaceReady;176else177*status=VASurfaceRendering;178}179180mtx_unlock(&drv->mutex);181182return VA_STATUS_SUCCESS;183}184185VAStatus186vlVaQuerySurfaceError(VADriverContextP ctx, VASurfaceID render_target, VAStatus error_status, void **error_info)187{188if (!ctx)189return VA_STATUS_ERROR_INVALID_CONTEXT;190191return VA_STATUS_ERROR_UNIMPLEMENTED;192}193194static void195upload_sampler(struct pipe_context *pipe, struct pipe_sampler_view *dst,196const struct pipe_box *dst_box, const void *src, unsigned src_stride,197unsigned src_x, unsigned src_y)198{199struct pipe_transfer *transfer;200void *map;201202map = pipe->texture_map(pipe, dst->texture, 0, PIPE_MAP_WRITE,203dst_box, &transfer);204if (!map)205return;206207util_copy_rect(map, dst->texture->format, transfer->stride, 0, 0,208dst_box->width, dst_box->height,209src, src_stride, src_x, src_y);210211pipe->texture_unmap(pipe, transfer);212}213214static VAStatus215vlVaPutSubpictures(vlVaSurface *surf, vlVaDriver *drv,216struct pipe_surface *surf_draw, struct u_rect *dirty_area,217struct u_rect *src_rect, struct u_rect *dst_rect)218{219vlVaSubpicture *sub;220int i;221222if (!(surf->subpics.data || surf->subpics.size))223return VA_STATUS_SUCCESS;224225for (i = 0; i < surf->subpics.size/sizeof(vlVaSubpicture *); i++) {226struct pipe_blend_state blend;227void *blend_state;228vlVaBuffer *buf;229struct pipe_box box;230struct u_rect *s, *d, sr, dr, c;231int sw, sh, dw, dh;232233sub = ((vlVaSubpicture **)surf->subpics.data)[i];234if (!sub)235continue;236237buf = handle_table_get(drv->htab, sub->image->buf);238if (!buf)239return VA_STATUS_ERROR_INVALID_IMAGE;240241box.x = 0;242box.y = 0;243box.z = 0;244box.width = sub->dst_rect.x1 - sub->dst_rect.x0;245box.height = sub->dst_rect.y1 - sub->dst_rect.y0;246box.depth = 1;247248s = &sub->src_rect;249d = &sub->dst_rect;250sw = s->x1 - s->x0;251sh = s->y1 - s->y0;252dw = d->x1 - d->x0;253dh = d->y1 - d->y0;254c.x0 = MAX2(d->x0, s->x0);255c.y0 = MAX2(d->y0, s->y0);256c.x1 = MIN2(d->x0 + dw, src_rect->x1);257c.y1 = MIN2(d->y0 + dh, src_rect->y1);258sr.x0 = s->x0 + (c.x0 - d->x0)*(sw/(float)dw);259sr.y0 = s->y0 + (c.y0 - d->y0)*(sh/(float)dh);260sr.x1 = s->x0 + (c.x1 - d->x0)*(sw/(float)dw);261sr.y1 = s->y0 + (c.y1 - d->y0)*(sh/(float)dh);262263s = src_rect;264d = dst_rect;265sw = s->x1 - s->x0;266sh = s->y1 - s->y0;267dw = d->x1 - d->x0;268dh = d->y1 - d->y0;269dr.x0 = d->x0 + c.x0*(dw/(float)sw);270dr.y0 = d->y0 + c.y0*(dh/(float)sh);271dr.x1 = d->x0 + c.x1*(dw/(float)sw);272dr.y1 = d->y0 + c.y1*(dh/(float)sh);273274memset(&blend, 0, sizeof(blend));275blend.independent_blend_enable = 0;276blend.rt[0].blend_enable = 1;277blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA;278blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;279blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO;280blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;281blend.rt[0].rgb_func = PIPE_BLEND_ADD;282blend.rt[0].alpha_func = PIPE_BLEND_ADD;283blend.rt[0].colormask = PIPE_MASK_RGBA;284blend.logicop_enable = 0;285blend.logicop_func = PIPE_LOGICOP_CLEAR;286blend.dither = 0;287blend_state = drv->pipe->create_blend_state(drv->pipe, &blend);288289vl_compositor_clear_layers(&drv->cstate);290vl_compositor_set_layer_blend(&drv->cstate, 0, blend_state, false);291upload_sampler(drv->pipe, sub->sampler, &box, buf->data,292sub->image->pitches[0], 0, 0);293vl_compositor_set_rgba_layer(&drv->cstate, &drv->compositor, 0, sub->sampler,294&sr, NULL, NULL);295vl_compositor_set_layer_dst_area(&drv->cstate, 0, &dr);296vl_compositor_render(&drv->cstate, &drv->compositor, surf_draw, dirty_area, false);297drv->pipe->delete_blend_state(drv->pipe, blend_state);298}299300return VA_STATUS_SUCCESS;301}302303VAStatus304vlVaPutSurface(VADriverContextP ctx, VASurfaceID surface_id, void* draw, short srcx, short srcy,305unsigned short srcw, unsigned short srch, short destx, short desty,306unsigned short destw, unsigned short desth, VARectangle *cliprects,307unsigned int number_cliprects, unsigned int flags)308{309vlVaDriver *drv;310vlVaSurface *surf;311struct pipe_screen *screen;312struct pipe_resource *tex;313struct pipe_surface surf_templ, *surf_draw;314struct vl_screen *vscreen;315struct u_rect src_rect, *dirty_area;316struct u_rect dst_rect = {destx, destx + destw, desty, desty + desth};317enum pipe_format format;318VAStatus status;319320if (!ctx)321return VA_STATUS_ERROR_INVALID_CONTEXT;322323drv = VL_VA_DRIVER(ctx);324mtx_lock(&drv->mutex);325surf = handle_table_get(drv->htab, surface_id);326if (!surf) {327mtx_unlock(&drv->mutex);328return VA_STATUS_ERROR_INVALID_SURFACE;329}330331screen = drv->pipe->screen;332vscreen = drv->vscreen;333334tex = vscreen->texture_from_drawable(vscreen, draw);335if (!tex) {336mtx_unlock(&drv->mutex);337return VA_STATUS_ERROR_INVALID_DISPLAY;338}339340dirty_area = vscreen->get_dirty_area(vscreen);341342memset(&surf_templ, 0, sizeof(surf_templ));343surf_templ.format = tex->format;344surf_draw = drv->pipe->create_surface(drv->pipe, tex, &surf_templ);345if (!surf_draw) {346pipe_resource_reference(&tex, NULL);347mtx_unlock(&drv->mutex);348return VA_STATUS_ERROR_INVALID_DISPLAY;349}350351src_rect.x0 = srcx;352src_rect.y0 = srcy;353src_rect.x1 = srcw + srcx;354src_rect.y1 = srch + srcy;355356format = surf->buffer->buffer_format;357358vl_compositor_clear_layers(&drv->cstate);359360if (format == PIPE_FORMAT_B8G8R8A8_UNORM || format == PIPE_FORMAT_B8G8R8X8_UNORM ||361format == PIPE_FORMAT_R8G8B8A8_UNORM || format == PIPE_FORMAT_R8G8B8X8_UNORM) {362struct pipe_sampler_view **views;363364views = surf->buffer->get_sampler_view_planes(surf->buffer);365vl_compositor_set_rgba_layer(&drv->cstate, &drv->compositor, 0, views[0], &src_rect, NULL, NULL);366} else367vl_compositor_set_buffer_layer(&drv->cstate, &drv->compositor, 0, surf->buffer, &src_rect, NULL, VL_COMPOSITOR_WEAVE);368369vl_compositor_set_layer_dst_area(&drv->cstate, 0, &dst_rect);370vl_compositor_render(&drv->cstate, &drv->compositor, surf_draw, dirty_area, true);371372status = vlVaPutSubpictures(surf, drv, surf_draw, dirty_area, &src_rect, &dst_rect);373if (status) {374mtx_unlock(&drv->mutex);375return status;376}377378/* flush before calling flush_frontbuffer so that rendering is flushed379* to back buffer so the texture can be copied in flush_frontbuffer380*/381drv->pipe->flush(drv->pipe, NULL, 0);382383screen->flush_frontbuffer(screen, drv->pipe, tex, 0, 0,384vscreen->get_private(vscreen), NULL);385386387pipe_resource_reference(&tex, NULL);388pipe_surface_reference(&surf_draw, NULL);389mtx_unlock(&drv->mutex);390391return VA_STATUS_SUCCESS;392}393394VAStatus395vlVaLockSurface(VADriverContextP ctx, VASurfaceID surface, unsigned int *fourcc,396unsigned int *luma_stride, unsigned int *chroma_u_stride, unsigned int *chroma_v_stride,397unsigned int *luma_offset, unsigned int *chroma_u_offset, unsigned int *chroma_v_offset,398unsigned int *buffer_name, void **buffer)399{400if (!ctx)401return VA_STATUS_ERROR_INVALID_CONTEXT;402403return VA_STATUS_ERROR_UNIMPLEMENTED;404}405406VAStatus407vlVaUnlockSurface(VADriverContextP ctx, VASurfaceID surface)408{409if (!ctx)410return VA_STATUS_ERROR_INVALID_CONTEXT;411412return VA_STATUS_ERROR_UNIMPLEMENTED;413}414415VAStatus416vlVaQuerySurfaceAttributes(VADriverContextP ctx, VAConfigID config_id,417VASurfaceAttrib *attrib_list, unsigned int *num_attribs)418{419vlVaDriver *drv;420vlVaConfig *config;421VASurfaceAttrib *attribs;422struct pipe_screen *pscreen;423int i, j;424425STATIC_ASSERT(ARRAY_SIZE(vpp_surface_formats) <= VL_VA_MAX_IMAGE_FORMATS);426427if (config_id == VA_INVALID_ID)428return VA_STATUS_ERROR_INVALID_CONFIG;429430if (!attrib_list && !num_attribs)431return VA_STATUS_ERROR_INVALID_PARAMETER;432433if (!attrib_list) {434*num_attribs = VL_VA_MAX_IMAGE_FORMATS + VASurfaceAttribCount;435return VA_STATUS_SUCCESS;436}437438if (!ctx)439return VA_STATUS_ERROR_INVALID_CONTEXT;440441drv = VL_VA_DRIVER(ctx);442443if (!drv)444return VA_STATUS_ERROR_INVALID_CONTEXT;445446mtx_lock(&drv->mutex);447config = handle_table_get(drv->htab, config_id);448mtx_unlock(&drv->mutex);449450if (!config)451return VA_STATUS_ERROR_INVALID_CONFIG;452453pscreen = VL_VA_PSCREEN(ctx);454455if (!pscreen)456return VA_STATUS_ERROR_INVALID_CONTEXT;457458attribs = CALLOC(VL_VA_MAX_IMAGE_FORMATS + VASurfaceAttribCount,459sizeof(VASurfaceAttrib));460461if (!attribs)462return VA_STATUS_ERROR_ALLOCATION_FAILED;463464i = 0;465466/* vlVaCreateConfig returns PIPE_VIDEO_PROFILE_UNKNOWN467* only for VAEntrypointVideoProc. */468if (config->profile == PIPE_VIDEO_PROFILE_UNKNOWN) {469if (config->rt_format & VA_RT_FORMAT_RGB32) {470for (j = 0; j < ARRAY_SIZE(vpp_surface_formats); ++j) {471attribs[i].type = VASurfaceAttribPixelFormat;472attribs[i].value.type = VAGenericValueTypeInteger;473attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;474attribs[i].value.value.i = PipeFormatToVaFourcc(vpp_surface_formats[j]);475i++;476}477}478}479if (config->rt_format & VA_RT_FORMAT_YUV420) {480attribs[i].type = VASurfaceAttribPixelFormat;481attribs[i].value.type = VAGenericValueTypeInteger;482attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;483attribs[i].value.value.i = VA_FOURCC_NV12;484i++;485}486if (config->rt_format & VA_RT_FORMAT_YUV420_10 ||487(config->rt_format & VA_RT_FORMAT_YUV420 &&488config->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE)) {489attribs[i].type = VASurfaceAttribPixelFormat;490attribs[i].value.type = VAGenericValueTypeInteger;491attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;492attribs[i].value.value.i = VA_FOURCC_P010;493i++;494attribs[i].type = VASurfaceAttribPixelFormat;495attribs[i].value.type = VAGenericValueTypeInteger;496attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;497attribs[i].value.value.i = VA_FOURCC_P016;498i++;499}500501attribs[i].type = VASurfaceAttribMemoryType;502attribs[i].value.type = VAGenericValueTypeInteger;503attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;504attribs[i].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_VA |505VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME |506VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2;507i++;508509attribs[i].type = VASurfaceAttribExternalBufferDescriptor;510attribs[i].value.type = VAGenericValueTypePointer;511attribs[i].flags = VA_SURFACE_ATTRIB_SETTABLE;512attribs[i].value.value.p = NULL; /* ignore */513i++;514515#ifdef HAVE_VA_SURFACE_ATTRIB_DRM_FORMAT_MODIFIERS516if (drv->pipe->create_video_buffer_with_modifiers) {517attribs[i].type = VASurfaceAttribDRMFormatModifiers;518attribs[i].value.type = VAGenericValueTypePointer;519attribs[i].flags = VA_SURFACE_ATTRIB_SETTABLE;520attribs[i].value.value.p = NULL; /* ignore */521i++;522}523#endif524525if (config->entrypoint != PIPE_VIDEO_ENTRYPOINT_UNKNOWN) {526attribs[i].type = VASurfaceAttribMaxWidth;527attribs[i].value.type = VAGenericValueTypeInteger;528attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE;529attribs[i].value.value.i =530pscreen->get_video_param(pscreen,531config->profile, config->entrypoint,532PIPE_VIDEO_CAP_MAX_WIDTH);533i++;534535attribs[i].type = VASurfaceAttribMaxHeight;536attribs[i].value.type = VAGenericValueTypeInteger;537attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE;538attribs[i].value.value.i =539pscreen->get_video_param(pscreen,540config->profile, config->entrypoint,541PIPE_VIDEO_CAP_MAX_HEIGHT);542i++;543} else {544attribs[i].type = VASurfaceAttribMaxWidth;545attribs[i].value.type = VAGenericValueTypeInteger;546attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE;547attribs[i].value.value.i = vl_video_buffer_max_size(pscreen);548i++;549550attribs[i].type = VASurfaceAttribMaxHeight;551attribs[i].value.type = VAGenericValueTypeInteger;552attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE;553attribs[i].value.value.i = vl_video_buffer_max_size(pscreen);554i++;555}556557if (i > *num_attribs) {558*num_attribs = i;559FREE(attribs);560return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;561}562563*num_attribs = i;564memcpy(attrib_list, attribs, i * sizeof(VASurfaceAttrib));565FREE(attribs);566567return VA_STATUS_SUCCESS;568}569570static VAStatus571surface_from_external_memory(VADriverContextP ctx, vlVaSurface *surface,572VASurfaceAttribExternalBuffers *memory_attribute,573unsigned index, struct pipe_video_buffer *templat)574{575vlVaDriver *drv;576struct pipe_screen *pscreen;577struct pipe_resource res_templ;578struct winsys_handle whandle;579struct pipe_resource *resources[VL_NUM_COMPONENTS];580enum pipe_format resource_formats[VL_NUM_COMPONENTS];581VAStatus result;582int i;583584pscreen = VL_VA_PSCREEN(ctx);585drv = VL_VA_DRIVER(ctx);586587if (!memory_attribute || !memory_attribute->buffers ||588index > memory_attribute->num_buffers)589return VA_STATUS_ERROR_INVALID_PARAMETER;590591if (surface->templat.width != memory_attribute->width ||592surface->templat.height != memory_attribute->height ||593memory_attribute->num_planes < 1)594return VA_STATUS_ERROR_INVALID_PARAMETER;595596if (memory_attribute->num_planes > VL_NUM_COMPONENTS)597return VA_STATUS_ERROR_INVALID_PARAMETER;598599vl_get_video_buffer_formats(pscreen, templat->buffer_format, resource_formats);600601memset(&res_templ, 0, sizeof(res_templ));602res_templ.target = PIPE_TEXTURE_2D;603res_templ.last_level = 0;604res_templ.depth0 = 1;605res_templ.array_size = 1;606res_templ.bind = PIPE_BIND_SAMPLER_VIEW;607res_templ.usage = PIPE_USAGE_DEFAULT;608609memset(&whandle, 0, sizeof(struct winsys_handle));610whandle.type = WINSYS_HANDLE_TYPE_FD;611whandle.handle = memory_attribute->buffers[index];612whandle.modifier = DRM_FORMAT_MOD_INVALID;613whandle.format = templat->buffer_format;614615// Create a resource for each plane.616memset(resources, 0, sizeof resources);617for (i = 0; i < memory_attribute->num_planes; i++) {618unsigned num_planes = util_format_get_num_planes(templat->buffer_format);619620res_templ.format = resource_formats[i];621if (res_templ.format == PIPE_FORMAT_NONE) {622if (i < num_planes) {623result = VA_STATUS_ERROR_INVALID_PARAMETER;624goto fail;625} else {626continue;627}628}629630res_templ.width0 = util_format_get_plane_width(templat->buffer_format, i,631memory_attribute->width);632res_templ.height0 = util_format_get_plane_height(templat->buffer_format, i,633memory_attribute->height);634635whandle.stride = memory_attribute->pitches[i];636whandle.offset = memory_attribute->offsets[i];637resources[i] = pscreen->resource_from_handle(pscreen, &res_templ, &whandle,638PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE);639if (!resources[i]) {640result = VA_STATUS_ERROR_ALLOCATION_FAILED;641goto fail;642}643}644645surface->buffer = vl_video_buffer_create_ex2(drv->pipe, templat, resources);646if (!surface->buffer) {647result = VA_STATUS_ERROR_ALLOCATION_FAILED;648goto fail;649}650return VA_STATUS_SUCCESS;651652fail:653for (i = 0; i < VL_NUM_COMPONENTS; i++)654pipe_resource_reference(&resources[i], NULL);655return result;656}657658static VAStatus659surface_from_prime_2(VADriverContextP ctx, vlVaSurface *surface,660VADRMPRIMESurfaceDescriptor *desc,661struct pipe_video_buffer *templat)662{663vlVaDriver *drv;664struct pipe_screen *pscreen;665struct pipe_resource res_templ;666struct winsys_handle whandle;667struct pipe_resource *resources[VL_NUM_COMPONENTS];668enum pipe_format resource_formats[VL_NUM_COMPONENTS];669unsigned num_format_planes, expected_planes, input_planes, plane;670VAStatus result;671672num_format_planes = util_format_get_num_planes(templat->buffer_format);673pscreen = VL_VA_PSCREEN(ctx);674drv = VL_VA_DRIVER(ctx);675676if (!desc || desc->num_layers >= 4 ||desc->num_objects == 0)677return VA_STATUS_ERROR_INVALID_PARAMETER;678679if (surface->templat.width != desc->width ||680surface->templat.height != desc->height ||681desc->num_layers < 1)682return VA_STATUS_ERROR_INVALID_PARAMETER;683684if (desc->num_layers != num_format_planes)685return VA_STATUS_ERROR_INVALID_PARAMETER;686687input_planes = 0;688for (unsigned i = 0; i < desc->num_layers; ++i) {689if (desc->layers[i].num_planes == 0 || desc->layers[i].num_planes > 4)690return VA_STATUS_ERROR_INVALID_PARAMETER;691692for (unsigned j = 0; j < desc->layers[i].num_planes; ++j)693if (desc->layers[i].object_index[j] >= desc->num_objects)694return VA_STATUS_ERROR_INVALID_PARAMETER;695696input_planes += desc->layers[i].num_planes;697}698699expected_planes = num_format_planes;700if (desc->objects[0].drm_format_modifier != DRM_FORMAT_MOD_INVALID &&701pscreen->is_dmabuf_modifier_supported &&702pscreen->is_dmabuf_modifier_supported(pscreen, desc->objects[0].drm_format_modifier,703templat->buffer_format, NULL) &&704pscreen->get_dmabuf_modifier_planes)705expected_planes = pscreen->get_dmabuf_modifier_planes(pscreen, desc->objects[0].drm_format_modifier,706templat->buffer_format);707708if (input_planes != expected_planes)709return VA_STATUS_ERROR_INVALID_PARAMETER;710711vl_get_video_buffer_formats(pscreen, templat->buffer_format, resource_formats);712713memset(&res_templ, 0, sizeof(res_templ));714res_templ.target = PIPE_TEXTURE_2D;715res_templ.last_level = 0;716res_templ.depth0 = 1;717res_templ.array_size = 1;718res_templ.width0 = desc->width;719res_templ.height0 = desc->height;720res_templ.bind = PIPE_BIND_SAMPLER_VIEW;721res_templ.usage = PIPE_USAGE_DEFAULT;722res_templ.format = templat->buffer_format;723724memset(&whandle, 0, sizeof(struct winsys_handle));725whandle.type = WINSYS_HANDLE_TYPE_FD;726whandle.format = templat->buffer_format;727whandle.modifier = desc->objects[0].drm_format_modifier;728729// Create a resource for each plane.730memset(resources, 0, sizeof resources);731732/* This does a backwards walk to set the next pointers. It interleaves so733* that the main planes always come first and then the first compression metadata734* plane of each main plane etc. */735plane = input_planes - 1;736for (int layer_plane = 3; layer_plane >= 0; --layer_plane) {737for (int layer = desc->num_layers - 1; layer >= 0; --layer) {738if (layer_plane >= desc->layers[layer].num_planes)739continue;740741if (plane < num_format_planes)742res_templ.format = resource_formats[plane];743744whandle.stride = desc->layers[layer].pitch[layer_plane];745whandle.offset = desc->layers[layer].offset[layer_plane];746whandle.handle = desc->objects[desc->layers[layer].object_index[layer_plane]].fd;747whandle.plane = plane;748749resources[plane] = pscreen->resource_from_handle(pscreen, &res_templ, &whandle,750PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE);751if (!resources[plane]) {752result = VA_STATUS_ERROR_ALLOCATION_FAILED;753goto fail;754}755756/* After the resource gets created the resource now owns the next reference. */757res_templ.next = NULL;758759if (plane)760pipe_resource_reference(&res_templ.next, resources[plane]);761--plane;762}763}764765surface->buffer = vl_video_buffer_create_ex2(drv->pipe, templat, resources);766if (!surface->buffer) {767result = VA_STATUS_ERROR_ALLOCATION_FAILED;768goto fail;769}770return VA_STATUS_SUCCESS;771772fail:773pipe_resource_reference(&res_templ.next, NULL);774for (int i = 0; i < VL_NUM_COMPONENTS; i++)775pipe_resource_reference(&resources[i], NULL);776return result;777}778779VAStatus780vlVaHandleSurfaceAllocate(vlVaDriver *drv, vlVaSurface *surface,781struct pipe_video_buffer *templat,782const uint64_t *modifiers,783unsigned int modifiers_count)784{785struct pipe_surface **surfaces;786unsigned i;787788if (modifiers_count > 0) {789if (!drv->pipe->create_video_buffer_with_modifiers)790return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED;791surface->buffer =792drv->pipe->create_video_buffer_with_modifiers(drv->pipe, templat,793modifiers,794modifiers_count);795} else {796surface->buffer = drv->pipe->create_video_buffer(drv->pipe, templat);797}798if (!surface->buffer)799return VA_STATUS_ERROR_ALLOCATION_FAILED;800801surfaces = surface->buffer->get_surfaces(surface->buffer);802for (i = 0; i < VL_MAX_SURFACES; ++i) {803union pipe_color_union c = {};804805if (!surfaces[i])806continue;807808if (i > !!surface->buffer->interlaced)809c.f[0] = c.f[1] = c.f[2] = c.f[3] = 0.5f;810811drv->pipe->clear_render_target(drv->pipe, surfaces[i], &c, 0, 0,812surfaces[i]->width, surfaces[i]->height,813false);814}815drv->pipe->flush(drv->pipe, NULL, 0);816817return VA_STATUS_SUCCESS;818}819820VAStatus821vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format,822unsigned int width, unsigned int height,823VASurfaceID *surfaces, unsigned int num_surfaces,824VASurfaceAttrib *attrib_list, unsigned int num_attribs)825{826vlVaDriver *drv;827VASurfaceAttribExternalBuffers *memory_attribute;828VADRMPRIMESurfaceDescriptor *prime_desc;829#ifdef HAVE_VA_SURFACE_ATTRIB_DRM_FORMAT_MODIFIERS830const VADRMFormatModifierList *modifier_list;831#endif832struct pipe_video_buffer templat;833struct pipe_screen *pscreen;834int i;835int memory_type;836int expected_fourcc;837VAStatus vaStatus;838vlVaSurface *surf;839bool protected;840const uint64_t *modifiers;841unsigned int modifiers_count;842843if (!ctx)844return VA_STATUS_ERROR_INVALID_CONTEXT;845846if (!(width && height))847return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT;848849drv = VL_VA_DRIVER(ctx);850851if (!drv)852return VA_STATUS_ERROR_INVALID_CONTEXT;853854pscreen = VL_VA_PSCREEN(ctx);855856if (!pscreen)857return VA_STATUS_ERROR_INVALID_CONTEXT;858859/* Default. */860memory_attribute = NULL;861prime_desc = NULL;862memory_type = VA_SURFACE_ATTRIB_MEM_TYPE_VA;863expected_fourcc = 0;864modifiers = NULL;865modifiers_count = 0;866867for (i = 0; i < num_attribs && attrib_list; i++) {868if (!(attrib_list[i].flags & VA_SURFACE_ATTRIB_SETTABLE))869continue;870871switch (attrib_list[i].type) {872case VASurfaceAttribPixelFormat:873if (attrib_list[i].value.type != VAGenericValueTypeInteger)874return VA_STATUS_ERROR_INVALID_PARAMETER;875expected_fourcc = attrib_list[i].value.value.i;876break;877case VASurfaceAttribMemoryType:878if (attrib_list[i].value.type != VAGenericValueTypeInteger)879return VA_STATUS_ERROR_INVALID_PARAMETER;880881switch (attrib_list[i].value.value.i) {882case VA_SURFACE_ATTRIB_MEM_TYPE_VA:883case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME:884case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2:885memory_type = attrib_list[i].value.value.i;886break;887default:888return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;889}890break;891case VASurfaceAttribExternalBufferDescriptor:892if (attrib_list[i].value.type != VAGenericValueTypePointer)893return VA_STATUS_ERROR_INVALID_PARAMETER;894if (memory_type == VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2)895prime_desc = (VADRMPRIMESurfaceDescriptor *)attrib_list[i].value.value.p;896else897memory_attribute = (VASurfaceAttribExternalBuffers *)attrib_list[i].value.value.p;898break;899#ifdef HAVE_VA_SURFACE_ATTRIB_DRM_FORMAT_MODIFIERS900case VASurfaceAttribDRMFormatModifiers:901if (attrib_list[i].value.type != VAGenericValueTypePointer)902return VA_STATUS_ERROR_INVALID_PARAMETER;903modifier_list = attrib_list[i].value.value.p;904modifiers = modifier_list->modifiers;905modifiers_count = modifier_list->num_modifiers;906break;907#endif908case VASurfaceAttribUsageHint:909if (attrib_list[i].value.type != VAGenericValueTypeInteger)910return VA_STATUS_ERROR_INVALID_PARAMETER;911break;912default:913return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED;914}915}916917protected = format & VA_RT_FORMAT_PROTECTED;918format &= ~VA_RT_FORMAT_PROTECTED;919920if (VA_RT_FORMAT_YUV420 != format &&921VA_RT_FORMAT_YUV422 != format &&922VA_RT_FORMAT_YUV444 != format &&923VA_RT_FORMAT_YUV420_10BPP != format &&924VA_RT_FORMAT_RGB32 != format) {925return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;926}927928switch (memory_type) {929case VA_SURFACE_ATTRIB_MEM_TYPE_VA:930break;931case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME:932if (!memory_attribute)933return VA_STATUS_ERROR_INVALID_PARAMETER;934if (modifiers)935return VA_STATUS_ERROR_INVALID_PARAMETER;936937expected_fourcc = memory_attribute->pixel_format;938break;939case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2:940if (!prime_desc)941return VA_STATUS_ERROR_INVALID_PARAMETER;942943expected_fourcc = prime_desc->fourcc;944break;945default:946assert(0);947}948949memset(&templat, 0, sizeof(templat));950951templat.buffer_format = pscreen->get_video_param(952pscreen,953PIPE_VIDEO_PROFILE_UNKNOWN,954PIPE_VIDEO_ENTRYPOINT_BITSTREAM,955PIPE_VIDEO_CAP_PREFERED_FORMAT956);957958if (modifiers)959templat.interlaced = false;960else961templat.interlaced =962pscreen->get_video_param(pscreen, PIPE_VIDEO_PROFILE_UNKNOWN,963PIPE_VIDEO_ENTRYPOINT_BITSTREAM,964PIPE_VIDEO_CAP_PREFERS_INTERLACED);965966if (expected_fourcc) {967enum pipe_format expected_format = VaFourccToPipeFormat(expected_fourcc);968969if (expected_format != templat.buffer_format || memory_attribute)970templat.interlaced = 0;971972templat.buffer_format = expected_format;973}974975templat.width = width;976templat.height = height;977if (protected)978templat.bind |= PIPE_BIND_PROTECTED;979980memset(surfaces, VA_INVALID_ID, num_surfaces * sizeof(VASurfaceID));981982mtx_lock(&drv->mutex);983for (i = 0; i < num_surfaces; i++) {984surf = CALLOC(1, sizeof(vlVaSurface));985if (!surf) {986vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;987goto no_res;988}989990surf->templat = templat;991992switch (memory_type) {993case VA_SURFACE_ATTRIB_MEM_TYPE_VA:994/* The application will clear the TILING flag when the surface is995* intended to be exported as dmabuf. Adding shared flag because not996* null memory_attribute means VASurfaceAttribExternalBuffers is used.997*/998if (memory_attribute &&999!(memory_attribute->flags & VA_SURFACE_EXTBUF_DESC_ENABLE_TILING))1000templat.bind = PIPE_BIND_LINEAR | PIPE_BIND_SHARED;10011002vaStatus = vlVaHandleSurfaceAllocate(drv, surf, &templat, modifiers,1003modifiers_count);1004if (vaStatus != VA_STATUS_SUCCESS)1005goto free_surf;1006break;10071008case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME:1009vaStatus = surface_from_external_memory(ctx, surf, memory_attribute, i, &templat);1010if (vaStatus != VA_STATUS_SUCCESS)1011goto free_surf;1012break;10131014case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2:1015vaStatus = surface_from_prime_2(ctx, surf, prime_desc, &templat);1016if (vaStatus != VA_STATUS_SUCCESS)1017goto free_surf;1018break;1019default:1020assert(0);1021}10221023util_dynarray_init(&surf->subpics, NULL);1024surfaces[i] = handle_table_add(drv->htab, surf);1025if (!surfaces[i]) {1026vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;1027goto destroy_surf;1028}1029}1030mtx_unlock(&drv->mutex);10311032return VA_STATUS_SUCCESS;10331034destroy_surf:1035surf->buffer->destroy(surf->buffer);10361037free_surf:1038FREE(surf);10391040no_res:1041mtx_unlock(&drv->mutex);1042if (i)1043vlVaDestroySurfaces(ctx, surfaces, i);10441045return vaStatus;1046}10471048VAStatus1049vlVaQueryVideoProcFilters(VADriverContextP ctx, VAContextID context,1050VAProcFilterType *filters, unsigned int *num_filters)1051{1052unsigned int num = 0;10531054if (!ctx)1055return VA_STATUS_ERROR_INVALID_CONTEXT;10561057if (!num_filters || !filters)1058return VA_STATUS_ERROR_INVALID_PARAMETER;10591060filters[num++] = VAProcFilterDeinterlacing;10611062*num_filters = num;10631064return VA_STATUS_SUCCESS;1065}10661067VAStatus1068vlVaQueryVideoProcFilterCaps(VADriverContextP ctx, VAContextID context,1069VAProcFilterType type, void *filter_caps,1070unsigned int *num_filter_caps)1071{1072unsigned int i;10731074if (!ctx)1075return VA_STATUS_ERROR_INVALID_CONTEXT;10761077if (!filter_caps || !num_filter_caps)1078return VA_STATUS_ERROR_INVALID_PARAMETER;10791080i = 0;10811082switch (type) {1083case VAProcFilterNone:1084break;1085case VAProcFilterDeinterlacing: {1086VAProcFilterCapDeinterlacing *deint = filter_caps;10871088if (*num_filter_caps < 3) {1089*num_filter_caps = 3;1090return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;1091}10921093deint[i++].type = VAProcDeinterlacingBob;1094deint[i++].type = VAProcDeinterlacingWeave;1095deint[i++].type = VAProcDeinterlacingMotionAdaptive;1096break;1097}10981099case VAProcFilterNoiseReduction:1100case VAProcFilterSharpening:1101case VAProcFilterColorBalance:1102case VAProcFilterSkinToneEnhancement:1103return VA_STATUS_ERROR_UNIMPLEMENTED;1104default:1105assert(0);1106}11071108*num_filter_caps = i;11091110return VA_STATUS_SUCCESS;1111}11121113static VAProcColorStandardType vpp_input_color_standards[] = {1114VAProcColorStandardBT6011115};11161117static VAProcColorStandardType vpp_output_color_standards[] = {1118VAProcColorStandardBT6011119};11201121VAStatus1122vlVaQueryVideoProcPipelineCaps(VADriverContextP ctx, VAContextID context,1123VABufferID *filters, unsigned int num_filters,1124VAProcPipelineCaps *pipeline_cap)1125{1126unsigned int i = 0;11271128if (!ctx)1129return VA_STATUS_ERROR_INVALID_CONTEXT;11301131if (!pipeline_cap)1132return VA_STATUS_ERROR_INVALID_PARAMETER;11331134if (num_filters && !filters)1135return VA_STATUS_ERROR_INVALID_PARAMETER;11361137pipeline_cap->pipeline_flags = 0;1138pipeline_cap->filter_flags = 0;1139pipeline_cap->num_forward_references = 0;1140pipeline_cap->num_backward_references = 0;1141pipeline_cap->num_input_color_standards = ARRAY_SIZE(vpp_input_color_standards);1142pipeline_cap->input_color_standards = vpp_input_color_standards;1143pipeline_cap->num_output_color_standards = ARRAY_SIZE(vpp_output_color_standards);1144pipeline_cap->output_color_standards = vpp_output_color_standards;11451146for (i = 0; i < num_filters; i++) {1147vlVaBuffer *buf = handle_table_get(VL_VA_DRIVER(ctx)->htab, filters[i]);1148VAProcFilterParameterBufferBase *filter;11491150if (!buf || buf->type != VAProcFilterParameterBufferType)1151return VA_STATUS_ERROR_INVALID_BUFFER;11521153filter = buf->data;1154switch (filter->type) {1155case VAProcFilterDeinterlacing: {1156VAProcFilterParameterBufferDeinterlacing *deint = buf->data;1157if (deint->algorithm == VAProcDeinterlacingMotionAdaptive) {1158pipeline_cap->num_forward_references = 2;1159pipeline_cap->num_backward_references = 1;1160}1161break;1162}1163default:1164return VA_STATUS_ERROR_UNIMPLEMENTED;1165}1166}11671168return VA_STATUS_SUCCESS;1169}11701171static uint32_t pipe_format_to_drm_format(enum pipe_format format)1172{1173switch (format) {1174case PIPE_FORMAT_R8_UNORM:1175return DRM_FORMAT_R8;1176case PIPE_FORMAT_R8G8_UNORM:1177return DRM_FORMAT_GR88;1178case PIPE_FORMAT_R16_UNORM:1179return DRM_FORMAT_R16;1180case PIPE_FORMAT_R16G16_UNORM:1181return DRM_FORMAT_GR1616;1182case PIPE_FORMAT_B8G8R8A8_UNORM:1183return DRM_FORMAT_ARGB8888;1184case PIPE_FORMAT_R8G8B8A8_UNORM:1185return DRM_FORMAT_ABGR8888;1186case PIPE_FORMAT_B8G8R8X8_UNORM:1187return DRM_FORMAT_XRGB8888;1188case PIPE_FORMAT_R8G8B8X8_UNORM:1189return DRM_FORMAT_XBGR8888;1190case PIPE_FORMAT_NV12:1191return DRM_FORMAT_NV12;1192case PIPE_FORMAT_P010:1193return DRM_FORMAT_P010;1194default:1195return DRM_FORMAT_INVALID;1196}1197}11981199#if VA_CHECK_VERSION(1, 1, 0)1200VAStatus1201vlVaExportSurfaceHandle(VADriverContextP ctx,1202VASurfaceID surface_id,1203uint32_t mem_type,1204uint32_t flags,1205void *descriptor)1206{1207vlVaDriver *drv;1208vlVaSurface *surf;1209struct pipe_surface **surfaces;1210struct pipe_screen *screen;1211VAStatus ret;1212unsigned int usage;1213int i, p;12141215VADRMPRIMESurfaceDescriptor *desc = descriptor;12161217if (mem_type != VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2)1218return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;12191220drv = VL_VA_DRIVER(ctx);1221screen = VL_VA_PSCREEN(ctx);1222mtx_lock(&drv->mutex);12231224surf = handle_table_get(drv->htab, surface_id);1225if (!surf || !surf->buffer) {1226mtx_unlock(&drv->mutex);1227return VA_STATUS_ERROR_INVALID_SURFACE;1228}12291230if (surf->buffer->interlaced) {1231struct pipe_video_buffer *interlaced = surf->buffer;1232struct u_rect src_rect, dst_rect;12331234surf->templat.interlaced = false;12351236ret = vlVaHandleSurfaceAllocate(drv, surf, &surf->templat, NULL, 0);1237if (ret != VA_STATUS_SUCCESS) {1238mtx_unlock(&drv->mutex);1239return VA_STATUS_ERROR_ALLOCATION_FAILED;1240}12411242src_rect.x0 = dst_rect.x0 = 0;1243src_rect.y0 = dst_rect.y0 = 0;1244src_rect.x1 = dst_rect.x1 = surf->templat.width;1245src_rect.y1 = dst_rect.y1 = surf->templat.height;12461247vl_compositor_yuv_deint_full(&drv->cstate, &drv->compositor,1248interlaced, surf->buffer,1249&src_rect, &dst_rect,1250VL_COMPOSITOR_WEAVE);12511252interlaced->destroy(interlaced);1253}12541255surfaces = surf->buffer->get_surfaces(surf->buffer);12561257usage = 0;1258if (flags & VA_EXPORT_SURFACE_WRITE_ONLY)1259usage |= PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE;12601261desc->fourcc = PipeFormatToVaFourcc(surf->buffer->buffer_format);1262desc->width = surf->buffer->width;1263desc->height = surf->buffer->height;12641265for (p = 0; p < VL_MAX_SURFACES; p++) {1266struct winsys_handle whandle;1267struct pipe_resource *resource;1268uint32_t drm_format;12691270if (!surfaces[p])1271break;12721273resource = surfaces[p]->texture;12741275drm_format = pipe_format_to_drm_format(resource->format);1276if (drm_format == DRM_FORMAT_INVALID) {1277ret = VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;1278goto fail;1279}12801281memset(&whandle, 0, sizeof(whandle));1282whandle.type = WINSYS_HANDLE_TYPE_FD;12831284if (!screen->resource_get_handle(screen, drv->pipe, resource,1285&whandle, usage)) {1286ret = VA_STATUS_ERROR_INVALID_SURFACE;1287goto fail;1288}12891290desc->objects[p].fd = (int)whandle.handle;1291desc->objects[p].size = 0;1292desc->objects[p].drm_format_modifier = whandle.modifier;12931294if (flags & VA_EXPORT_SURFACE_COMPOSED_LAYERS) {1295desc->layers[0].object_index[p] = p;1296desc->layers[0].offset[p] = whandle.offset;1297desc->layers[0].pitch[p] = whandle.stride;1298} else {1299desc->layers[p].drm_format = drm_format;1300desc->layers[p].num_planes = 1;1301desc->layers[p].object_index[0] = p;1302desc->layers[p].offset[0] = whandle.offset;1303desc->layers[p].pitch[0] = whandle.stride;1304}1305}13061307desc->num_objects = p;13081309if (flags & VA_EXPORT_SURFACE_COMPOSED_LAYERS) {1310uint32_t drm_format = pipe_format_to_drm_format(surf->buffer->buffer_format);1311if (drm_format == DRM_FORMAT_INVALID) {1312ret = VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;1313goto fail;1314}13151316desc->num_layers = 1;1317desc->layers[0].drm_format = drm_format;1318desc->layers[0].num_planes = p;1319} else {1320desc->num_layers = p;1321}13221323mtx_unlock(&drv->mutex);13241325return VA_STATUS_SUCCESS;13261327fail:1328for (i = 0; i < p; i++)1329close(desc->objects[i].fd);13301331mtx_unlock(&drv->mutex);13321333return ret;1334}1335#endif133613371338