On 08/17/17 09:59, Hans Verkuil wrote:
> Hi Sergei,
> 
> A quick review. I'm concentrating on the mesh ioctl, since that's what sets 
> this
> driver apart.
> 
> On 08/04/2017 08:03 PM, Sergei Shtylyov wrote:
> 
> <snip>
> 
>> Index: media_tree/Documentation/media/v4l-drivers/rcar_imr.rst
>> ===================================================================
>> --- /dev/null
>> +++ media_tree/Documentation/media/v4l-drivers/rcar_imr.rst
>> @@ -0,0 +1,372 @@
>> +Renesas R-Car Image Renderer (IMR) Driver
>> +=========================================
>> +
>> +This file documents some driver-specific aspects of the IMR driver, such as
>> +the driver-specific ioctl.
> 
> Just drop the part ', such as...'.
> 
> Can you add a high-level description of the functionality here? Similar to 
> what
> you did in the bindings document.
> 
>> +
>> +The ioctl reference
>> +~~~~~~~~~~~~~~~~~~~
>> +
>> +See ``include/uapi/linux/rcar_imr.h`` for the data structures used.
>> +
>> +VIDIOC_IMR_MESH - Set mapping data
>> +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> +
>> +Argument: ``struct imr_map_desc``
>> +
>> +**Description**:
>> +
>> +This ioctl sets up the mesh through which the input frames will be 
>> transformed
>> +into the output frames. The mesh can be strictly rectangular (when
>> +``IMR_MAP_MESH`` bit is set in ``imr_map_desc::type``) or arbitrary (when 
>> that
>> +bit is not set).
> 
> Wouldn't something like 'IMR_MAP_RECTANGULAR' be much more descriptive than 
> _MESH?
> There is nothing in the name _MESH to indicate that this switches the data to
> rectangles.
> 
>> +
>> +A rectangular mesh consists of the imr_mesh structure followed by M*N vertex
>> +objects (where M is ``imr_mesh::rows`` and N is ``imr_mesh::columns``).
>> +In case either ``IMR_MAP_AUTOSG`` or ``IMR_MAP_AUTODG`` (not both) bits are
>> +set in ``imr_map_desc::type``, ``imr_mesh::{x|y}0`` specify the coordinates
>> +of the top left corner of the auto-generated mesh and ``imr_mesh::d{x|y}``
>> +specify the mesh's X/Y steps.
> 
> So if the auto bits are set, then there are no vertex objects? Since it's auto
> generated by the hardware?
> 
> I believe we discussed in the past whether 'type' should be split in a 'type'
> and 'flags' field.
> 
>> +
>> +An arbitrary mesh consists of the imr_vbo structure followed by N triangle
>> +objects (where N is ``imr_vbo::num``), consisting of 3 vertex objects each.
>> +Setting ``IMR_MAP_AUTODG`` and ``IMR_MAP_AUTOSG`` bits in
>> +``imr_map_desc::type``) isn't allowed for this type of mesh.
>> +
>> +The vertex object has a complex structure depending on some of the bits in
>> +``imr_map_desc::type``:
>> +
>> +============  ============  ==============  ==============  
>> ===========================
>> +IMR_MAP_CLCE  IMR_MAP_LUCE  IMR_MAP_AUTODG  IMR_MAP_AUTOSG  Vertex 
>> structure variant
> 
> You should explain the meaning of these bits in this section. I.e., what does
> CLCE or AUTODG stand for?
> 
>> +============  ============  ==============  ==============  
>> ===========================
>> +\                                                           
>> ``imr_full_coord``
>> +\                                           X               
>> ``imr_dst_coord``
>> +\                           X                               
>> ``imr_src_coord``
>> +\             X                                             
>> ``imr_full_coord_any_correct``
>> +\             X                             X               
>> ``imr_auto_coord_any_correct``
>> +\             X             X                               
>> ``imr_auto_coord_any_crrect``
> 
> crrect -> correct
> 
>> +X                                                           
>> ``imr_full_coord_any_correct``
>> +X                                           X               
>> ``imr_auto_coord_any_correct``
>> +X                           X                               
>> ``imr_auto_coord_any_correct``
>> +X             X                                             
>> ``imr_full_coord_both_correct``
>> +X             X                             X               
>> ``imr_auto_coord_both_correct``
>> +X             X             X                               
>> ``imr_auto_coord_both_correct``
>> +============  ============  ==============  ==============  
>> ===========================
>> +
>> +The luma correction is calculated according to the following formula (where
>> +``Y`` is the luma value after texture mapping, ``Y'`` is the luma value 
>> after
>> +luma correction, ``lscal`` and ``lofst`` are the luma correction scale and
>> +offset taken from ``struct imr_luma_correct``, ``YLDPO`` is a luma 
>> correction
>> +scale decimal point position specified by ``IMR_MAP_YLDPO(n)``): ::
>> +
>> +    Y' = ((Y * lscal) >> YLDPO) + lofst
>> +
>> +The chroma correction is calculated according to the following formula 
>> (where
>> +``U/V`` are the chroma values after texture mapping, ``U'/V'`` are the 
>> chroma
>> +values after chroma correction, ``ubscl/vrscl`` and ``ubofs/vrofs`` are the
>> +U/V value chroma correction scales and offsets taken from
>> +``struct imr_chroma_correct``, ``UBDPO/VRDPO`` are the chroma correction 
>> scale
>> +decimal point positions specified by ``IMR_MAP_{UBDPO|VRDPO}(n)``): ::
>> +
>> +    U' = ((U + ubofs) * ubscl) >> UBDPO
>> +    V' = ((V + vrofs) * vrscl) >> VRDPO
>> +
>> +**Return value**:
>> +
>> +On success 0 is returned. On error -1 is returned and ``errno`` is set
>> +appropriately.
>> +
>> +**Example code**:
>> +
>> +Below is an example code for constructing the meshes: ``imr_map_create()``
>> +constructs an arbitraty mesh, ``imr_map_mesh_src()`` function constructs
> 
> arbitrary
> 
>> +a rectangular mesh with the auto-generated destination coordinates.
>> +
>> +.. code-block:: C
>> +
>> + #include <malloc.h>
>> + #include <math.h>
>> + #include <linux/rcar_imr.h>
>> +
>> + /* IMR device data */
>> + struct imr_device {
>> +    /* V4L2 file decriptor */
> 
> descriptor
> 
>> +    int                     vfd;
>> +
>> +    /* input/output buffers dimensions */
>> +    int                     w, h, W, H;
>> + };
>> +
>> + #define IMR_SRC_SUBSAMPLE  5
>> + #define IMR_DST_SUBSAMPLE  2
>> + #define IMR_COORD_THRESHOLD        (128 * 128 * (1 << 2 * 
>> IMR_DST_SUBSAMPLE))
>> +
>> + /* find the longest side (index) */
>> + static void find_longest_side(int n, __s16 xy0, __s16 xy1, int *max, int 
>> *side)
>> + {
>> +    int t = xy1 - xy0;
>> +
>> +    t *= t;
>> +    if (*max < t) {
>> +            *max  = t;
>> +            *side = n;
>> +    }
>> + }
>> +
>> + /* recursively split a triangle until it can be passed to IMR */
>> + static int split_triangle(struct imr_full_coord *coord,
>> +                       __s16 *xy0, __s16 *xy1, __s16 *xy2,
>> +                       __u16 *uv0, __u16 *uv1, __u16 *uv2, int avail)
>> + {
>> +    int     max = 0, k = 0;
>> +
>> +    /* we need to have at least one available triangle */
>> +    if (avail < 1)
>> +            return 0;
>> +
>> +    find_longest_side(0, xy0[0], xy1[0], &max, &k);
>> +    find_longest_side(0, xy0[1], xy1[1], &max, &k);
>> +    find_longest_side(1, xy1[0], xy2[0], &max, &k);
>> +    find_longest_side(1, xy1[1], xy2[1], &max, &k);
>> +    find_longest_side(2, xy2[0], xy0[0], &max, &k);
>> +    find_longest_side(2, xy2[1], xy0[1], &max, &k);
>> +
>> +    /* if value exceeds the threshold, do splitting */
>> +    if (max >= IMR_COORD_THRESHOLD) {
>> +            __s16   XY[2];
>> +            __u16   UV[2];
>> +            int     n;
>> +
>> +            switch (k) {
>> +            case 0:
>> +                    /* split triangle along edge 0 - 1 */
>> +                    XY[0] = (xy0[0] + xy1[0]) / 2;
>> +                    XY[1] = (xy0[1] + xy1[1]) / 2;
>> +                    UV[0] = (uv0[0] + uv1[0]) / 2;
>> +                    UV[1] = (uv0[1] + uv1[1]) / 2;
>> +                    n = split_triangle(coord, xy0, XY, xy2, uv0, UV, uv2,
>> +                                       avail);
>> +                    n += split_triangle(coord + 3 * n, XY, xy1, xy2,
>> +                                        UV, uv1, uv2, avail - n);
>> +                    break;
>> +            case 1:
>> +                    /* split triangle along edge 1 - 2 */
>> +                    XY[0] = (xy1[0] + xy2[0]) / 2;
>> +                    XY[1] = (xy1[1] + xy2[1]) / 2;
>> +                    UV[0] = (uv1[0] + uv2[0]) / 2;
>> +                    UV[1] = (uv1[1] + uv2[1]) / 2;
>> +                    n = split_triangle(coord, xy1, XY, xy0, uv1, UV, uv0,
>> +                                       avail);
>> +                    n += split_triangle(coord + 3 * n, XY, xy2, xy0,
>> +                                        UV, uv2, uv0, avail - n);
>> +                    break;
>> +            default:
>> +                    /* split triangle along edge 2 - 0 */
>> +                    XY[0] = (xy2[0] + xy0[0]) / 2;
>> +                    XY[1] = (xy2[1] + xy0[1]) / 2;
>> +                    UV[0] = (uv2[0] + uv0[0]) / 2;
>> +                    UV[1] = (uv2[1] + uv0[1]) / 2;
>> +                    n = split_triangle(coord, xy2, XY, xy1, uv2, UV, uv1,
>> +                                       avail);
>> +                    n += split_triangle(coord + 3 * n, XY, xy0, xy1,
>> +                                        UV, uv0, uv1, avail - n);
>> +            }
>> +
>> +            /* return number of triangles added */
>> +            return n;
>> +    } else {
>> +            /* no need to split a rectangle; save coordinates */
>> +            coord[0].src.u = uv0[0];
>> +            coord[0].src.v = uv0[1];
>> +            coord[0].dst.x = xy0[0];
>> +            coord[0].dst.y = xy0[1];
>> +            coord[1].src.u = uv1[0];
>> +            coord[1].src.v = uv1[1];
>> +            coord[1].dst.x = xy1[0];
>> +            coord[1].dst.y = xy1[1];
>> +            coord[2].src.u = uv2[0];
>> +            coord[2].src.v = uv2[1];
>> +            coord[2].dst.x = xy2[0];
>> +            coord[2].dst.y = xy2[1];
>> +
>> +            /* single triangle is created */
>> +            return 1;
>> +    }
>> + }
>> +
>> + /* process single triangle */
>> + static int process_triangle(struct imr_full_coord *coord, __u16 *uv, __s16 
>> *xy,
>> +                         int avail)
>> + {
>> +    /* cull invisible triangle first */
>> +    if ((xy[2] - xy[0]) * (xy[5] - xy[3]) >=
>> +        (xy[3] - xy[1]) * (xy[4] - xy[2])) {
>> +            return 0;
>> +    } else {
>> +            /* recursively split triangle into smaller ones */
>> +            return split_triangle(coord, xy + 0, xy + 2, xy + 4,
>> +                                  uv + 0, uv + 2, uv + 4, avail);
>> +    }
>> + }
>> +
>> + /* clamp texture coordinates to not exceed input dimensions */
>> + static void clamp_texture(__u16 *uv, float *UV, int w, int h)
>> + {
>> +    float t;
>> +
>> +    t = UV[0];
>> +    if (t < 0)
>> +            uv[0] = 0;
>> +    t *= w;
>> +    if (t > w - 1)
>> +            uv[0] = w - 1;
>> +    else
>> +            uv[0] = round(t);
>> +
>> +    t = UV[1];
>> +    if (t < 0)
>> +            uv[1] = 0;
>> +    t *= h;
>> +    if (t > h - 1)
>> +            uv[1] = h - 1;
>> +    else
>> +            uv[1] = round(t);
>> + }
>> +
>> + /* clamp vertex coordinates */
>> + static int clamp_vertex(__s16 *xy, float *XY, int W, int H)
>> + {
>> +    float x = round(XY[0] * W), y = round(XY[1] * H), z = XY[2];
>> +
>> +    if (z < 0.1)
>> +            return 0;
>> +    if (x < -(256 << IMR_DST_SUBSAMPLE) || x >= W + (256 << 
>> IMR_DST_SUBSAMPLE))
>> +            return 0;
>> +    if (y < -(256 << IMR_DST_SUBSAMPLE) || y >= H + (256 << 
>> IMR_DST_SUBSAMPLE))
>> +            return 0;
>> +
>> +    xy[0] = (__s16)x;
>> +    xy[1] = (__s16)y;
>> +
>> +    return 1;
>> + }
>> +
>> + /* create arbitrary mesh */
>> + struct imr_map_desc *imr_map_create(struct imr_device *dev,
>> +                                 float *uv, float *xy, int n)
>> + {
>> +    struct imr_map_desc     *desc;
>> +    struct imr_vbo          *vbo;
>> +    struct imr_full_coord   *coord;
>> +    int                     j, m, w, h, W, H;
>> +
>> +    /* create a configuration structure */
>> +    desc = malloc(sizeof(*desc) + sizeof(*vbo) + 3 * n * sizeof(*coord));
>> +    if (!desc)
>> +            return NULL;
>> +
>> +    /* fill-in VBO coordinates */
>> +    vbo = (void *)(desc + 1);
>> +    coord = (void *)(vbo + 1);
>> +
>> +    /* calculate source/destination dimensions in subpixel coordinates */
>> +    w = dev->w << IMR_SRC_SUBSAMPLE;
>> +    h = dev->h << IMR_SRC_SUBSAMPLE;
>> +    W = dev->W << IMR_DST_SUBSAMPLE;
>> +    H = dev->H << IMR_DST_SUBSAMPLE;
>> +
>> +    /* put at most N triangles into mesh descriptor */
>> +    for (j = 0, m = 0; j < n && m < n; j++, xy += 9, uv += 6) {
>> +            __u16   UV[6];
>> +            __s16   XY[6];
>> +            int     k;
>> +
>> +            /* translate model coordinates to fixed-point */
>> +            if (!clamp_vertex(XY + 0, xy + 0, W, H))
>> +                    continue;
>> +            if (!clamp_vertex(XY + 2, xy + 3, W, H))
>> +                    continue;
>> +            if (!clamp_vertex(XY + 4, xy + 6, W, H))
>> +                    continue;
>> +
>> +            /* translate source coordinates */
>> +            clamp_texture(UV + 0, uv + 0, w, h);
>> +            clamp_texture(UV + 2, uv + 2, w, h);
>> +            clamp_texture(UV + 4, uv + 4, w, h);
>> +
>> +            /* process single triangle */
>> +            k = process_triangle(coord, UV, XY, n - m);
>> +            if (k != 0) {
>> +                    /* advance vertex coordinates pointer */
>> +                    coord += 3 * k;
>> +                    m += k;
>> +            }
>> +    }
>> +
>> +    /* put number of triangles in VBO */
>> +    vbo->num = m;
>> +
>> +    /* fill-in descriptor */
>> +    desc->type = IMR_MAP_UVDPOR(IMR_SRC_SUBSAMPLE) |
>> +                 (IMR_DST_SUBSAMPLE ? IMR_MAP_DDP : 0);
>> +    desc->size = (void *)coord - (void *)vbo;
>> +    desc->data = (__u64)vbo;
>> +
>> +    return desc;
>> + }
>> +
>> + /* create rectangular mesh */
>> + struct imr_map_desc *imr_map_mesh_src(struct imr_device *dev, float *uv,
>> +                                   int rows, int columns,
>> +                                   float x0, float y0, float dx, float dy)
>> + {
>> +    struct imr_map_desc     *desc;
>> +    struct imr_mesh         *mesh;
>> +    struct imr_src_coord    *coord;
>> +    int                     k, w, h, W, H;
>> +
>> +    /* create a configuration structure */
>> +    desc = malloc(sizeof(*desc) + sizeof(*mesh) + rows * columns *
>> +                  sizeof(*coord));
>> +    if (!desc)
>> +            return NULL;
>> +
>> +    /* fill-in rectangular mesh coordinates */
>> +    mesh = (void *)(desc + 1);
>> +    coord = (void *)(mesh + 1);
>> +
>> +    /* calculate source/destination dimensions in subpixel coordinates */
>> +    w = dev->w << IMR_SRC_SUBSAMPLE;
>> +    h = dev->h << IMR_SRC_SUBSAMPLE;
>> +    W = dev->W << IMR_DST_SUBSAMPLE;
>> +    H = dev->H << IMR_DST_SUBSAMPLE;
>> +
>> +    /* set mesh parameters */
>> +    mesh->rows = rows;
>> +    mesh->columns = columns;
>> +    mesh->x0 = (__u16)round(x0 * W);
>> +    mesh->y0 = (__u16)round(y0 * H);
>> +    mesh->dx = (__u16)round(dx * W);
>> +    mesh->dy = (__u16)round(dy * H);
>> +
>> +    /* put mesh coordinates */
>> +    for (k = 0; k < rows * columns; k++, uv += 2, coord++) {
>> +            __u16   UV[2];
>> +
>> +            /* transform point into texture coordinates */
>> +            clamp_texture(UV, uv, w, h);
>> +
>> +            /* fill the mesh */
>> +            coord->u = UV[0];
>> +            coord->v = UV[1];
>> +    }
>> +
>> +    /* fill-in descriptor */
>> +    desc->type = IMR_MAP_MESH | IMR_MAP_AUTODG |
>> +                 IMR_MAP_UVDPOR(IMR_SRC_SUBSAMPLE) |
>> +                 (IMR_DST_SUBSAMPLE ? IMR_MAP_DDP : 0);
>> +    desc->size = (void *)coord - (void *)mesh;
>> +    desc->data = (__u64)mesh;
>> +
>> +    return desc;
>> + }
> 
> <snip>
> 
>> Index: media_tree/include/uapi/linux/rcar_imr.h
>> ===================================================================
>> --- /dev/null
>> +++ media_tree/include/uapi/linux/rcar_imr.h
>> @@ -0,0 +1,182 @@
>> +/*
>> + * rcar_imr.h -- R-Car IMR-LX4 Driver UAPI
>> + *
>> + * Copyright (C) 2016-2017 Cogent Embedded, Inc. <sou...@cogentembedded.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + */
>> +
>> +#ifndef __RCAR_IMR_H
>> +#define __RCAR_IMR_H
>> +
>> +#include <linux/videodev2.h>
>> +
>> +/*******************************************************************************
>> + * Mapping specification descriptor
>> + 
>> ******************************************************************************/
>> +
>> +struct imr_map_desc {
>> +    /* bitmask of the mapping type (see below) */
>> +    __u32                   type;
>> +
>> +    /* total data size */
>> +    __u32                   size;
>> +
>> +    /* data user-pointer */
>> +    __u64                   data;
>> +} __attribute__((packed));
>> +
>> +/* regular mesh specification */
>> +#define IMR_MAP_MESH                (1 << 0)
>> +
>> +/* auto-generated source coordinates */
>> +#define IMR_MAP_AUTOSG              (1 << 1)
>> +
>> +/* auto-generated destination coordinates */
>> +#define IMR_MAP_AUTODG              (1 << 2)
>> +
>> +/* luma correction flag */
>> +#define IMR_MAP_LUCE                (1 << 3)
>> +
>> +/* chroma correction flag */
>> +#define IMR_MAP_CLCE                (1 << 4)
>> +
>> +/* vertex clockwise-mode order */
>> +#define IMR_MAP_TCM         (1 << 5)
>> +
>> +/* source coordinate decimal point position */
>> +#define __IMR_MAP_UVDPOR_SHIFT      8
>> +#define __IMR_MAP_UVDPOR(v) (((v) >> __IMR_MAP_UVDPOR_SHIFT) & 0x7)
>> +#define IMR_MAP_UVDPOR(n)   (((n) & 0x7) << __IMR_MAP_UVDPOR_SHIFT)
>> +
>> +/* destination coordinate sub-pixel mode */
>> +#define IMR_MAP_DDP         (1 << 11)
>> +
>> +/* luminance correction scale decimal point position */
>> +#define __IMR_MAP_YLDPO_SHIFT       12
>> +#define __IMR_MAP_YLDPO(v)  (((v) >> __IMR_MAP_YLDPO_SHIFT) & 0x7)
>> +#define IMR_MAP_YLDPO(n)    (((n) & 0x7) << __IMR_MAP_YLDPO_SHIFT)
>> +
>> +/* chroma (U) correction scale decimal point position */
>> +#define __IMR_MAP_UBDPO_SHIFT       15
>> +#define __IMR_MAP_UBDPO(v)  (((v) >> __IMR_MAP_UBDPO_SHIFT) & 0x7)
>> +#define IMR_MAP_UBDPO(n)    (((n) & 0x7) << __IMR_MAP_UBDPO_SHIFT)
>> +
>> +/* chroma (V) correction scale decimal point position */
>> +#define __IMR_MAP_VRDPO_SHIFT       18
>> +#define __IMR_MAP_VRDPO(v)  (((v) >> __IMR_MAP_VRDPO_SHIFT) & 0x7)
>> +#define IMR_MAP_VRDPO(n)    (((n) & 0x7) << __IMR_MAP_VRDPO_SHIFT)
> 
> You need to document all these bits in the documentation. I.e. TCM and DDP
> are not currently documented.
> 
> It helps a lot to understand these defines if the documentation and the
> comments explain what the abbreviations mean. E.g. what does DDP stand
> for, or YLDPO? It's an alphabet soup right now.
> 
>> +
>> +/* regular mesh specification */
>> +struct imr_mesh {
> 
> How about imr_rectangles? There is no indication in the struct name that this
> describes a rectangle.
> 
>> +    /* rectangular mesh size */
>> +    __u16                   rows, columns;
>> +
>> +    /* auto-generated mesh parameters */
>> +    __u16                   x0, y0, dx, dy;
>> +} __attribute__((packed));
>> +
>> +/* vertex-buffer-object (VBO) descriptor */
>> +struct imr_vbo {
>> +    /* number of triangles */
>> +    __u16                   num;
>> +} __attribute__((packed));
>> +
>> +/*******************************************************************************
>> + * Vertex-related structures
>> + 
>> ******************************************************************************/
>> +
>> +/* source coordinates */
>> +struct imr_src_coord {
>> +    /* vertical, horizontal */
>> +    __u16                   v, u;
> 
> Confusing: why isn't this 'v, h;' given the comment? Or does this refer to
> chroma (U and V)? And what does 'vertical, horizontal' mean anyway? Vertical
> what?
> 
>> +} __attribute__((packed));
>> +
>> +/* destination coordinates */
>> +struct imr_dst_coord {
>> +    /* vertical, horizontal */
> 
> Confusing comment as well. I assume y and x are simply coordinates of a 
> vertex?
> Just say so. This comment doesn't mean anything.
> 
>> +    __u16                   y, x;
>> +} __attribute__((packed));
>> +
>> +/* luma correction parameters */
>> +struct imr_luma_correct {
>> +    /* offset */
>> +    __s8                    lofst;
>> +
>> +    /* scale */
>> +    __u8                    lscal;
>> +
>> +    __u16                   reserved;
> 
> Why is this reserved? Is that for padding? If so, then add a comment that 
> mentions
> that.
> 
>> +} __attribute__((packed));
>> +
>> +/* chroma correction parameters */
>> +struct imr_chroma_correct {
>> +    /* V value offset */
>> +    __s8                    vrofs;
>> +
>> +    /* V value scale */
>> +    __u8                    vrscl;
>> +
>> +    /* U value offset */
>> +    __s8                    ubofs;
>> +
>> +    /* V value scale */
>> +    __u8                    ubscl;
>> +} __attribute__((packed));
>> +
>> +/* fully specified source/destination coordinates */
>> +struct imr_full_coord {
>> +    struct imr_src_coord    src;
>> +    struct imr_dst_coord    dst;
>> +} __attribute__((packed));
>> +
>> +/* auto-generated coordinates with luma or chroma correction */
>> +struct imr_auto_coord_any_correct {
>> +    union {
>> +            struct imr_src_coord src;
>> +            struct imr_dst_coord dst;
> 
> Why have separate imr_src_coord and imr_dst_coord structs? Why not just
> call it imr_coord? I think that is part of the reason of my confusion
> regarding understanding those structs.
> 
> The field name here indicates whether it is a source or destination,
> the coordinate information is the same for both.
> 
>> +    };
>> +    union {
>> +            struct imr_luma_correct luma;
>> +            struct imr_chroma_correct chroma;
>> +    };
>> +} __attribute__((packed));
>> +
>> +/* auto-generated coordinates with both luma and chroma correction */
>> +struct imr_auto_coord_both_correct {
>> +    union {
>> +            struct imr_src_coord src;
>> +            struct imr_dst_coord dst;
>> +    };
>> +    struct imr_luma_correct luma;
>> +    struct imr_chroma_correct chroma;
>> +} __attribute__((packed));
>> +
>> +/* fully specified coordinates with luma or chroma correction */
>> +struct imr_full_coord_any_correct {
>> +    struct imr_src_coord src;
>> +    struct imr_dst_coord dst;
>> +    union {
>> +            struct imr_luma_correct luma;
>> +            struct imr_chroma_correct chroma;
>> +    };
>> +} __attribute__((packed));
>> +
>> +/* fully specified coordinates with both luma and chroma correction */
>> +struct imr_full_coord_both_correct {
>> +    struct imr_src_coord src;
>> +    struct imr_dst_coord dst;
>> +    struct imr_luma_correct luma;
>> +    struct imr_chroma_correct chroma;
>> +} __attribute__((packed));
>> +
>> +/*******************************************************************************
>> + * Private IOCTL codes
>> + 
>> ******************************************************************************/
>> +
>> +#define VIDIOC_IMR_MESH _IOW('V', BASE_VIDIOC_PRIVATE + 0, struct 
>> imr_map_desc)
>> +
>> +#endif /* __RCAR_IMR_H */
>>
> 
> Do you know the typical number of rectangles or triangles that are passed to 
> this
> function? Is there an upper hardware limit?
> 
> I ask, because I wonder whether using a fixed vertex struct like 
> imr_full_coord_both_correct
> for all variations isn't much simpler. The driver just ignores the fields it 
> doesn't
> need in that case.
> 
> Yes, you get some memory overhead, but the code for both userspace and 
> kernelspace
> will be much simpler.

I just had a brainwave: rather than making these complicated structure variants,
why not just do this (just thrown together, I didn't look at alignment etc.):

struct imr_map_desc {
        /* bitmask of the mapping type (see below) */
        __u32                   type;

        /* total data size */
        __u32                   size;

        /* number of vertices */
        __u32                   vertices;

        /* rectangular mesh size (ignored for triangles) */
        __u16                   rows, columns;

        /* auto-generated mesh parameters (ignored if not auto-generated) */
        __u16                   x0, y0, dx, dy;

        /* data user-pointer */
        __u64                   src_coords;
        __u64                   dst_coords;
        __u64                   luma_corr;
        __u64                   chroma_corr;
} __attribute__((packed));

Just leave the corresponding data pointer 0 when not needed, and otherwise
these data pointers point to a struct imr_coord, imr_luma_corr or 
imr_chroma_corr
arrays. Much simpler and still memory efficient.

BTW, I prefer either _corr or _correction over _correct. 'correct' is confusing
since it is also a normal english word and it is not obvious that it is an
abbreviation for 'correction'.

Regards,

        Hans

Reply via email to