[PATCH 1/2] d2d1: Implement ellipse and rounded rectangle filling with arcs.

Henri Verbeet hverbeet at gmail.com
Mon Feb 17 10:01:14 CST 2020


On Fri, 14 Feb 2020 at 22:19, Giovanni Mascellani <gio at debian.org> wrote:
> For both this and the following patch the pixel shader needs to do
> different things depending on whether it is working with Bézier curves
> or arcs. The way I implement this is not really as clean as it could
> be. In case you don't like it, how would you suggest to fix it?
>
It could be combined with the "outline" field into something similar
to the "type" field in the brush structure, but I'm not sure it's
really worth it. There's also the option of passing information
through the vertex data, or indexed by the instance ID. We'll probably
want something along those lines at some point, but not yet.

> @@ -397,6 +399,15 @@ struct d2d_bezier_vertex
>      } texcoord;
>  };
>
> +struct d2d_arc_vertex
> +{
> +    D2D1_POINT_2F position;
> +    struct
> +    {
> +        float u, v, sign;
> +    } texcoord;
> +};
> +
I'd argue for combining this with the d2d_bezier_vertex structure into
e.g. a "d2d_curve_vertex" structure.

> +    if (geometry->fill.arc_vertex_count) {
> +        buffer_desc.ByteWidth = geometry->fill.arc_vertex_count * sizeof(*geometry->fill.arc_vertices);
> +        buffer_data.pSysMem = geometry->fill.arc_vertices;
> +
> +        if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb))) {
> +            ERR("Failed to create arc vertex buffer, hr %#x.\n", hr);
> +            goto done;
> +        }
> +
> +        d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_ARC, NULL, geometry->fill.arc_vertex_count, vb,
> +                                sizeof(*geometry->fill.arc_vertices), vs_cb, ps_cb_arc, brush, opacity_brush);
Some formatting issues here.

> @@ -2748,6 +2772,11 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target,
>          {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT,    0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
>          {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
>      };
> +    static const D3D10_INPUT_ELEMENT_DESC il_desc_arc[] =
> +    {
> +        {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT,    0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
> +        {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
> +    };
Similar to the d2d_arc_vertex structure, I'd argue for combining this
with "il_desc_bezier".

> +    static const DWORD vs_code_arc[] =
> +    {
> +#if 0
> +        float3x2 transform_geometry;
> +        float4 transform_rtx;
> +        float4 transform_rty;
> +
> +        struct output
> +        {
> +            float2 p : WORLD_POSITION;
> +            float4 b : BEZIER;
> +            nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
> +            float4 position : SV_POSITION;
> +        };
> +
> +        void main(float2 position : POSITION, float3 texcoord : TEXCOORD0, out struct output o)
> +        {
> +            o.p = mul(float3(position, 1.0f), transform_geometry);
> +            o.b = float4(texcoord, 1.0);
> +            o.stroke_transform = float2x2(1.0, 0.0, 0.0, 1.0);
> +            position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
> +                    * float2(transform_rtx.w, transform_rty.w);
> +            o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
> +        }
> +#endif
And then this can be combined with "vs_code_bezier".

> -                clip((i.b.x * i.b.x - i.b.y) * i.b.z);
> +                if (!is_arc) {
> +                    clip((i.b.x * i.b.x - i.b.y) * i.b.z);
> +                } else {
> +                    clip((i.b.x * i.b.x + i.b.y * i.b.y - 1.0) * i.b.z);
> +                }
Formatting.

> -    b = &geometry->fill.bezier_vertices[geometry->fill.bezier_vertex_count];
> -    d2d_bezier_vertex_set(&b[0], p0, 0.0f, 0.0f, -1.0f);
> -    d2d_bezier_vertex_set(&b[1], p1, 0.5f, 0.0f, -1.0f);
> -    d2d_bezier_vertex_set(&b[2], p2, 1.0f, 1.0f, -1.0f);
> -    geometry->fill.bezier_vertex_count += 3;
> +    a = geometry->fill.arc_vertices + geometry->fill.arc_vertex_count;
> +    d2d_arc_vertex_set(&a[0], p0, 0.0f, 1.0f, -1.0f);
> +    d2d_arc_vertex_set(&a[1], p1, 1.0f, 1.0f, -1.0f);
> +    d2d_arc_vertex_set(&a[2], p2, 1.0f, 0.0f, -1.0f);
> +    geometry->fill.arc_vertex_count += 3;
It's just a style preference, but I'd prefer "a =
&geometry->fill.arc_vertices[geometry->fill.arc_vertex_count];".



More information about the wine-devel mailing list