~mmach/netext73/mesa-haswell

« back to all changes in this revision

Viewing changes to src/gallium/frontends/va/surface.c

  • Committer: mmach
  • Date: 2022-09-22 19:56:13 UTC
  • Revision ID: netbit73@gmail.com-20220922195613-wtik9mmy20tmor0i
2022-09-22 21:17:09

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/**************************************************************************
2
 
 *
3
 
 * Copyright 2010 Thomas Balling Sørensen & 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 "frontend/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
 
#include "util/u_video.h"
40
 
 
41
 
#include "vl/vl_compositor.h"
42
 
#include "vl/vl_video_buffer.h"
43
 
#include "vl/vl_winsys.h"
44
 
 
45
 
#include "va_private.h"
46
 
 
47
 
#include <va/va_drmcommon.h>
48
 
#include "drm-uapi/drm_fourcc.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
 
   mtx_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
 
         mtx_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
 
   mtx_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
 
   mtx_lock(&drv->mutex);
106
 
   surf = handle_table_get(drv->htab, render_target);
107
 
 
108
 
   if (!surf || !surf->buffer) {
109
 
      mtx_unlock(&drv->mutex);
110
 
      return VA_STATUS_ERROR_INVALID_SURFACE;
111
 
   }
112
 
 
113
 
   if (!surf->feedback) {
114
 
      // No outstanding operation: nothing to do.
115
 
      mtx_unlock(&drv->mutex);
116
 
      return VA_STATUS_SUCCESS;
117
 
   }
118
 
 
119
 
   context = handle_table_get(drv->htab, surf->ctx);
120
 
   if (!context) {
121
 
      mtx_unlock(&drv->mutex);
122
 
      return VA_STATUS_ERROR_INVALID_CONTEXT;
123
 
   }
124
 
 
125
 
   if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) {
126
 
      if (u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC) {
127
 
         int frame_diff;
128
 
         if (context->desc.h264enc.frame_num_cnt >= surf->frame_num_cnt)
129
 
            frame_diff = context->desc.h264enc.frame_num_cnt - surf->frame_num_cnt;
130
 
         else
131
 
            frame_diff = 0xFFFFFFFF - surf->frame_num_cnt + 1 + context->desc.h264enc.frame_num_cnt;
132
 
         if ((frame_diff == 0) &&
133
 
             (surf->force_flushed == false) &&
134
 
             (context->desc.h264enc.frame_num_cnt % 2 != 0)) {
135
 
            context->decoder->flush(context->decoder);
136
 
            context->first_single_submitted = true;
137
 
         }
138
 
      }
139
 
      context->decoder->get_feedback(context->decoder, surf->feedback, &(surf->coded_buf->coded_size));
140
 
      surf->feedback = NULL;
141
 
   }
142
 
   mtx_unlock(&drv->mutex);
143
 
   return VA_STATUS_SUCCESS;
144
 
}
145
 
 
146
 
VAStatus
147
 
vlVaQuerySurfaceStatus(VADriverContextP ctx, VASurfaceID render_target, VASurfaceStatus *status)
148
 
{
149
 
   vlVaDriver *drv;
150
 
   vlVaSurface *surf;
151
 
   vlVaContext *context;
152
 
 
153
 
   if (!ctx)
154
 
      return VA_STATUS_ERROR_INVALID_CONTEXT;
155
 
 
156
 
   drv = VL_VA_DRIVER(ctx);
157
 
   if (!drv)
158
 
      return VA_STATUS_ERROR_INVALID_CONTEXT;
159
 
 
160
 
   mtx_lock(&drv->mutex);
161
 
 
162
 
   surf = handle_table_get(drv->htab, render_target);
163
 
   if (!surf || !surf->buffer) {
164
 
      mtx_unlock(&drv->mutex);
165
 
      return VA_STATUS_ERROR_INVALID_SURFACE;
166
 
   }
167
 
 
168
 
   context = handle_table_get(drv->htab, surf->ctx);
169
 
   if (!context) {
170
 
      mtx_unlock(&drv->mutex);
171
 
      return VA_STATUS_ERROR_INVALID_CONTEXT;
172
 
   }
173
 
 
174
 
   if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) {
175
 
      if(surf->feedback == NULL)
176
 
         *status=VASurfaceReady;
177
 
      else
178
 
         *status=VASurfaceRendering;
179
 
   }
180
 
 
181
 
   mtx_unlock(&drv->mutex);
182
 
 
183
 
   return VA_STATUS_SUCCESS;
184
 
}
185
 
 
186
 
VAStatus
187
 
vlVaQuerySurfaceError(VADriverContextP ctx, VASurfaceID render_target, VAStatus error_status, void **error_info)
188
 
{
189
 
   if (!ctx)
190
 
      return VA_STATUS_ERROR_INVALID_CONTEXT;
191
 
 
192
 
   return VA_STATUS_ERROR_UNIMPLEMENTED;
193
 
}
194
 
 
195
 
static void
196
 
upload_sampler(struct pipe_context *pipe, struct pipe_sampler_view *dst,
197
 
               const struct pipe_box *dst_box, const void *src, unsigned src_stride,
198
 
               unsigned src_x, unsigned src_y)
199
 
{
200
 
   struct pipe_transfer *transfer;
201
 
   void *map;
202
 
 
203
 
   map = pipe->texture_map(pipe, dst->texture, 0, PIPE_MAP_WRITE,
204
 
                            dst_box, &transfer);
205
 
   if (!map)
206
 
      return;
207
 
 
208
 
   util_copy_rect(map, dst->texture->format, transfer->stride, 0, 0,
209
 
                  dst_box->width, dst_box->height,
210
 
                  src, src_stride, src_x, src_y);
211
 
 
212
 
   pipe->texture_unmap(pipe, transfer);
213
 
}
214
 
 
215
 
static VAStatus
216
 
vlVaPutSubpictures(vlVaSurface *surf, vlVaDriver *drv,
217
 
                   struct pipe_surface *surf_draw, struct u_rect *dirty_area,
218
 
                   struct u_rect *src_rect, struct u_rect *dst_rect)
219
 
{
220
 
   vlVaSubpicture *sub;
221
 
   int i;
222
 
 
223
 
   if (!(surf->subpics.data || surf->subpics.size))
224
 
      return VA_STATUS_SUCCESS;
225
 
 
226
 
   for (i = 0; i < surf->subpics.size/sizeof(vlVaSubpicture *); i++) {
227
 
      struct pipe_blend_state blend;
228
 
      void *blend_state;
229
 
      vlVaBuffer *buf;
230
 
      struct pipe_box box;
231
 
      struct u_rect *s, *d, sr, dr, c;
232
 
      int sw, sh, dw, dh;
233
 
 
234
 
      sub = ((vlVaSubpicture **)surf->subpics.data)[i];
235
 
      if (!sub)
236
 
         continue;
237
 
 
238
 
      buf = handle_table_get(drv->htab, sub->image->buf);
239
 
      if (!buf)
240
 
         return VA_STATUS_ERROR_INVALID_IMAGE;
241
 
 
242
 
      box.x = 0;
243
 
      box.y = 0;
244
 
      box.z = 0;
245
 
      box.width = sub->dst_rect.x1 - sub->dst_rect.x0;
246
 
      box.height = sub->dst_rect.y1 - sub->dst_rect.y0;
247
 
      box.depth = 1;
248
 
 
249
 
      s = &sub->src_rect;
250
 
      d = &sub->dst_rect;
251
 
      sw = s->x1 - s->x0;
252
 
      sh = s->y1 - s->y0;
253
 
      dw = d->x1 - d->x0;
254
 
      dh = d->y1 - d->y0;
255
 
      c.x0 = MAX2(d->x0, s->x0);
256
 
      c.y0 = MAX2(d->y0, s->y0);
257
 
      c.x1 = MIN2(d->x0 + dw, src_rect->x1);
258
 
      c.y1 = MIN2(d->y0 + dh, src_rect->y1);
259
 
      sr.x0 = s->x0 + (c.x0 - d->x0)*(sw/(float)dw);
260
 
      sr.y0 = s->y0 + (c.y0 - d->y0)*(sh/(float)dh);
261
 
      sr.x1 = s->x0 + (c.x1 - d->x0)*(sw/(float)dw);
262
 
      sr.y1 = s->y0 + (c.y1 - d->y0)*(sh/(float)dh);
263
 
 
264
 
      s = src_rect;
265
 
      d = dst_rect;
266
 
      sw = s->x1 - s->x0;
267
 
      sh = s->y1 - s->y0;
268
 
      dw = d->x1 - d->x0;
269
 
      dh = d->y1 - d->y0;
270
 
      dr.x0 = d->x0 + c.x0*(dw/(float)sw);
271
 
      dr.y0 = d->y0 + c.y0*(dh/(float)sh);
272
 
      dr.x1 = d->x0 + c.x1*(dw/(float)sw);
273
 
      dr.y1 = d->y0 + c.y1*(dh/(float)sh);
274
 
 
275
 
      memset(&blend, 0, sizeof(blend));
276
 
      blend.independent_blend_enable = 0;
277
 
      blend.rt[0].blend_enable = 1;
278
 
      blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
279
 
      blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
280
 
      blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO;
281
 
      blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
282
 
      blend.rt[0].rgb_func = PIPE_BLEND_ADD;
283
 
      blend.rt[0].alpha_func = PIPE_BLEND_ADD;
284
 
      blend.rt[0].colormask = PIPE_MASK_RGBA;
285
 
      blend.logicop_enable = 0;
286
 
      blend.logicop_func = PIPE_LOGICOP_CLEAR;
287
 
      blend.dither = 0;
288
 
      blend_state = drv->pipe->create_blend_state(drv->pipe, &blend);
289
 
 
290
 
      vl_compositor_clear_layers(&drv->cstate);
291
 
      vl_compositor_set_layer_blend(&drv->cstate, 0, blend_state, false);
292
 
      upload_sampler(drv->pipe, sub->sampler, &box, buf->data,
293
 
                     sub->image->pitches[0], 0, 0);
294
 
      vl_compositor_set_rgba_layer(&drv->cstate, &drv->compositor, 0, sub->sampler,
295
 
                                   &sr, NULL, NULL);
296
 
      vl_compositor_set_layer_dst_area(&drv->cstate, 0, &dr);
297
 
      vl_compositor_render(&drv->cstate, &drv->compositor, surf_draw, dirty_area, false);
298
 
      drv->pipe->delete_blend_state(drv->pipe, blend_state);
299
 
   }
300
 
 
301
 
   return VA_STATUS_SUCCESS;
302
 
}
303
 
 
304
 
VAStatus
305
 
vlVaPutSurface(VADriverContextP ctx, VASurfaceID surface_id, void* draw, short srcx, short srcy,
306
 
               unsigned short srcw, unsigned short srch, short destx, short desty,
307
 
               unsigned short destw, unsigned short desth, VARectangle *cliprects,
308
 
               unsigned int number_cliprects,  unsigned int flags)
309
 
{
310
 
   vlVaDriver *drv;
311
 
   vlVaSurface *surf;
312
 
   struct pipe_screen *screen;
313
 
   struct pipe_resource *tex;
314
 
   struct pipe_surface surf_templ, *surf_draw;
315
 
   struct vl_screen *vscreen;
316
 
   struct u_rect src_rect, *dirty_area;
317
 
   struct u_rect dst_rect = {destx, destx + destw, desty, desty + desth};
318
 
   enum pipe_format format;
319
 
   VAStatus status;
320
 
 
321
 
   if (!ctx)
322
 
      return VA_STATUS_ERROR_INVALID_CONTEXT;
323
 
 
324
 
   drv = VL_VA_DRIVER(ctx);
325
 
   mtx_lock(&drv->mutex);
326
 
   surf = handle_table_get(drv->htab, surface_id);
327
 
   if (!surf) {
328
 
      mtx_unlock(&drv->mutex);
329
 
      return VA_STATUS_ERROR_INVALID_SURFACE;
330
 
   }
331
 
 
332
 
   screen = drv->pipe->screen;
333
 
   vscreen = drv->vscreen;
334
 
 
335
 
   tex = vscreen->texture_from_drawable(vscreen, draw);
336
 
   if (!tex) {
337
 
      mtx_unlock(&drv->mutex);
338
 
      return VA_STATUS_ERROR_INVALID_DISPLAY;
339
 
   }
340
 
 
341
 
   dirty_area = vscreen->get_dirty_area(vscreen);
342
 
 
343
 
   memset(&surf_templ, 0, sizeof(surf_templ));
344
 
   surf_templ.format = tex->format;
345
 
   surf_draw = drv->pipe->create_surface(drv->pipe, tex, &surf_templ);
346
 
   if (!surf_draw) {
347
 
      pipe_resource_reference(&tex, NULL);
348
 
      mtx_unlock(&drv->mutex);
349
 
      return VA_STATUS_ERROR_INVALID_DISPLAY;
350
 
   }
351
 
 
352
 
   src_rect.x0 = srcx;
353
 
   src_rect.y0 = srcy;
354
 
   src_rect.x1 = srcw + srcx;
355
 
   src_rect.y1 = srch + srcy;
356
 
 
357
 
   format = surf->buffer->buffer_format;
358
 
 
359
 
   vl_compositor_clear_layers(&drv->cstate);
360
 
 
361
 
   if (format == PIPE_FORMAT_B8G8R8A8_UNORM || format == PIPE_FORMAT_B8G8R8X8_UNORM ||
362
 
       format == PIPE_FORMAT_R8G8B8A8_UNORM || format == PIPE_FORMAT_R8G8B8X8_UNORM) {
363
 
      struct pipe_sampler_view **views;
364
 
 
365
 
      views = surf->buffer->get_sampler_view_planes(surf->buffer);
366
 
      vl_compositor_set_rgba_layer(&drv->cstate, &drv->compositor, 0, views[0], &src_rect, NULL, NULL);
367
 
   } else
368
 
      vl_compositor_set_buffer_layer(&drv->cstate, &drv->compositor, 0, surf->buffer, &src_rect, NULL, VL_COMPOSITOR_WEAVE);
369
 
 
370
 
   vl_compositor_set_layer_dst_area(&drv->cstate, 0, &dst_rect);
371
 
   vl_compositor_render(&drv->cstate, &drv->compositor, surf_draw, dirty_area, true);
372
 
 
373
 
   status = vlVaPutSubpictures(surf, drv, surf_draw, dirty_area, &src_rect, &dst_rect);
374
 
   if (status) {
375
 
      mtx_unlock(&drv->mutex);
376
 
      return status;
377
 
   }
378
 
 
379
 
   /* flush before calling flush_frontbuffer so that rendering is flushed
380
 
    * to back buffer so the texture can be copied in flush_frontbuffer
381
 
    */
382
 
   drv->pipe->flush(drv->pipe, NULL, 0);
383
 
 
384
 
   screen->flush_frontbuffer(screen, drv->pipe, tex, 0, 0,
385
 
                             vscreen->get_private(vscreen), NULL);
386
 
 
387
 
 
388
 
   pipe_resource_reference(&tex, NULL);
389
 
   pipe_surface_reference(&surf_draw, NULL);
390
 
   mtx_unlock(&drv->mutex);
391
 
 
392
 
   return VA_STATUS_SUCCESS;
393
 
}
394
 
 
395
 
VAStatus
396
 
vlVaLockSurface(VADriverContextP ctx, VASurfaceID surface, unsigned int *fourcc,
397
 
                unsigned int *luma_stride, unsigned int *chroma_u_stride, unsigned int *chroma_v_stride,
398
 
                unsigned int *luma_offset, unsigned int *chroma_u_offset, unsigned int *chroma_v_offset,
399
 
                unsigned int *buffer_name, void **buffer)
400
 
{
401
 
   if (!ctx)
402
 
      return VA_STATUS_ERROR_INVALID_CONTEXT;
403
 
 
404
 
   return VA_STATUS_ERROR_UNIMPLEMENTED;
405
 
}
406
 
 
407
 
VAStatus
408
 
vlVaUnlockSurface(VADriverContextP ctx, VASurfaceID surface)
409
 
{
410
 
   if (!ctx)
411
 
      return VA_STATUS_ERROR_INVALID_CONTEXT;
412
 
 
413
 
   return VA_STATUS_ERROR_UNIMPLEMENTED;
414
 
}
415
 
 
416
 
VAStatus
417
 
vlVaQuerySurfaceAttributes(VADriverContextP ctx, VAConfigID config_id,
418
 
                           VASurfaceAttrib *attrib_list, unsigned int *num_attribs)
419
 
{
420
 
   vlVaDriver *drv;
421
 
   vlVaConfig *config;
422
 
   VASurfaceAttrib *attribs;
423
 
   struct pipe_screen *pscreen;
424
 
   int i, j;
425
 
 
426
 
   STATIC_ASSERT(ARRAY_SIZE(vpp_surface_formats) <= VL_VA_MAX_IMAGE_FORMATS);
427
 
 
428
 
   if (config_id == VA_INVALID_ID)
429
 
      return VA_STATUS_ERROR_INVALID_CONFIG;
430
 
 
431
 
   if (!attrib_list && !num_attribs)
432
 
      return VA_STATUS_ERROR_INVALID_PARAMETER;
433
 
 
434
 
   if (!attrib_list) {
435
 
      *num_attribs = VL_VA_MAX_IMAGE_FORMATS + VASurfaceAttribCount;
436
 
      return VA_STATUS_SUCCESS;
437
 
   }
438
 
 
439
 
   if (!ctx)
440
 
      return VA_STATUS_ERROR_INVALID_CONTEXT;
441
 
 
442
 
   drv = VL_VA_DRIVER(ctx);
443
 
 
444
 
   if (!drv)
445
 
      return VA_STATUS_ERROR_INVALID_CONTEXT;
446
 
 
447
 
   mtx_lock(&drv->mutex);
448
 
   config = handle_table_get(drv->htab, config_id);
449
 
   mtx_unlock(&drv->mutex);
450
 
 
451
 
   if (!config)
452
 
      return VA_STATUS_ERROR_INVALID_CONFIG;
453
 
 
454
 
   pscreen = VL_VA_PSCREEN(ctx);
455
 
 
456
 
   if (!pscreen)
457
 
      return VA_STATUS_ERROR_INVALID_CONTEXT;
458
 
 
459
 
   attribs = CALLOC(VL_VA_MAX_IMAGE_FORMATS + VASurfaceAttribCount,
460
 
                    sizeof(VASurfaceAttrib));
461
 
 
462
 
   if (!attribs)
463
 
      return VA_STATUS_ERROR_ALLOCATION_FAILED;
464
 
 
465
 
   i = 0;
466
 
 
467
 
   /* vlVaCreateConfig returns PIPE_VIDEO_PROFILE_UNKNOWN
468
 
    * only for VAEntrypointVideoProc. */
469
 
   if (config->profile == PIPE_VIDEO_PROFILE_UNKNOWN) {
470
 
      if (config->rt_format & VA_RT_FORMAT_RGB32) {
471
 
         for (j = 0; j < ARRAY_SIZE(vpp_surface_formats); ++j) {
472
 
            attribs[i].type = VASurfaceAttribPixelFormat;
473
 
            attribs[i].value.type = VAGenericValueTypeInteger;
474
 
            attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
475
 
            attribs[i].value.value.i = PipeFormatToVaFourcc(vpp_surface_formats[j]);
476
 
            i++;
477
 
         }
478
 
      }
479
 
   }
480
 
   if (config->rt_format & VA_RT_FORMAT_YUV420) {
481
 
      attribs[i].type = VASurfaceAttribPixelFormat;
482
 
      attribs[i].value.type = VAGenericValueTypeInteger;
483
 
      attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
484
 
      attribs[i].value.value.i = VA_FOURCC_NV12;
485
 
      i++;
486
 
   }
487
 
   if (config->rt_format & VA_RT_FORMAT_YUV420_10 ||
488
 
       (config->rt_format & VA_RT_FORMAT_YUV420 &&
489
 
        config->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE)) {
490
 
      attribs[i].type = VASurfaceAttribPixelFormat;
491
 
      attribs[i].value.type = VAGenericValueTypeInteger;
492
 
      attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
493
 
      attribs[i].value.value.i = VA_FOURCC_P010;
494
 
      i++;
495
 
      attribs[i].type = VASurfaceAttribPixelFormat;
496
 
      attribs[i].value.type = VAGenericValueTypeInteger;
497
 
      attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
498
 
      attribs[i].value.value.i = VA_FOURCC_P016;
499
 
      i++;
500
 
   }
501
 
 
502
 
   attribs[i].type = VASurfaceAttribMemoryType;
503
 
   attribs[i].value.type = VAGenericValueTypeInteger;
504
 
   attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
505
 
   attribs[i].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_VA |
506
 
         VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME |
507
 
         VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2;
508
 
   i++;
509
 
 
510
 
   attribs[i].type = VASurfaceAttribExternalBufferDescriptor;
511
 
   attribs[i].value.type = VAGenericValueTypePointer;
512
 
   attribs[i].flags = VA_SURFACE_ATTRIB_SETTABLE;
513
 
   attribs[i].value.value.p = NULL; /* ignore */
514
 
   i++;
515
 
 
516
 
#ifdef HAVE_VA_SURFACE_ATTRIB_DRM_FORMAT_MODIFIERS
517
 
   if (drv->pipe->create_video_buffer_with_modifiers) {
518
 
      attribs[i].type = VASurfaceAttribDRMFormatModifiers;
519
 
      attribs[i].value.type = VAGenericValueTypePointer;
520
 
      attribs[i].flags = VA_SURFACE_ATTRIB_SETTABLE;
521
 
      attribs[i].value.value.p = NULL; /* ignore */
522
 
      i++;
523
 
   }
524
 
#endif
525
 
 
526
 
   if (config->entrypoint != PIPE_VIDEO_ENTRYPOINT_UNKNOWN) {
527
 
      attribs[i].type = VASurfaceAttribMaxWidth;
528
 
      attribs[i].value.type = VAGenericValueTypeInteger;
529
 
      attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE;
530
 
      attribs[i].value.value.i =
531
 
         pscreen->get_video_param(pscreen,
532
 
                                  config->profile, config->entrypoint,
533
 
                                  PIPE_VIDEO_CAP_MAX_WIDTH);
534
 
      i++;
535
 
 
536
 
      attribs[i].type = VASurfaceAttribMaxHeight;
537
 
      attribs[i].value.type = VAGenericValueTypeInteger;
538
 
      attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE;
539
 
      attribs[i].value.value.i =
540
 
         pscreen->get_video_param(pscreen,
541
 
                                  config->profile, config->entrypoint,
542
 
                                  PIPE_VIDEO_CAP_MAX_HEIGHT);
543
 
      i++;
544
 
   } else {
545
 
      attribs[i].type = VASurfaceAttribMaxWidth;
546
 
      attribs[i].value.type = VAGenericValueTypeInteger;
547
 
      attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE;
548
 
      attribs[i].value.value.i = vl_video_buffer_max_size(pscreen);
549
 
      i++;
550
 
 
551
 
      attribs[i].type = VASurfaceAttribMaxHeight;
552
 
      attribs[i].value.type = VAGenericValueTypeInteger;
553
 
      attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE;
554
 
      attribs[i].value.value.i = vl_video_buffer_max_size(pscreen);
555
 
      i++;
556
 
   }
557
 
 
558
 
   if (i > *num_attribs) {
559
 
      *num_attribs = i;
560
 
      FREE(attribs);
561
 
      return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
562
 
   }
563
 
 
564
 
   *num_attribs = i;
565
 
   memcpy(attrib_list, attribs, i * sizeof(VASurfaceAttrib));
566
 
   FREE(attribs);
567
 
 
568
 
   return VA_STATUS_SUCCESS;
569
 
}
570
 
 
571
 
static VAStatus
572
 
surface_from_external_memory(VADriverContextP ctx, vlVaSurface *surface,
573
 
                             VASurfaceAttribExternalBuffers *memory_attribute,
574
 
                             unsigned index, struct pipe_video_buffer *templat)
575
 
{
576
 
   vlVaDriver *drv;
577
 
   struct pipe_screen *pscreen;
578
 
   struct pipe_resource res_templ;
579
 
   struct winsys_handle whandle;
580
 
   struct pipe_resource *resources[VL_NUM_COMPONENTS];
581
 
   enum pipe_format resource_formats[VL_NUM_COMPONENTS];
582
 
   VAStatus result;
583
 
   int i;
584
 
 
585
 
   pscreen = VL_VA_PSCREEN(ctx);
586
 
   drv = VL_VA_DRIVER(ctx);
587
 
 
588
 
   if (!memory_attribute || !memory_attribute->buffers ||
589
 
       index > memory_attribute->num_buffers)
590
 
      return VA_STATUS_ERROR_INVALID_PARAMETER;
591
 
 
592
 
   if (surface->templat.width != memory_attribute->width ||
593
 
       surface->templat.height != memory_attribute->height ||
594
 
       memory_attribute->num_planes < 1)
595
 
      return VA_STATUS_ERROR_INVALID_PARAMETER;
596
 
 
597
 
   if (memory_attribute->num_planes > VL_NUM_COMPONENTS)
598
 
      return VA_STATUS_ERROR_INVALID_PARAMETER;
599
 
 
600
 
   vl_get_video_buffer_formats(pscreen, templat->buffer_format, resource_formats);
601
 
 
602
 
   memset(&res_templ, 0, sizeof(res_templ));
603
 
   res_templ.target = PIPE_TEXTURE_2D;
604
 
   res_templ.last_level = 0;
605
 
   res_templ.depth0 = 1;
606
 
   res_templ.array_size = 1;
607
 
   res_templ.bind = PIPE_BIND_SAMPLER_VIEW;
608
 
   res_templ.usage = PIPE_USAGE_DEFAULT;
609
 
 
610
 
   memset(&whandle, 0, sizeof(struct winsys_handle));
611
 
   whandle.type = WINSYS_HANDLE_TYPE_FD;
612
 
   whandle.handle = memory_attribute->buffers[index];
613
 
   whandle.modifier = DRM_FORMAT_MOD_INVALID;
614
 
   whandle.format = templat->buffer_format;
615
 
 
616
 
   // Create a resource for each plane.
617
 
   memset(resources, 0, sizeof resources);
618
 
   for (i = 0; i < memory_attribute->num_planes; i++) {
619
 
      unsigned num_planes = util_format_get_num_planes(templat->buffer_format);
620
 
 
621
 
      res_templ.format = resource_formats[i];
622
 
      if (res_templ.format == PIPE_FORMAT_NONE) {
623
 
         if (i < num_planes) {
624
 
            result = VA_STATUS_ERROR_INVALID_PARAMETER;
625
 
            goto fail;
626
 
         } else {
627
 
            continue;
628
 
         }
629
 
      }
630
 
 
631
 
      res_templ.width0 = util_format_get_plane_width(templat->buffer_format, i,
632
 
                                                     memory_attribute->width);
633
 
      res_templ.height0 = util_format_get_plane_height(templat->buffer_format, i,
634
 
                                                       memory_attribute->height);
635
 
 
636
 
      whandle.stride = memory_attribute->pitches[i];
637
 
      whandle.offset = memory_attribute->offsets[i];
638
 
      resources[i] = pscreen->resource_from_handle(pscreen, &res_templ, &whandle,
639
 
                                                   PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE);
640
 
      if (!resources[i]) {
641
 
         result = VA_STATUS_ERROR_ALLOCATION_FAILED;
642
 
         goto fail;
643
 
      }
644
 
   }
645
 
 
646
 
   surface->buffer = vl_video_buffer_create_ex2(drv->pipe, templat, resources);
647
 
   if (!surface->buffer) {
648
 
      result = VA_STATUS_ERROR_ALLOCATION_FAILED;
649
 
      goto fail;
650
 
   }
651
 
   return VA_STATUS_SUCCESS;
652
 
 
653
 
fail:
654
 
   for (i = 0; i < VL_NUM_COMPONENTS; i++)
655
 
      pipe_resource_reference(&resources[i], NULL);
656
 
   return result;
657
 
}
658
 
 
659
 
static VAStatus
660
 
surface_from_prime_2(VADriverContextP ctx, vlVaSurface *surface,
661
 
                     VADRMPRIMESurfaceDescriptor *desc,
662
 
                     struct pipe_video_buffer *templat)
663
 
{
664
 
   vlVaDriver *drv;
665
 
   struct pipe_screen *pscreen;
666
 
   struct pipe_resource res_templ;
667
 
   struct winsys_handle whandle;
668
 
   struct pipe_resource *resources[VL_NUM_COMPONENTS];
669
 
   enum pipe_format resource_formats[VL_NUM_COMPONENTS];
670
 
   unsigned num_format_planes, expected_planes, input_planes, plane;
671
 
   VAStatus result;
672
 
 
673
 
   num_format_planes = util_format_get_num_planes(templat->buffer_format);
674
 
   pscreen = VL_VA_PSCREEN(ctx);
675
 
   drv = VL_VA_DRIVER(ctx);
676
 
 
677
 
   if (!desc || desc->num_layers >= 4 ||desc->num_objects == 0)
678
 
      return VA_STATUS_ERROR_INVALID_PARAMETER;
679
 
 
680
 
   if (surface->templat.width != desc->width ||
681
 
       surface->templat.height != desc->height ||
682
 
       desc->num_layers < 1)
683
 
      return VA_STATUS_ERROR_INVALID_PARAMETER;
684
 
 
685
 
   if (desc->num_layers != num_format_planes)
686
 
      return VA_STATUS_ERROR_INVALID_PARAMETER;
687
 
 
688
 
   input_planes = 0;
689
 
   for (unsigned i = 0; i < desc->num_layers; ++i) {
690
 
      if (desc->layers[i].num_planes == 0 || desc->layers[i].num_planes > 4)
691
 
         return VA_STATUS_ERROR_INVALID_PARAMETER;
692
 
 
693
 
      for (unsigned j = 0; j < desc->layers[i].num_planes; ++j)
694
 
         if (desc->layers[i].object_index[j] >= desc->num_objects)
695
 
            return VA_STATUS_ERROR_INVALID_PARAMETER;
696
 
 
697
 
      input_planes += desc->layers[i].num_planes;
698
 
   }
699
 
 
700
 
   expected_planes = num_format_planes;
701
 
   if (desc->objects[0].drm_format_modifier != DRM_FORMAT_MOD_INVALID &&
702
 
       pscreen->is_dmabuf_modifier_supported &&
703
 
       pscreen->is_dmabuf_modifier_supported(pscreen, desc->objects[0].drm_format_modifier,
704
 
                                            templat->buffer_format, NULL) &&
705
 
       pscreen->get_dmabuf_modifier_planes)
706
 
      expected_planes = pscreen->get_dmabuf_modifier_planes(pscreen, desc->objects[0].drm_format_modifier,
707
 
                                                           templat->buffer_format);
708
 
 
709
 
   if (input_planes != expected_planes)
710
 
      return VA_STATUS_ERROR_INVALID_PARAMETER;
711
 
 
712
 
   vl_get_video_buffer_formats(pscreen, templat->buffer_format, resource_formats);
713
 
 
714
 
   memset(&res_templ, 0, sizeof(res_templ));
715
 
   res_templ.target = PIPE_TEXTURE_2D;
716
 
   res_templ.last_level = 0;
717
 
   res_templ.depth0 = 1;
718
 
   res_templ.array_size = 1;
719
 
   res_templ.width0 = desc->width;
720
 
   res_templ.height0 = desc->height;
721
 
   res_templ.bind = PIPE_BIND_SAMPLER_VIEW;
722
 
   res_templ.usage = PIPE_USAGE_DEFAULT;
723
 
   res_templ.format = templat->buffer_format;
724
 
 
725
 
   memset(&whandle, 0, sizeof(struct winsys_handle));
726
 
   whandle.type = WINSYS_HANDLE_TYPE_FD;
727
 
   whandle.format = templat->buffer_format;
728
 
   whandle.modifier = desc->objects[0].drm_format_modifier;
729
 
 
730
 
   // Create a resource for each plane.
731
 
   memset(resources, 0, sizeof resources);
732
 
 
733
 
   /* This does a backwards walk to set the next pointers. It interleaves so
734
 
    * that the main planes always come first and then the first compression metadata
735
 
    * plane of each main plane etc. */
736
 
   plane = input_planes - 1;
737
 
   for (int layer_plane = 3; layer_plane >= 0; --layer_plane) {
738
 
      for (int layer = desc->num_layers - 1; layer >= 0; --layer) {
739
 
         if (layer_plane >= desc->layers[layer].num_planes)
740
 
            continue;
741
 
 
742
 
         if (plane < num_format_planes)
743
 
            res_templ.format = resource_formats[plane];
744
 
 
745
 
         whandle.stride = desc->layers[layer].pitch[layer_plane];
746
 
         whandle.offset = desc->layers[layer].offset[layer_plane];
747
 
         whandle.handle = desc->objects[desc->layers[layer].object_index[layer_plane]].fd;
748
 
         whandle.plane = plane;
749
 
 
750
 
         resources[plane] = pscreen->resource_from_handle(pscreen, &res_templ, &whandle,
751
 
                                                          PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE);
752
 
         if (!resources[plane]) {
753
 
            result = VA_STATUS_ERROR_ALLOCATION_FAILED;
754
 
            goto fail;
755
 
         }
756
 
 
757
 
         /* After the resource gets created the resource now owns the next reference. */
758
 
         res_templ.next = NULL;
759
 
 
760
 
         if (plane)
761
 
            pipe_resource_reference(&res_templ.next, resources[plane]);
762
 
         --plane;
763
 
      }
764
 
   }
765
 
 
766
 
   surface->buffer = vl_video_buffer_create_ex2(drv->pipe, templat, resources);
767
 
   if (!surface->buffer) {
768
 
      result = VA_STATUS_ERROR_ALLOCATION_FAILED;
769
 
      goto fail;
770
 
   }
771
 
   return VA_STATUS_SUCCESS;
772
 
 
773
 
fail:
774
 
   pipe_resource_reference(&res_templ.next, NULL);
775
 
   for (int i = 0; i < VL_NUM_COMPONENTS; i++)
776
 
      pipe_resource_reference(&resources[i], NULL);
777
 
   return result;
778
 
}
779
 
 
780
 
VAStatus
781
 
vlVaHandleSurfaceAllocate(vlVaDriver *drv, vlVaSurface *surface,
782
 
                          struct pipe_video_buffer *templat,
783
 
                          const uint64_t *modifiers,
784
 
                          unsigned int modifiers_count)
785
 
{
786
 
   struct pipe_surface **surfaces;
787
 
   unsigned i;
788
 
 
789
 
   if (modifiers_count > 0) {
790
 
      if (!drv->pipe->create_video_buffer_with_modifiers)
791
 
         return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED;
792
 
      surface->buffer =
793
 
         drv->pipe->create_video_buffer_with_modifiers(drv->pipe, templat,
794
 
                                                       modifiers,
795
 
                                                       modifiers_count);
796
 
   } else {
797
 
      surface->buffer = drv->pipe->create_video_buffer(drv->pipe, templat);
798
 
   }
799
 
   if (!surface->buffer)
800
 
      return VA_STATUS_ERROR_ALLOCATION_FAILED;
801
 
 
802
 
   surfaces = surface->buffer->get_surfaces(surface->buffer);
803
 
   for (i = 0; i < VL_MAX_SURFACES; ++i) {
804
 
      union pipe_color_union c = {};
805
 
 
806
 
      if (!surfaces[i])
807
 
         continue;
808
 
 
809
 
      if (i > !!surface->buffer->interlaced)
810
 
         c.f[0] = c.f[1] = c.f[2] = c.f[3] = 0.5f;
811
 
 
812
 
      drv->pipe->clear_render_target(drv->pipe, surfaces[i], &c, 0, 0,
813
 
                                     surfaces[i]->width, surfaces[i]->height,
814
 
                                     false);
815
 
   }
816
 
   drv->pipe->flush(drv->pipe, NULL, 0);
817
 
 
818
 
   return VA_STATUS_SUCCESS;
819
 
}
820
 
 
821
 
VAStatus
822
 
vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format,
823
 
                    unsigned int width, unsigned int height,
824
 
                    VASurfaceID *surfaces, unsigned int num_surfaces,
825
 
                    VASurfaceAttrib *attrib_list, unsigned int num_attribs)
826
 
{
827
 
   vlVaDriver *drv;
828
 
   VASurfaceAttribExternalBuffers *memory_attribute;
829
 
   VADRMPRIMESurfaceDescriptor *prime_desc;
830
 
#ifdef HAVE_VA_SURFACE_ATTRIB_DRM_FORMAT_MODIFIERS
831
 
   const VADRMFormatModifierList *modifier_list;
832
 
#endif
833
 
   struct pipe_video_buffer templat;
834
 
   struct pipe_screen *pscreen;
835
 
   int i;
836
 
   int memory_type;
837
 
   int expected_fourcc;
838
 
   VAStatus vaStatus;
839
 
   vlVaSurface *surf;
840
 
   bool protected;
841
 
   const uint64_t *modifiers;
842
 
   unsigned int modifiers_count;
843
 
 
844
 
   if (!ctx)
845
 
      return VA_STATUS_ERROR_INVALID_CONTEXT;
846
 
 
847
 
   if (!(width && height))
848
 
      return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT;
849
 
 
850
 
   drv = VL_VA_DRIVER(ctx);
851
 
 
852
 
   if (!drv)
853
 
      return VA_STATUS_ERROR_INVALID_CONTEXT;
854
 
 
855
 
   pscreen = VL_VA_PSCREEN(ctx);
856
 
 
857
 
   if (!pscreen)
858
 
      return VA_STATUS_ERROR_INVALID_CONTEXT;
859
 
 
860
 
   /* Default. */
861
 
   memory_attribute = NULL;
862
 
   prime_desc = NULL;
863
 
   memory_type = VA_SURFACE_ATTRIB_MEM_TYPE_VA;
864
 
   expected_fourcc = 0;
865
 
   modifiers = NULL;
866
 
   modifiers_count = 0;
867
 
 
868
 
   for (i = 0; i < num_attribs && attrib_list; i++) {
869
 
      if (!(attrib_list[i].flags & VA_SURFACE_ATTRIB_SETTABLE))
870
 
         continue;
871
 
 
872
 
      switch (attrib_list[i].type) {
873
 
      case VASurfaceAttribPixelFormat:
874
 
         if (attrib_list[i].value.type != VAGenericValueTypeInteger)
875
 
            return VA_STATUS_ERROR_INVALID_PARAMETER;
876
 
         expected_fourcc = attrib_list[i].value.value.i;
877
 
         break;
878
 
      case VASurfaceAttribMemoryType:
879
 
         if (attrib_list[i].value.type != VAGenericValueTypeInteger)
880
 
            return VA_STATUS_ERROR_INVALID_PARAMETER;
881
 
 
882
 
         switch (attrib_list[i].value.value.i) {
883
 
         case VA_SURFACE_ATTRIB_MEM_TYPE_VA:
884
 
         case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME:
885
 
         case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2:
886
 
            memory_type = attrib_list[i].value.value.i;
887
 
            break;
888
 
         default:
889
 
            return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;
890
 
         }
891
 
         break;
892
 
      case VASurfaceAttribExternalBufferDescriptor:
893
 
         if (attrib_list[i].value.type != VAGenericValueTypePointer)
894
 
            return VA_STATUS_ERROR_INVALID_PARAMETER;
895
 
         if (memory_type == VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2)
896
 
            prime_desc = (VADRMPRIMESurfaceDescriptor *)attrib_list[i].value.value.p;
897
 
         else
898
 
            memory_attribute = (VASurfaceAttribExternalBuffers *)attrib_list[i].value.value.p;
899
 
         break;
900
 
#ifdef HAVE_VA_SURFACE_ATTRIB_DRM_FORMAT_MODIFIERS
901
 
      case VASurfaceAttribDRMFormatModifiers:
902
 
         if (attrib_list[i].value.type != VAGenericValueTypePointer)
903
 
            return VA_STATUS_ERROR_INVALID_PARAMETER;
904
 
         modifier_list = attrib_list[i].value.value.p;
905
 
         if (modifier_list != NULL) {
906
 
            modifiers = modifier_list->modifiers;
907
 
            modifiers_count = modifier_list->num_modifiers;
908
 
         }
909
 
         break;
910
 
#endif
911
 
      case VASurfaceAttribUsageHint:
912
 
         if (attrib_list[i].value.type != VAGenericValueTypeInteger)
913
 
            return VA_STATUS_ERROR_INVALID_PARAMETER;
914
 
         break;
915
 
      default:
916
 
         return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED;
917
 
      }
918
 
   }
919
 
 
920
 
   protected = format & VA_RT_FORMAT_PROTECTED;
921
 
   format &= ~VA_RT_FORMAT_PROTECTED;
922
 
 
923
 
   if (VA_RT_FORMAT_YUV420 != format &&
924
 
       VA_RT_FORMAT_YUV422 != format &&
925
 
       VA_RT_FORMAT_YUV444 != format &&
926
 
       VA_RT_FORMAT_YUV420_10BPP != format &&
927
 
       VA_RT_FORMAT_RGB32  != format) {
928
 
      return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
929
 
   }
930
 
 
931
 
   switch (memory_type) {
932
 
   case VA_SURFACE_ATTRIB_MEM_TYPE_VA:
933
 
      break;
934
 
   case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME:
935
 
      if (!memory_attribute)
936
 
         return VA_STATUS_ERROR_INVALID_PARAMETER;
937
 
      if (modifiers)
938
 
         return VA_STATUS_ERROR_INVALID_PARAMETER;
939
 
 
940
 
      expected_fourcc = memory_attribute->pixel_format;
941
 
      break;
942
 
   case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2:
943
 
      if (!prime_desc)
944
 
         return VA_STATUS_ERROR_INVALID_PARAMETER;
945
 
 
946
 
      expected_fourcc = prime_desc->fourcc;
947
 
      break;
948
 
   default:
949
 
      assert(0);
950
 
   }
951
 
 
952
 
   memset(&templat, 0, sizeof(templat));
953
 
 
954
 
   templat.buffer_format = pscreen->get_video_param(
955
 
      pscreen,
956
 
      PIPE_VIDEO_PROFILE_UNKNOWN,
957
 
      PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
958
 
      PIPE_VIDEO_CAP_PREFERED_FORMAT
959
 
   );
960
 
 
961
 
   if (modifiers)
962
 
      templat.interlaced = false;
963
 
   else
964
 
      templat.interlaced =
965
 
         pscreen->get_video_param(pscreen, PIPE_VIDEO_PROFILE_UNKNOWN,
966
 
                                  PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
967
 
                                  PIPE_VIDEO_CAP_PREFERS_INTERLACED);
968
 
 
969
 
   if (expected_fourcc) {
970
 
      enum pipe_format expected_format = VaFourccToPipeFormat(expected_fourcc);
971
 
 
972
 
      if (expected_format != templat.buffer_format || memory_attribute)
973
 
        templat.interlaced = 0;
974
 
 
975
 
      templat.buffer_format = expected_format;
976
 
   }
977
 
 
978
 
   templat.width = width;
979
 
   templat.height = height;
980
 
   if (protected)
981
 
      templat.bind |= PIPE_BIND_PROTECTED;
982
 
 
983
 
   memset(surfaces, VA_INVALID_ID, num_surfaces * sizeof(VASurfaceID));
984
 
 
985
 
   mtx_lock(&drv->mutex);
986
 
   for (i = 0; i < num_surfaces; i++) {
987
 
      surf = CALLOC(1, sizeof(vlVaSurface));
988
 
      if (!surf) {
989
 
         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
990
 
         goto no_res;
991
 
      }
992
 
 
993
 
      surf->templat = templat;
994
 
 
995
 
      switch (memory_type) {
996
 
      case VA_SURFACE_ATTRIB_MEM_TYPE_VA:
997
 
         /* The application will clear the TILING flag when the surface is
998
 
          * intended to be exported as dmabuf. Adding shared flag because not
999
 
          * null memory_attribute means VASurfaceAttribExternalBuffers is used.
1000
 
          */
1001
 
         if (memory_attribute &&
1002
 
             !(memory_attribute->flags & VA_SURFACE_EXTBUF_DESC_ENABLE_TILING))
1003
 
            templat.bind = PIPE_BIND_LINEAR | PIPE_BIND_SHARED;
1004
 
 
1005
 
         vaStatus = vlVaHandleSurfaceAllocate(drv, surf, &templat, modifiers,
1006
 
                                              modifiers_count);
1007
 
         if (vaStatus != VA_STATUS_SUCCESS)
1008
 
            goto free_surf;
1009
 
         break;
1010
 
 
1011
 
      case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME:
1012
 
         vaStatus = surface_from_external_memory(ctx, surf, memory_attribute, i, &templat);
1013
 
         if (vaStatus != VA_STATUS_SUCCESS)
1014
 
            goto free_surf;
1015
 
         break;
1016
 
 
1017
 
      case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2:
1018
 
         vaStatus = surface_from_prime_2(ctx, surf, prime_desc, &templat);
1019
 
         if (vaStatus != VA_STATUS_SUCCESS)
1020
 
            goto free_surf;
1021
 
         break;
1022
 
      default:
1023
 
         assert(0);
1024
 
      }
1025
 
 
1026
 
      util_dynarray_init(&surf->subpics, NULL);
1027
 
      surfaces[i] = handle_table_add(drv->htab, surf);
1028
 
      if (!surfaces[i]) {
1029
 
         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1030
 
         goto destroy_surf;
1031
 
      }
1032
 
   }
1033
 
   mtx_unlock(&drv->mutex);
1034
 
 
1035
 
   return VA_STATUS_SUCCESS;
1036
 
 
1037
 
destroy_surf:
1038
 
   surf->buffer->destroy(surf->buffer);
1039
 
 
1040
 
free_surf:
1041
 
   FREE(surf);
1042
 
 
1043
 
no_res:
1044
 
   mtx_unlock(&drv->mutex);
1045
 
   if (i)
1046
 
      vlVaDestroySurfaces(ctx, surfaces, i);
1047
 
 
1048
 
   return vaStatus;
1049
 
}
1050
 
 
1051
 
VAStatus
1052
 
vlVaQueryVideoProcFilters(VADriverContextP ctx, VAContextID context,
1053
 
                          VAProcFilterType *filters, unsigned int *num_filters)
1054
 
{
1055
 
   unsigned int num = 0;
1056
 
 
1057
 
   if (!ctx)
1058
 
      return VA_STATUS_ERROR_INVALID_CONTEXT;
1059
 
 
1060
 
   if (!num_filters || !filters)
1061
 
      return VA_STATUS_ERROR_INVALID_PARAMETER;
1062
 
 
1063
 
   filters[num++] = VAProcFilterDeinterlacing;
1064
 
 
1065
 
   *num_filters = num;
1066
 
 
1067
 
   return VA_STATUS_SUCCESS;
1068
 
}
1069
 
 
1070
 
VAStatus
1071
 
vlVaQueryVideoProcFilterCaps(VADriverContextP ctx, VAContextID context,
1072
 
                             VAProcFilterType type, void *filter_caps,
1073
 
                             unsigned int *num_filter_caps)
1074
 
{
1075
 
   unsigned int i;
1076
 
 
1077
 
   if (!ctx)
1078
 
      return VA_STATUS_ERROR_INVALID_CONTEXT;
1079
 
 
1080
 
   if (!filter_caps || !num_filter_caps)
1081
 
      return VA_STATUS_ERROR_INVALID_PARAMETER;
1082
 
 
1083
 
   i = 0;
1084
 
 
1085
 
   switch (type) {
1086
 
   case VAProcFilterNone:
1087
 
      break;
1088
 
   case VAProcFilterDeinterlacing: {
1089
 
      VAProcFilterCapDeinterlacing *deint = filter_caps;
1090
 
 
1091
 
      if (*num_filter_caps < 3) {
1092
 
         *num_filter_caps = 3;
1093
 
         return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
1094
 
      }
1095
 
 
1096
 
      deint[i++].type = VAProcDeinterlacingBob;
1097
 
      deint[i++].type = VAProcDeinterlacingWeave;
1098
 
      deint[i++].type = VAProcDeinterlacingMotionAdaptive;
1099
 
      break;
1100
 
   }
1101
 
 
1102
 
   case VAProcFilterNoiseReduction:
1103
 
   case VAProcFilterSharpening:
1104
 
   case VAProcFilterColorBalance:
1105
 
   case VAProcFilterSkinToneEnhancement:
1106
 
      return VA_STATUS_ERROR_UNIMPLEMENTED;
1107
 
   default:
1108
 
      assert(0);
1109
 
   }
1110
 
 
1111
 
   *num_filter_caps = i;
1112
 
 
1113
 
   return VA_STATUS_SUCCESS;
1114
 
}
1115
 
 
1116
 
static VAProcColorStandardType vpp_input_color_standards[] = {
1117
 
   VAProcColorStandardBT601
1118
 
};
1119
 
 
1120
 
static VAProcColorStandardType vpp_output_color_standards[] = {
1121
 
   VAProcColorStandardBT601
1122
 
};
1123
 
 
1124
 
VAStatus
1125
 
vlVaQueryVideoProcPipelineCaps(VADriverContextP ctx, VAContextID context,
1126
 
                               VABufferID *filters, unsigned int num_filters,
1127
 
                               VAProcPipelineCaps *pipeline_cap)
1128
 
{
1129
 
   unsigned int i = 0;
1130
 
 
1131
 
   if (!ctx)
1132
 
      return VA_STATUS_ERROR_INVALID_CONTEXT;
1133
 
 
1134
 
   if (!pipeline_cap)
1135
 
      return VA_STATUS_ERROR_INVALID_PARAMETER;
1136
 
 
1137
 
   if (num_filters && !filters)
1138
 
      return VA_STATUS_ERROR_INVALID_PARAMETER;
1139
 
 
1140
 
   pipeline_cap->pipeline_flags = 0;
1141
 
   pipeline_cap->filter_flags = 0;
1142
 
   pipeline_cap->num_forward_references = 0;
1143
 
   pipeline_cap->num_backward_references = 0;
1144
 
   pipeline_cap->num_input_color_standards = ARRAY_SIZE(vpp_input_color_standards);
1145
 
   pipeline_cap->input_color_standards = vpp_input_color_standards;
1146
 
   pipeline_cap->num_output_color_standards = ARRAY_SIZE(vpp_output_color_standards);
1147
 
   pipeline_cap->output_color_standards = vpp_output_color_standards;
1148
 
 
1149
 
   for (i = 0; i < num_filters; i++) {
1150
 
      vlVaBuffer *buf = handle_table_get(VL_VA_DRIVER(ctx)->htab, filters[i]);
1151
 
      VAProcFilterParameterBufferBase *filter;
1152
 
 
1153
 
      if (!buf || buf->type != VAProcFilterParameterBufferType)
1154
 
         return VA_STATUS_ERROR_INVALID_BUFFER;
1155
 
 
1156
 
      filter = buf->data;
1157
 
      switch (filter->type) {
1158
 
      case VAProcFilterDeinterlacing: {
1159
 
         VAProcFilterParameterBufferDeinterlacing *deint = buf->data;
1160
 
         if (deint->algorithm == VAProcDeinterlacingMotionAdaptive) {
1161
 
            pipeline_cap->num_forward_references = 2;
1162
 
            pipeline_cap->num_backward_references = 1;
1163
 
         }
1164
 
         break;
1165
 
      }
1166
 
      default:
1167
 
         return VA_STATUS_ERROR_UNIMPLEMENTED;
1168
 
      }
1169
 
   }
1170
 
 
1171
 
   return VA_STATUS_SUCCESS;
1172
 
}
1173
 
 
1174
 
static uint32_t pipe_format_to_drm_format(enum pipe_format format)
1175
 
{
1176
 
   switch (format) {
1177
 
   case PIPE_FORMAT_R8_UNORM:
1178
 
      return DRM_FORMAT_R8;
1179
 
   case PIPE_FORMAT_R8G8_UNORM:
1180
 
      return DRM_FORMAT_GR88;
1181
 
   case PIPE_FORMAT_R16_UNORM:
1182
 
      return DRM_FORMAT_R16;
1183
 
   case PIPE_FORMAT_R16G16_UNORM:
1184
 
      return DRM_FORMAT_GR1616;
1185
 
   case PIPE_FORMAT_B8G8R8A8_UNORM:
1186
 
      return DRM_FORMAT_ARGB8888;
1187
 
   case PIPE_FORMAT_R8G8B8A8_UNORM:
1188
 
      return DRM_FORMAT_ABGR8888;
1189
 
   case PIPE_FORMAT_B8G8R8X8_UNORM:
1190
 
      return DRM_FORMAT_XRGB8888;
1191
 
   case PIPE_FORMAT_R8G8B8X8_UNORM:
1192
 
      return DRM_FORMAT_XBGR8888;
1193
 
   case PIPE_FORMAT_NV12:
1194
 
      return DRM_FORMAT_NV12;
1195
 
   case PIPE_FORMAT_P010:
1196
 
      return DRM_FORMAT_P010;
1197
 
   default:
1198
 
      return DRM_FORMAT_INVALID;
1199
 
   }
1200
 
}
1201
 
 
1202
 
#if VA_CHECK_VERSION(1, 1, 0)
1203
 
VAStatus
1204
 
vlVaExportSurfaceHandle(VADriverContextP ctx,
1205
 
                        VASurfaceID surface_id,
1206
 
                        uint32_t mem_type,
1207
 
                        uint32_t flags,
1208
 
                        void *descriptor)
1209
 
{
1210
 
   vlVaDriver *drv;
1211
 
   vlVaSurface *surf;
1212
 
   struct pipe_surface **surfaces;
1213
 
   struct pipe_screen *screen;
1214
 
   VAStatus ret;
1215
 
   unsigned int usage;
1216
 
   int i, p;
1217
 
 
1218
 
   VADRMPRIMESurfaceDescriptor *desc = descriptor;
1219
 
 
1220
 
   if (mem_type != VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2)
1221
 
      return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;
1222
 
 
1223
 
   drv    = VL_VA_DRIVER(ctx);
1224
 
   screen = VL_VA_PSCREEN(ctx);
1225
 
   mtx_lock(&drv->mutex);
1226
 
 
1227
 
   surf = handle_table_get(drv->htab, surface_id);
1228
 
   if (!surf || !surf->buffer) {
1229
 
      mtx_unlock(&drv->mutex);
1230
 
      return VA_STATUS_ERROR_INVALID_SURFACE;
1231
 
   }
1232
 
 
1233
 
   if (surf->buffer->interlaced) {
1234
 
      struct pipe_video_buffer *interlaced = surf->buffer;
1235
 
      struct u_rect src_rect, dst_rect;
1236
 
 
1237
 
      surf->templat.interlaced = false;
1238
 
      surf->obsolete_buf = surf->buffer;
1239
 
 
1240
 
      ret = vlVaHandleSurfaceAllocate(drv, surf, &surf->templat, NULL, 0);
1241
 
      if (ret != VA_STATUS_SUCCESS) {
1242
 
         mtx_unlock(&drv->mutex);
1243
 
         return VA_STATUS_ERROR_ALLOCATION_FAILED;
1244
 
      }
1245
 
 
1246
 
      src_rect.x0 = dst_rect.x0 = 0;
1247
 
      src_rect.y0 = dst_rect.y0 = 0;
1248
 
      src_rect.x1 = dst_rect.x1 = surf->templat.width;
1249
 
      src_rect.y1 = dst_rect.y1 = surf->templat.height;
1250
 
 
1251
 
      vl_compositor_yuv_deint_full(&drv->cstate, &drv->compositor,
1252
 
                                   interlaced, surf->buffer,
1253
 
                                   &src_rect, &dst_rect,
1254
 
                                   VL_COMPOSITOR_WEAVE);
1255
 
 
1256
 
      interlaced->destroy(interlaced);
1257
 
   } else
1258
 
      surf->obsolete_buf = NULL;
1259
 
 
1260
 
   surfaces = surf->buffer->get_surfaces(surf->buffer);
1261
 
 
1262
 
   usage = 0;
1263
 
   if (flags & VA_EXPORT_SURFACE_WRITE_ONLY)
1264
 
      usage |= PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE;
1265
 
 
1266
 
   desc->fourcc = PipeFormatToVaFourcc(surf->buffer->buffer_format);
1267
 
   desc->width  = surf->templat.width;
1268
 
   desc->height = surf->templat.height;
1269
 
 
1270
 
   for (p = 0; p < VL_MAX_SURFACES; p++) {
1271
 
      struct winsys_handle whandle;
1272
 
      struct pipe_resource *resource;
1273
 
      uint32_t drm_format;
1274
 
 
1275
 
      if (!surfaces[p])
1276
 
         break;
1277
 
 
1278
 
      resource = surfaces[p]->texture;
1279
 
 
1280
 
      drm_format = pipe_format_to_drm_format(resource->format);
1281
 
      if (drm_format == DRM_FORMAT_INVALID) {
1282
 
         ret = VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;
1283
 
         goto fail;
1284
 
      }
1285
 
 
1286
 
      memset(&whandle, 0, sizeof(whandle));
1287
 
      whandle.type = WINSYS_HANDLE_TYPE_FD;
1288
 
 
1289
 
      if (!screen->resource_get_handle(screen, drv->pipe, resource,
1290
 
                                       &whandle, usage)) {
1291
 
         ret = VA_STATUS_ERROR_INVALID_SURFACE;
1292
 
         goto fail;
1293
 
      }
1294
 
 
1295
 
      desc->objects[p].fd   = (int)whandle.handle;
1296
 
      /* As per VADRMPRIMESurfaceDescriptor documentation, size must be the
1297
 
       * "Total size of this object (may include regions which are not part
1298
 
       * of the surface)."" */
1299
 
      desc->objects[p].size = (uint32_t) whandle.size;
1300
 
      desc->objects[p].drm_format_modifier = whandle.modifier;
1301
 
 
1302
 
      if (flags & VA_EXPORT_SURFACE_COMPOSED_LAYERS) {
1303
 
         desc->layers[0].object_index[p] = p;
1304
 
         desc->layers[0].offset[p]       = whandle.offset;
1305
 
         desc->layers[0].pitch[p]        = whandle.stride;
1306
 
      } else {
1307
 
         desc->layers[p].drm_format      = drm_format;
1308
 
         desc->layers[p].num_planes      = 1;
1309
 
         desc->layers[p].object_index[0] = p;
1310
 
         desc->layers[p].offset[0]       = whandle.offset;
1311
 
         desc->layers[p].pitch[0]        = whandle.stride;
1312
 
      }
1313
 
   }
1314
 
 
1315
 
   desc->num_objects = p;
1316
 
 
1317
 
   if (flags & VA_EXPORT_SURFACE_COMPOSED_LAYERS) {
1318
 
      uint32_t drm_format = pipe_format_to_drm_format(surf->buffer->buffer_format);
1319
 
      if (drm_format == DRM_FORMAT_INVALID) {
1320
 
         ret = VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;
1321
 
         goto fail;
1322
 
      }
1323
 
 
1324
 
      desc->num_layers = 1;
1325
 
      desc->layers[0].drm_format = drm_format;
1326
 
      desc->layers[0].num_planes = p;
1327
 
   } else {
1328
 
      desc->num_layers = p;
1329
 
   }
1330
 
 
1331
 
   mtx_unlock(&drv->mutex);
1332
 
 
1333
 
   return VA_STATUS_SUCCESS;
1334
 
 
1335
 
fail:
1336
 
   for (i = 0; i < p; i++)
1337
 
      close(desc->objects[i].fd);
1338
 
 
1339
 
   mtx_unlock(&drv->mutex);
1340
 
 
1341
 
   return ret;
1342
 
}
1343
 
#endif