Linux
OpenGLES
DRM
EGL
gstreamer-vaapi

libva-intel-driverが生成するBufferのアライメントとオフセットとか

背景

NV12フォーマットのGEM FLINK名からテクスチャを生成する
を元に YUV420 フォーマットで生成するにあたって、offset値に困った。
その調査ログである。
wayland + gstreamer-vaapiの環境の話。

TL;DR

offset値は drmプロトコルのwl_drmインターフェースのcreate_planar_bufferリクエストで見える。
offset値の元となるplanerレイアウト値は、i965_drv_video.c の i965_check_alloc_surface_bo() で設定している。

create_planarリクエスト

libvaのi965_output_wayland.cのva_GetSurfaceBufferWl()で設定/リクエストしている。

offsets[0] = 0;
pitches[0] = obj_surface->width;
offsets[1] = obj_surface->width * obj_surface->y_cb_offset;
pitches[1] = obj_surface->cb_cr_pitch;
offsets[2] = obj_surface->width * obj_surface->y_cr_offset
pitches[2] = obj_surface->cb_cr_pitch;

planarレイアウト

#define ALIGN(i, n) (((i) + (n) - 1) & ~((n) - 1))

bufferの情報は、 struct object_surface *obj_surface が所有している。

struct object_surface
{
    struct object_base base;
    VASurfaceStatus status;
    VASubpictureID subpic[I965_MAX_SUBPIC_SUM];
    struct object_subpic *obj_subpic[I965_MAX_SUBPIC_SUM];
    unsigned int subpic_render_idx;

    int width; // default: ALIGN(width, 16)
    int height; // default: ALIGN(height, 16)
    int size;
    int orig_width;
    int orig_height;
    int flags;
    unsigned int fourcc;
    dri_bo *bo;
    VAImageID locked_image_id;
    void (*free_private_data)(void **data);
    void *private_data;
    unsigned int subsampling;
    int x_cb_offset; // X offset is always 0
    int y_cb_offset;
    int x_cr_offset;
    int y_cr_offset;
    int cb_cr_width;
    int cb_cr_height;
    int cb_cr_pitch;
};

確認コード

https://wandbox.org/permlink/RZNwzBcMr0HFGHPS
https://gist.github.com/yuu/d7bd9413d6d1d90fa12638cdec658ec6

wayland_debugのログ↓

//                                                                id, name, width, height, format, offset0, stride0, offset1, stride1, offset2, stride2
[2610092.529]  -> wl_drm@14.create_planar_buffer(new id wl_buffer@13, 7, 320, 240, 842093913, 0, 320, 96000, 160, 76800, 160)

一緒ですね!終わり。