[PATCH 4/5] d2d1: Unify the outline and fill pixel shaders.

Henri Verbeet hverbeet at codeweavers.com
Sat Sep 23 06:37:00 CDT 2017


Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
---
 dlls/d2d1/brush.c         |  13 +-
 dlls/d2d1/d2d1_private.h  |  12 +-
 dlls/d2d1/render_target.c | 631 ++++++++++++++++++++++------------------------
 3 files changed, 316 insertions(+), 340 deletions(-)

diff --git a/dlls/d2d1/brush.c b/dlls/d2d1/brush.c
index 9aac480..9951803 100644
--- a/dlls/d2d1/brush.c
+++ b/dlls/d2d1/brush.c
@@ -846,25 +846,26 @@ static BOOL d2d_brush_fill_cb(const struct d2d_brush *brush,
 }
 
 HRESULT d2d_brush_get_ps_cb(struct d2d_brush *brush, struct d2d_brush *opacity_brush,
-        struct d2d_d3d_render_target *render_target, ID3D10Buffer **ps_cb)
+        BOOL outline, struct d2d_d3d_render_target *render_target, ID3D10Buffer **ps_cb)
 {
-    struct d2d_brush_cb brush_cb[2] = {{0}};
     D3D10_SUBRESOURCE_DATA buffer_data;
+    struct d2d_ps_cb cb_data = {0};
     D3D10_BUFFER_DESC buffer_desc;
     HRESULT hr;
 
-    if (!d2d_brush_fill_cb(brush, render_target, &brush_cb[0]))
+    cb_data.outline = outline;
+    if (!d2d_brush_fill_cb(brush, render_target, &cb_data.colour_brush))
         return E_NOTIMPL;
-    if (!d2d_brush_fill_cb(opacity_brush, render_target, &brush_cb[1]))
+    if (!d2d_brush_fill_cb(opacity_brush, render_target, &cb_data.opacity_brush))
         return E_NOTIMPL;
 
-    buffer_desc.ByteWidth = sizeof(brush_cb);
+    buffer_desc.ByteWidth = sizeof(cb_data);
     buffer_desc.Usage = D3D10_USAGE_DEFAULT;
     buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
     buffer_desc.CPUAccessFlags = 0;
     buffer_desc.MiscFlags = 0;
 
-    buffer_data.pSysMem = brush_cb;
+    buffer_data.pSysMem = &cb_data;
     buffer_data.SysMemPitch = 0;
     buffer_data.SysMemSlicePitch = 0;
 
diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h
index 77c5974..2294568 100644
--- a/dlls/d2d1/d2d1_private.h
+++ b/dlls/d2d1/d2d1_private.h
@@ -68,7 +68,6 @@ struct d2d_shape_resources
 {
     ID3D10InputLayout *il;
     ID3D10VertexShader *vs;
-    ID3D10PixelShader *ps;
 };
 
 struct d2d_brush_cb
@@ -91,6 +90,14 @@ struct d2d_brush_cb
     } u;
 };
 
+struct d2d_ps_cb
+{
+    BOOL outline;
+    BOOL pad[3];
+    struct d2d_brush_cb colour_brush;
+    struct d2d_brush_cb opacity_brush;
+};
+
 struct d2d_d3d_render_target
 {
     ID2D1RenderTarget ID2D1RenderTarget_iface;
@@ -105,6 +112,7 @@ struct d2d_d3d_render_target
     ID3D10RenderTargetView *view;
     ID3D10StateBlock *stateblock;
     struct d2d_shape_resources shape_resources[D2D_SHAPE_TYPE_COUNT];
+    ID3D10PixelShader *ps;
     ID3D10Buffer *ib;
     unsigned int vb_stride;
     ID3D10Buffer *vb;
@@ -241,7 +249,7 @@ HRESULT d2d_linear_gradient_brush_create(ID2D1Factory *factory, const D2D1_LINEA
 HRESULT d2d_bitmap_brush_create(ID2D1Factory *factory, ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES *bitmap_brush_desc,
         const D2D1_BRUSH_PROPERTIES *brush_desc, struct d2d_brush **brush) DECLSPEC_HIDDEN;
 void d2d_brush_bind_resources(struct d2d_brush *brush, ID3D10Device *device, unsigned int brush_idx) DECLSPEC_HIDDEN;
-HRESULT d2d_brush_get_ps_cb(struct d2d_brush *brush, struct d2d_brush *opacity_brush,
+HRESULT d2d_brush_get_ps_cb(struct d2d_brush *brush, struct d2d_brush *opacity_brush, BOOL outline,
         struct d2d_d3d_render_target *render_target, ID3D10Buffer **ps_cb) DECLSPEC_HIDDEN;
 struct d2d_brush *unsafe_impl_from_ID2D1Brush(ID2D1Brush *iface) DECLSPEC_HIDDEN;
 
diff --git a/dlls/d2d1/render_target.c b/dlls/d2d1/render_target.c
index 173fea1..0ef3442 100644
--- a/dlls/d2d1/render_target.c
+++ b/dlls/d2d1/render_target.c
@@ -162,7 +162,7 @@ static void d2d_rt_draw(struct d2d_d3d_render_target *render_target, enum d2d_sh
     ID3D10Device_VSSetConstantBuffers(device, 0, 1, &vs_cb);
     ID3D10Device_VSSetShader(device, shape_resources->vs);
     ID3D10Device_PSSetConstantBuffers(device, 0, 1, &ps_cb);
-    ID3D10Device_PSSetShader(device, shape_resources->ps);
+    ID3D10Device_PSSetShader(device, render_target->ps);
     ID3D10Device_RSSetViewports(device, 1, &vp);
     if (render_target->clip_stack.count)
     {
@@ -262,9 +262,9 @@ static ULONG STDMETHODCALLTYPE d2d_d3d_render_target_Release(ID2D1RenderTarget *
         ID3D10RasterizerState_Release(render_target->rs);
         ID3D10Buffer_Release(render_target->vb);
         ID3D10Buffer_Release(render_target->ib);
+        ID3D10PixelShader_Release(render_target->ps);
         for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
         {
-            ID3D10PixelShader_Release(render_target->shape_resources[i].ps);
             ID3D10VertexShader_Release(render_target->shape_resources[i].vs);
             ID3D10InputLayout_Release(render_target->shape_resources[i].il);
         }
@@ -682,7 +682,7 @@ static void d2d_rt_draw_geometry(struct d2d_d3d_render_target *render_target,
         return;
     }
 
-    if (FAILED(hr = d2d_brush_get_ps_cb(brush, NULL, render_target, &ps_cb)))
+    if (FAILED(hr = d2d_brush_get_ps_cb(brush, NULL, TRUE, render_target, &ps_cb)))
     {
         WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
         ID3D10Buffer_Release(vs_cb);
@@ -823,7 +823,7 @@ static void d2d_rt_fill_geometry(struct d2d_d3d_render_target *render_target,
         return;
     }
 
-    if (FAILED(hr = d2d_brush_get_ps_cb(brush, opacity_brush, render_target, &ps_cb)))
+    if (FAILED(hr = d2d_brush_get_ps_cb(brush, opacity_brush, FALSE, render_target, &ps_cb)))
     {
         WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
         ID3D10Buffer_Release(vs_cb);
@@ -1506,8 +1506,8 @@ static void STDMETHODCALLTYPE d2d_d3d_render_target_PopAxisAlignedClip(ID2D1Rend
 static void STDMETHODCALLTYPE d2d_d3d_render_target_Clear(ID2D1RenderTarget *iface, const D2D1_COLOR_F *colour)
 {
     struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
-    struct d2d_brush_cb brush_cb[2] = {{0}};
     D3D10_SUBRESOURCE_DATA buffer_data;
+    struct d2d_ps_cb ps_cb_data = {0};
     D3D10_BUFFER_DESC buffer_desc;
     ID3D10Buffer *vs_cb, *ps_cb;
     D2D1_COLOR_F *c;
@@ -1537,9 +1537,10 @@ static void STDMETHODCALLTYPE d2d_d3d_render_target_Clear(ID2D1RenderTarget *ifa
         return;
     }
 
-    brush_cb[0].type = D2D_BRUSH_TYPE_SOLID;
-    brush_cb[0].opacity = 1.0f;
-    c = &brush_cb[0].u.solid.colour;
+    ps_cb_data.outline = FALSE;
+    ps_cb_data.colour_brush.type = D2D_BRUSH_TYPE_SOLID;
+    ps_cb_data.colour_brush.opacity = 1.0f;
+    c = &ps_cb_data.colour_brush.u.solid.colour;
     if (colour)
         *c = *colour;
     if (render_target->desc.pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
@@ -1548,10 +1549,10 @@ static void STDMETHODCALLTYPE d2d_d3d_render_target_Clear(ID2D1RenderTarget *ifa
     c->g *= c->a;
     c->b *= c->a;
 
-    brush_cb[1].type = D2D_BRUSH_TYPE_COUNT;
+    ps_cb_data.opacity_brush.type = D2D_BRUSH_TYPE_COUNT;
 
-    buffer_desc.ByteWidth = sizeof(brush_cb);
-    buffer_data.pSysMem = brush_cb;
+    buffer_desc.ByteWidth = sizeof(ps_cb_data);
+    buffer_data.pSysMem = &ps_cb_data;
 
     if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ps_cb)))
     {
@@ -2169,6 +2170,13 @@ static HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_t
         float4 transform_rtx;
         float4 transform_rty;
 
+        struct output
+        {
+            float4 position : SV_POSITION;
+            float4 b : BEZIER;
+            nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
+        };
+
         /* The lines PₚᵣₑᵥP₀ and P₀Pₙₑₓₜ, both offset by ±½w, intersect each other at:
          *
          *   Pᵢ = P₀ ± w · ½q⃑ᵢ.
@@ -2178,69 +2186,78 @@ static HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_t
          *   q⃑ᵢ = q̂ₚᵣₑᵥ⊥ + tan(½θ) · -q̂ₚᵣₑᵥ
          *   θ  = ∠PₚᵣₑᵥP₀Pₙₑₓₜ
          *   q⃑ₚᵣₑᵥ = P₀ - Pₚᵣₑᵥ */
-        float4 main(float2 position : POSITION, float2 prev : PREV,
-                float2 next : NEXT, out float3 b : BEZIER) : SV_POSITION
+        void main(float2 position : POSITION, float2 prev : PREV, float2 next : NEXT, out struct output o)
         {
             float2 q_prev, q_next, v_p, q_i;
+            float2x2 geom;
             float l;
 
-            q_prev = float2(dot(prev, transform_geometry._11_21), dot(prev, transform_geometry._12_22));
-            q_prev = normalize(q_prev);
+            o.stroke_transform = float2x2(transform_rtx.xy, transform_rty.xy) * stroke_width * 0.5f;
 
-            q_next = float2(dot(next, transform_geometry._11_21), dot(next, transform_geometry._12_22));
-            q_next = normalize(q_next);
+            geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
+            q_prev = normalize(mul(geom, prev));
+            q_next = normalize(mul(geom, next));
 
             /* tan(½θ) = sin(θ) / (1 + cos(θ))
              *         = (q̂ₚᵣₑᵥ⊥ · q̂ₙₑₓₜ) / (1 + (q̂ₚᵣₑᵥ · q̂ₙₑₓₜ)) */
             v_p = float2(-q_prev.y, q_prev.x);
             l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
             q_i = l * q_prev + v_p;
-            position = mul(float3(position, 1.0f), transform_geometry) + stroke_width * 0.5f * q_i;
 
-            b = float3(1.0, 0.0, 1.0);
-            return float4(mul(float2x3(transform_rtx.xyz * transform_rtx.w, transform_rty.xyz * transform_rty.w),
-                    float3(position.xy, 1.0f)) + float2(-1.0f, 1.0f), 0.0f, 1.0f);
+            o.b = float4(0.0, 0.0, 0.0, 0.0);
+
+            position = mul(float3(position, 1.0f), transform_geometry) + stroke_width * 0.5f * q_i;
+            position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(position, 1.0f))
+                    * float2(transform_rtx.w, transform_rty.w);
+            o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
         }
 #endif
-        0x43425844, 0xf54c4bf8, 0xa8a4ab16, 0x05ee4e9c, 0x55549ca4, 0x00000001, 0x000004c8, 0x00000003,
-        0x0000002c, 0x00000098, 0x000000ec, 0x4e475349, 0x00000064, 0x00000003, 0x00000008, 0x00000050,
+        0x43425844, 0x02efddb1, 0x64c7aa76, 0x9bfda1b3, 0xaf692726, 0x00000001, 0x000005c0, 0x00000003,
+        0x0000002c, 0x00000098, 0x0000012c, 0x4e475349, 0x00000064, 0x00000003, 0x00000008, 0x00000050,
         0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000059, 0x00000000, 0x00000000,
         0x00000003, 0x00000001, 0x00000303, 0x0000005e, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
-        0x00000303, 0x49534f50, 0x4e4f4954, 0x45525000, 0x454e0056, 0xab005458, 0x4e47534f, 0x0000004c,
-        0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f,
-        0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000807, 0x505f5653, 0x5449534f,
-        0x004e4f49, 0x495a4542, 0xab005245, 0x52444853, 0x000003d4, 0x00010040, 0x000000f5, 0x04000059,
+        0x00000303, 0x49534f50, 0x4e4f4954, 0x45525000, 0x454e0056, 0xab005458, 0x4e47534f, 0x0000008c,
+        0x00000004, 0x00000008, 0x00000068, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f,
+        0x00000074, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x0000007b, 0x00000000,
+        0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x0000007b, 0x00000001, 0x00000000, 0x00000003,
+        0x00000003, 0x00000c03, 0x505f5653, 0x5449534f, 0x004e4f49, 0x495a4542, 0x53005245, 0x4b4f5254,
+        0x52545f45, 0x46534e41, 0x004d524f, 0x52444853, 0x0000048c, 0x00010040, 0x00000123, 0x04000059,
         0x00208e46, 0x00000000, 0x00000004, 0x0300005f, 0x00101032, 0x00000000, 0x0300005f, 0x00101032,
         0x00000001, 0x0300005f, 0x00101032, 0x00000002, 0x04000067, 0x001020f2, 0x00000000, 0x00000001,
-        0x03000065, 0x00102072, 0x00000001, 0x02000068, 0x00000003, 0x0800000f, 0x00100012, 0x00000000,
-        0x00101046, 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x0800000f, 0x00100022, 0x00000000,
-        0x00101046, 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x0700000f, 0x00100042, 0x00000000,
-        0x00100046, 0x00000000, 0x00100046, 0x00000000, 0x05000044, 0x00100042, 0x00000000, 0x0010002a,
-        0x00000000, 0x07000038, 0x00100032, 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000,
-        0x0800000f, 0x00100012, 0x00000001, 0x00101046, 0x00000001, 0x00208046, 0x00000000, 0x00000000,
-        0x0800000f, 0x00100022, 0x00000001, 0x00101046, 0x00000001, 0x00208046, 0x00000000, 0x00000001,
-        0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000001, 0x05000044,
-        0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000001, 0x00100aa6,
-        0x00000000, 0x00100046, 0x00000001, 0x06000036, 0x001000c2, 0x00000001, 0x80100556, 0x00000041,
-        0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100a26, 0x00000001, 0x00100046, 0x00000000,
-        0x0700000f, 0x00100012, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000000, 0x07000000,
-        0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x3f800000, 0x0800000e, 0x00100012,
-        0x00000000, 0x8010002a, 0x00000041, 0x00000000, 0x0010000a, 0x00000000, 0x09000032, 0x00100032,
-        0x00000000, 0x00100006, 0x00000000, 0x00100046, 0x00000001, 0x00100f36, 0x00000001, 0x08000038,
-        0x00100042, 0x00000000, 0x0020803a, 0x00000000, 0x00000001, 0x00004001, 0x3f000000, 0x05000036,
-        0x00100032, 0x00000001, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001,
-        0x3f800000, 0x08000010, 0x00100012, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000,
-        0x00000000, 0x08000010, 0x00100022, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000,
-        0x00000001, 0x09000032, 0x00100032, 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000,
-        0x00100046, 0x00000002, 0x09000038, 0x00100072, 0x00000001, 0x00208ff6, 0x00000000, 0x00000002,
-        0x00208246, 0x00000000, 0x00000002, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000,
-        0x07000010, 0x00100012, 0x00000001, 0x00100246, 0x00000001, 0x00100246, 0x00000000, 0x09000038,
-        0x00100072, 0x00000002, 0x00208ff6, 0x00000000, 0x00000003, 0x00208246, 0x00000000, 0x00000003,
-        0x07000010, 0x00100022, 0x00000001, 0x00100246, 0x00000002, 0x00100246, 0x00000000, 0x0a000000,
-        0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000,
-        0x00000000, 0x08000036, 0x001020c2, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
-        0x3f800000, 0x08000036, 0x00102072, 0x00000001, 0x00004002, 0x3f800000, 0x00000000, 0x3f800000,
-        0x00000000, 0x0100003e,
+        0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032,
+        0x00000003, 0x02000068, 0x00000003, 0x0800000f, 0x00100012, 0x00000000, 0x00208046, 0x00000000,
+        0x00000000, 0x00101046, 0x00000002, 0x0800000f, 0x00100022, 0x00000000, 0x00208046, 0x00000000,
+        0x00000001, 0x00101046, 0x00000002, 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000000,
+        0x00100046, 0x00000000, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038,
+        0x00100032, 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x0800000f, 0x00100012,
+        0x00000001, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100022,
+        0x00000001, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000001, 0x0700000f, 0x00100042,
+        0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000001, 0x05000044, 0x00100042, 0x00000000,
+        0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046,
+        0x00000001, 0x06000036, 0x001000c2, 0x00000001, 0x80100556, 0x00000041, 0x00000001, 0x0700000f,
+        0x00100042, 0x00000000, 0x00100a26, 0x00000001, 0x00100046, 0x00000000, 0x0700000f, 0x00100012,
+        0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000000, 0x07000000, 0x00100012, 0x00000000,
+        0x0010000a, 0x00000000, 0x00004001, 0x3f800000, 0x0800000e, 0x00100012, 0x00000000, 0x8010002a,
+        0x00000041, 0x00000000, 0x0010000a, 0x00000000, 0x09000032, 0x00100032, 0x00000000, 0x00100006,
+        0x00000000, 0x00100046, 0x00000001, 0x00100f36, 0x00000001, 0x08000038, 0x00100042, 0x00000000,
+        0x0020803a, 0x00000000, 0x00000001, 0x00004001, 0x3f000000, 0x05000036, 0x00100032, 0x00000001,
+        0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010,
+        0x00100012, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000000, 0x08000010,
+        0x00100022, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000001, 0x09000032,
+        0x00100032, 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002,
+        0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x08000010, 0x00100082, 0x00000000,
+        0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000000, 0x08000010, 0x00100012, 0x00000000,
+        0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000000, 0x08000038, 0x00100022, 0x00000000,
+        0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012, 0x00000000,
+        0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032, 0x00000000,
+        0x00100046, 0x00000000, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036,
+        0x001020c2, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x08000036,
+        0x001020f2, 0x00000001, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06000036,
+        0x00100032, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x06000036, 0x001000c2, 0x00000000,
+        0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000,
+        0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000,
+        0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x05000036, 0x00102032, 0x00000002,
+        0x00100086, 0x00000000, 0x05000036, 0x00102032, 0x00000003, 0x001005d6, 0x00000000, 0x0100003e,
     };
     /*     ⎡p0.x p0.y 1⎤
      * A = ⎢p1.x p1.y 1⎥
@@ -2267,9 +2284,15 @@ static HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_t
         float4 transform_rtx;
         float4 transform_rty;
 
-        float4 main(float2 position : POSITION, float2 p0 : P0, float2 p1 : P1, float2 p2 : P2,
-                float2 prev : PREV, float2 next : NEXT, out float4 texcoord : UV,
-                out float2x2 stroke_transform : STROKE_TRANSFORM) : SV_POSITION
+        struct output
+        {
+            float4 position : SV_POSITION;
+            float4 b : BEZIER;
+            nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
+        };
+
+        void main(float2 position : POSITION, float2 p0 : P0, float2 p1 : P1, float2 p2 : P2,
+                float2 prev : PREV, float2 next : NEXT, out struct output o)
         {
             float2 q_prev, q_next, v_p, q_i, p;
             float2x2 geom, rt;
@@ -2277,7 +2300,7 @@ static HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_t
 
             geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
             rt = float2x2(transform_rtx.xy, transform_rty.xy);
-            stroke_transform = rt * stroke_width * 0.5f;
+            o.stroke_transform = rt * stroke_width * 0.5f;
 
             p = mul(geom, position);
             p0 = mul(geom, p0);
@@ -2300,70 +2323,68 @@ static HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_t
             v_p = normalize(float2(-v_p.y, v_p.x));
             if (abs(dot(mul(rt, p1), v_p)) < 1.0f)
             {
-                texcoord.xzw = float3(0.0f, 0.0f, 0.0f);
-                texcoord.y = dot(mul(rt, p), v_p);
+                o.b.xzw = float3(0.0f, 0.0f, 0.0f);
+                o.b.y = dot(mul(rt, p), v_p);
             }
             else
             {
-                texcoord.zw = sign(dot(mul(rt, p1), v_p)) * v_p;
+                o.b.zw = sign(dot(mul(rt, p1), v_p)) * v_p;
                 v_p = -float2(-p.y, p.x) / dot(float2(-p1.y, p1.x), p2);
-                texcoord.x = dot(v_p, p1 - 0.5f * p2);
-                texcoord.y = dot(v_p, p1);
+                o.b.x = dot(v_p, p1 - 0.5f * p2);
+                o.b.y = dot(v_p, p1);
             }
 
-            position = mul(geom, position)
-                    + float2(transform_geometry._31, transform_geometry._32) + stroke_width * q_i;
-            position = mul(rt, position) + float2(transform_rtx.z, transform_rty.z);
-            position = position * float2(transform_rtx.w, transform_rty.w) + float2(-1.0f, 1.0f);
-
-            return float4(position, 0.0f, 1.0f);
+            position = mul(float3(position, 1.0f), transform_geometry) + stroke_width * q_i;
+            position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(position, 1.0f))
+                    * float2(transform_rtx.w, transform_rty.w);
+            o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
         }
 #endif
-        0x43425844, 0x2b43c2df, 0x861ad5cd, 0x32b8fe33, 0x2d50f992, 0x00000001, 0x00000a9c, 0x00000003,
-        0x0000002c, 0x000000e4, 0x00000174, 0x4e475349, 0x000000b0, 0x00000006, 0x00000008, 0x00000098,
+        0x43425844, 0xe65d4bd7, 0x8fdb9a5b, 0xd62a5d61, 0x55d20218, 0x00000001, 0x00000a9c, 0x00000003,
+        0x0000002c, 0x000000e4, 0x00000178, 0x4e475349, 0x000000b0, 0x00000006, 0x00000008, 0x00000098,
         0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x000000a1, 0x00000000, 0x00000000,
         0x00000003, 0x00000001, 0x00000303, 0x000000a1, 0x00000001, 0x00000000, 0x00000003, 0x00000002,
         0x00000303, 0x000000a1, 0x00000002, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x000000a3,
         0x00000000, 0x00000000, 0x00000003, 0x00000004, 0x00000303, 0x000000a8, 0x00000000, 0x00000000,
         0x00000003, 0x00000005, 0x00000303, 0x49534f50, 0x4e4f4954, 0x50005000, 0x00564552, 0x5458454e,
-        0xababab00, 0x4e47534f, 0x00000088, 0x00000004, 0x00000008, 0x00000068, 0x00000000, 0x00000001,
+        0xababab00, 0x4e47534f, 0x0000008c, 0x00000004, 0x00000008, 0x00000068, 0x00000000, 0x00000001,
         0x00000003, 0x00000000, 0x0000000f, 0x00000074, 0x00000000, 0x00000000, 0x00000003, 0x00000001,
-        0x0000000f, 0x00000077, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000077,
+        0x0000000f, 0x0000007b, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x0000007b,
         0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x505f5653, 0x5449534f, 0x004e4f49,
-        0x53005655, 0x4b4f5254, 0x52545f45, 0x46534e41, 0x004d524f, 0x52444853, 0x00000920, 0x00010040,
-        0x00000248, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f, 0x00101032, 0x00000000,
-        0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032, 0x00000002, 0x0300005f, 0x00101032,
-        0x00000003, 0x0300005f, 0x00101032, 0x00000004, 0x0300005f, 0x00101032, 0x00000005, 0x04000067,
-        0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102032,
-        0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x02000068, 0x00000005, 0x0800000f, 0x00100012,
-        0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000005, 0x0800000f, 0x00100022,
-        0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000005, 0x0700000f, 0x00100042,
-        0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000000, 0x05000044, 0x00100042, 0x00000000,
-        0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000000, 0x00100aa6, 0x00000000, 0x00100046,
-        0x00000000, 0x0800000f, 0x00100012, 0x00000001, 0x00208046, 0x00000000, 0x00000000, 0x00101046,
-        0x00000004, 0x0800000f, 0x00100022, 0x00000001, 0x00208046, 0x00000000, 0x00000001, 0x00101046,
-        0x00000004, 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000001,
-        0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000001,
-        0x00100aa6, 0x00000000, 0x00100046, 0x00000001, 0x06000036, 0x001000c2, 0x00000001, 0x80100556,
-        0x00000041, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100a26, 0x00000001, 0x00100046,
-        0x00000000, 0x0700000f, 0x00100012, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000000,
-        0x07000000, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x3f800000, 0x0800000e,
-        0x00100012, 0x00000000, 0x8010002a, 0x00000041, 0x00000000, 0x0010000a, 0x00000000, 0x09000032,
-        0x00100032, 0x00000000, 0x00100006, 0x00000000, 0x00100046, 0x00000001, 0x00100f36, 0x00000001,
-        0x0800000f, 0x00100012, 0x00000001, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000000,
-        0x08000000, 0x00100012, 0x00000002, 0x0010000a, 0x00000001, 0x0020802a, 0x00000000, 0x00000000,
-        0x0800000f, 0x00100022, 0x00000001, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000000,
-        0x08000000, 0x00100022, 0x00000002, 0x0010001a, 0x00000001, 0x0020802a, 0x00000000, 0x00000001,
-        0x0a000032, 0x001000c2, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x00100406, 0x00000000,
-        0x00100406, 0x00000002, 0x0800000f, 0x00100042, 0x00000001, 0x00208046, 0x00000000, 0x00000002,
-        0x00100ae6, 0x00000000, 0x0800000f, 0x00100042, 0x00000000, 0x00208046, 0x00000000, 0x00000003,
-        0x00100ae6, 0x00000000, 0x08000000, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x0020802a,
-        0x00000000, 0x00000003, 0x08000038, 0x00100022, 0x00000002, 0x0010002a, 0x00000000, 0x0020803a,
-        0x00000000, 0x00000003, 0x08000000, 0x00100042, 0x00000000, 0x0010002a, 0x00000001, 0x0020802a,
-        0x00000000, 0x00000002, 0x08000038, 0x00100012, 0x00000002, 0x0010002a, 0x00000000, 0x0020803a,
-        0x00000000, 0x00000002, 0x0a000000, 0x00102032, 0x00000000, 0x00100046, 0x00000002, 0x00004002,
+        0x495a4542, 0x53005245, 0x4b4f5254, 0x52545f45, 0x46534e41, 0x004d524f, 0x52444853, 0x0000091c,
+        0x00010040, 0x00000247, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f, 0x00101032,
+        0x00000000, 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032, 0x00000002, 0x0300005f,
+        0x00101032, 0x00000003, 0x0300005f, 0x00101032, 0x00000004, 0x0300005f, 0x00101032, 0x00000005,
+        0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000001, 0x03000065,
+        0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x02000068, 0x00000005, 0x0800000f,
+        0x00100012, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000005, 0x0800000f,
+        0x00100022, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000005, 0x0700000f,
+        0x00100042, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000000, 0x05000044, 0x00100042,
+        0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000000, 0x00100aa6, 0x00000000,
+        0x00100046, 0x00000000, 0x0800000f, 0x00100012, 0x00000001, 0x00208046, 0x00000000, 0x00000000,
+        0x00101046, 0x00000004, 0x0800000f, 0x00100022, 0x00000001, 0x00208046, 0x00000000, 0x00000001,
+        0x00101046, 0x00000004, 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000001, 0x00100046,
+        0x00000001, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032,
+        0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000001, 0x06000036, 0x001000c2, 0x00000001,
+        0x80100556, 0x00000041, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100a26, 0x00000001,
+        0x00100046, 0x00000000, 0x0700000f, 0x00100012, 0x00000000, 0x00100046, 0x00000001, 0x00100046,
+        0x00000000, 0x07000000, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x3f800000,
+        0x0800000e, 0x00100012, 0x00000000, 0x8010002a, 0x00000041, 0x00000000, 0x0010000a, 0x00000000,
+        0x09000032, 0x00100032, 0x00000000, 0x00100006, 0x00000000, 0x00100046, 0x00000001, 0x00100f36,
+        0x00000001, 0x05000036, 0x00100032, 0x00000001, 0x00101046, 0x00000000, 0x05000036, 0x00100042,
+        0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000002, 0x00100246, 0x00000001,
+        0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00100022, 0x00000002, 0x00100246, 0x00000001,
+        0x00208246, 0x00000000, 0x00000001, 0x0a000032, 0x00100032, 0x00000001, 0x00208ff6, 0x00000000,
+        0x00000001, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x05000036, 0x00100042, 0x00000001,
+        0x00004001, 0x3f800000, 0x08000010, 0x00100042, 0x00000000, 0x00208246, 0x00000000, 0x00000002,
+        0x00100246, 0x00000001, 0x08000010, 0x00100082, 0x00000000, 0x00208246, 0x00000000, 0x00000003,
+        0x00100246, 0x00000001, 0x08000038, 0x00100022, 0x00000001, 0x0010003a, 0x00000000, 0x0020803a,
+        0x00000000, 0x00000003, 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000000, 0x0020803a,
+        0x00000000, 0x00000002, 0x0a000000, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x00004002,
         0xbf800000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036, 0x001020c2, 0x00000000, 0x00004002,
-        0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0800000f, 0x00100012, 0x00000002, 0x00208046,
+        0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0800000f, 0x00100012, 0x00000001, 0x00208046,
+        0x00000000, 0x00000000, 0x00101046, 0x00000000, 0x0800000f, 0x00100022, 0x00000001, 0x00208046,
+        0x00000000, 0x00000001, 0x00101046, 0x00000000, 0x0800000f, 0x00100012, 0x00000002, 0x00208046,
         0x00000000, 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100022, 0x00000002, 0x00208046,
         0x00000000, 0x00000001, 0x00101046, 0x00000001, 0x08000000, 0x001000c2, 0x00000000, 0x00100406,
         0x00000001, 0x80100406, 0x00000041, 0x00000002, 0x0a000032, 0x00100032, 0x00000000, 0x00208ff6,
@@ -2410,51 +2431,81 @@ static HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_t
 #if 0
         float3x2 transform;
 
-        float4 main(float4 position : POSITION, out float3 b : BEZIER) : SV_POSITION
+        struct output
+        {
+            float4 position : SV_POSITION;
+            float4 b : BEZIER;
+            nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
+        };
+
+        void main(float2 position : POSITION, out struct output o)
         {
-            b = float3(1.0, 0.0, 1.0);
-            return float4(mul(position.xyw, transform), position.zw);
+            o.b = float4(1.0, 0.0, 1.0, 1.0);
+            o.stroke_transform = float2x2(1.0, 0.0, 0.0, 1.0);
+            o.position = float4(mul(float3(position, 1.0f), transform), 0.0f, 1.0f);
         }
 #endif
-        0x43425844, 0x846013ae, 0x13dddb07, 0xbbef6d72, 0xb2dd83d5, 0x00000001, 0x00000174, 0x00000003,
-        0x0000002c, 0x00000060, 0x000000b4, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
-        0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0xababab00,
-        0x4e47534f, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003,
-        0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000807,
-        0x505f5653, 0x5449534f, 0x004e4f49, 0x495a4542, 0xab005245, 0x52444853, 0x000000b8, 0x00010040,
-        0x0000002e, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300005f, 0x001010f2, 0x00000000,
-        0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x00102072, 0x00000001, 0x08000010,
-        0x00102012, 0x00000000, 0x00101346, 0x00000000, 0x00208246, 0x00000000, 0x00000000, 0x08000010,
-        0x00102022, 0x00000000, 0x00101346, 0x00000000, 0x00208246, 0x00000000, 0x00000001, 0x05000036,
-        0x001020c2, 0x00000000, 0x00101ea6, 0x00000000, 0x08000036, 0x00102072, 0x00000001, 0x00004002,
-        0x3f800000, 0x00000000, 0x3f800000, 0x00000000, 0x0100003e,
+        0x43425844, 0x39fa8f9d, 0x25509057, 0xcfb2ce2a, 0x9d7fbadc, 0x00000001, 0x00000248, 0x00000003,
+        0x0000002c, 0x00000060, 0x000000f4, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
+        0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x49534f50, 0x4e4f4954, 0xababab00,
+        0x4e47534f, 0x0000008c, 0x00000004, 0x00000008, 0x00000068, 0x00000000, 0x00000001, 0x00000003,
+        0x00000000, 0x0000000f, 0x00000074, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f,
+        0x0000007b, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x0000007b, 0x00000001,
+        0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x505f5653, 0x5449534f, 0x004e4f49, 0x495a4542,
+        0x53005245, 0x4b4f5254, 0x52545f45, 0x46534e41, 0x004d524f, 0x52444853, 0x0000014c, 0x00010040,
+        0x00000053, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300005f, 0x00101032, 0x00000000,
+        0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000001, 0x03000065,
+        0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x02000068, 0x00000001, 0x08000036,
+        0x001020c2, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x05000036,
+        0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001,
+        0x3f800000, 0x08000010, 0x00102012, 0x00000000, 0x00100246, 0x00000000, 0x00208246, 0x00000000,
+        0x00000000, 0x08000010, 0x00102022, 0x00000000, 0x00100246, 0x00000000, 0x00208246, 0x00000000,
+        0x00000001, 0x08000036, 0x001020f2, 0x00000001, 0x00004002, 0x3f800000, 0x00000000, 0x3f800000,
+        0x3f800000, 0x08000036, 0x00102032, 0x00000002, 0x00004002, 0x3f800000, 0x00000000, 0x00000000,
+        0x00000000, 0x08000036, 0x00102032, 0x00000003, 0x00004002, 0x00000000, 0x3f800000, 0x00000000,
+        0x00000000, 0x0100003e,
     };
     static const DWORD vs_code_bezier[] =
     {
 #if 0
         float3x2 transform;
 
-        float4 main(float4 position : POSITION,
-              inout float3 texcoord : TEXCOORD0) : SV_POSITION
+        struct output
+        {
+            float4 position : SV_POSITION;
+            float4 b : BEZIER;
+            nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
+        };
+
+        void main(float2 position : POSITION, float3 texcoord : TEXCOORD0, out struct output o)
         {
-            return float4(mul(position.xyw, transform), position.zw);
+            o.b = float4(texcoord, 1.0);
+            o.stroke_transform = float2x2(1.0, 0.0, 0.0, 1.0);
+            o.position = float4(mul(float3(position, 1.0f), transform), 0.0f, 1.0f);
         }
 #endif
-        0x43425844, 0x5e578adb, 0x093f7e27, 0x50d478af, 0xec3dfa4f, 0x00000001, 0x00000198, 0x00000003,
-        0x0000002c, 0x00000080, 0x000000d8, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038,
-        0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000041, 0x00000000, 0x00000000,
+        0x43425844, 0xb3062c59, 0x502bebd6, 0xb6d3782a, 0x5377c79f, 0x00000001, 0x0000027c, 0x00000003,
+        0x0000002c, 0x00000080, 0x00000114, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038,
+        0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000041, 0x00000000, 0x00000000,
         0x00000003, 0x00000001, 0x00000707, 0x49534f50, 0x4e4f4954, 0x58455400, 0x524f4f43, 0xabab0044,
-        0x4e47534f, 0x00000050, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003,
-        0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000807,
-        0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, 0x44524f4f, 0xababab00, 0x52444853, 0x000000b8,
-        0x00010040, 0x0000002e, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300005f, 0x001010f2,
-        0x00000000, 0x0300005f, 0x00101072, 0x00000001, 0x04000067, 0x001020f2, 0x00000000, 0x00000001,
-        0x03000065, 0x00102072, 0x00000001, 0x08000010, 0x00102012, 0x00000000, 0x00101346, 0x00000000,
-        0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00102022, 0x00000000, 0x00101346, 0x00000000,
-        0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x001020c2, 0x00000000, 0x00101ea6, 0x00000000,
-        0x05000036, 0x00102072, 0x00000001, 0x00101246, 0x00000001, 0x0100003e,
+        0x4e47534f, 0x0000008c, 0x00000004, 0x00000008, 0x00000068, 0x00000000, 0x00000001, 0x00000003,
+        0x00000000, 0x0000000f, 0x00000074, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f,
+        0x0000007b, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x0000007b, 0x00000001,
+        0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x505f5653, 0x5449534f, 0x004e4f49, 0x495a4542,
+        0x53005245, 0x4b4f5254, 0x52545f45, 0x46534e41, 0x004d524f, 0x52444853, 0x00000160, 0x00010040,
+        0x00000058, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300005f, 0x00101032, 0x00000000,
+        0x0300005f, 0x00101072, 0x00000001, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065,
+        0x001020f2, 0x00000001, 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003,
+        0x02000068, 0x00000001, 0x08000036, 0x001020c2, 0x00000000, 0x00004002, 0x00000000, 0x00000000,
+        0x00000000, 0x3f800000, 0x05000036, 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x05000036,
+        0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x08000010, 0x00102012, 0x00000000, 0x00100246,
+        0x00000000, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00102022, 0x00000000, 0x00100246,
+        0x00000000, 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x00102072, 0x00000001, 0x00101246,
+        0x00000001, 0x05000036, 0x00102082, 0x00000001, 0x00004001, 0x3f800000, 0x08000036, 0x00102032,
+        0x00000002, 0x00004002, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x08000036, 0x00102032,
+        0x00000003, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, 0x0100003e,
     };
-    static const DWORD ps_code_fill[] =
+    static const DWORD ps_code[] =
     {
 #if 0
         #define BRUSH_TYPE_SOLID    0
@@ -2462,6 +2513,7 @@ static HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_t
         #define BRUSH_TYPE_BITMAP   2
         #define BRUSH_TYPE_COUNT    3
 
+        bool outline;
         struct brush
         {
             uint type;
@@ -2472,6 +2524,13 @@ static HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_t
         SamplerState s0, s1;
         Texture2D t0, t1;
 
+        struct input
+        {
+            float4 p : SV_POSITION;
+            float4 b : BEZIER;
+            nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
+        };
+
         float4 brush_bitmap(struct brush brush, Texture2D t, SamplerState s, float2 position)
         {
             float3 transform[2];
@@ -2500,193 +2559,106 @@ static HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_t
             return float4(0.0, 0.0, 0.0, brush.opacity);
         }
 
-        float4 main(float4 position : SV_POSITION, float3 b : BEZIER) : SV_Target
+        float4 main(struct input i) : SV_Target
         {
             float4 colour;
 
-            colour = sample_brush(colour_brush, t0, s0, position.xy);
+            colour = sample_brush(colour_brush, t0, s0, i.p.xy);
             if (opacity_brush.type < BRUSH_TYPE_COUNT)
-                colour *= sample_brush(opacity_brush, t1, s1, position.xy).a;
+                colour *= sample_brush(opacity_brush, t1, s1, i.p.xy).a;
 
-            /* Evaluate the implicit form of the curve in texture space.
-             * "b.z" determines which side of the curve is shaded. */
-            clip((b.x * b.x - b.y) * b.z);
+            if (outline)
+            {
+                float2 du, dv, df;
+                float4 uv;
+
+                /* Evaluate the implicit form of the curve (u² - v = 0) in texture space,
+                 * using the screen-space partial derivatives to convert the calculated
+                 * distance to object space.
+                 *
+                 * d(x, y) = |f(x, y)| / ‖∇f(x, y)‖
+                 *         = |f(x, y)| / √((∂f/∂x)² + (∂f/∂y)²)
+                 * f(x, y) = u(x, y)² - v(x, y)
+                 * ∂f/∂x = 2u · ∂u/∂x - ∂v/∂x
+                 * ∂f/∂y = 2u · ∂u/∂y - ∂v/∂y */
+                uv = i.b;
+                du = float2(ddx(uv.x), ddy(uv.x));
+                dv = float2(ddx(uv.y), ddy(uv.y));
+                df = 2.0f * uv.x * du - dv;
+
+                clip(dot(df, uv.zw));
+                clip(length(mul(i.stroke_transform, df)) - abs(uv.x * uv.x - uv.y));
+            }
+            else
+            {
+                /* Evaluate the implicit form of the curve in texture space.
+                 * "i.b.z" determines which side of the curve is shaded. */
+                clip((i.b.x * i.b.x - i.b.y) * i.b.z);
+            }
 
             return colour;
         }
 #endif
-        0x43425844, 0xdd58588a, 0xd71e170f, 0xcc16526c, 0xbf705c92, 0x00000001, 0x00000530, 0x00000003,
-        0x0000002c, 0x00000080, 0x000000b4, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038,
-        0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x00000044, 0x00000000, 0x00000000,
-        0x00000003, 0x00000001, 0x00000707, 0x505f5653, 0x5449534f, 0x004e4f49, 0x495a4542, 0xab005245,
+        0x43425844, 0x94204054, 0xb32c16ca, 0xf1b1691a, 0x21e0e461, 0x00000001, 0x00000778, 0x00000003,
+        0x0000002c, 0x000000c0, 0x000000f4, 0x4e475349, 0x0000008c, 0x00000004, 0x00000008, 0x00000068,
+        0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x00000074, 0x00000000, 0x00000000,
+        0x00000003, 0x00000001, 0x00000f0f, 0x0000007b, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
+        0x00000303, 0x0000007b, 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x505f5653,
+        0x5449534f, 0x004e4f49, 0x495a4542, 0x53005245, 0x4b4f5254, 0x52545f45, 0x46534e41, 0x004d524f,
         0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
-        0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000474, 0x00000040,
-        0x0000011d, 0x04000059, 0x00208e46, 0x00000000, 0x00000006, 0x0300005a, 0x00106000, 0x00000000,
+        0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x0000067c, 0x00000040,
+        0x0000019f, 0x04000059, 0x00208e46, 0x00000000, 0x00000007, 0x0300005a, 0x00106000, 0x00000000,
         0x0300005a, 0x00106000, 0x00000001, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04001858,
         0x00107000, 0x00000001, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03001062,
-        0x00101072, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000003, 0x09000038,
-        0x001000f2, 0x00000000, 0x00208556, 0x00000000, 0x00000000, 0x00208e46, 0x00000000, 0x00000001,
-        0x0404001f, 0x0020800a, 0x00000000, 0x00000000, 0x08000020, 0x00100012, 0x00000001, 0x0020800a,
-        0x00000000, 0x00000000, 0x00004001, 0x00000002, 0x0304001f, 0x0010000a, 0x00000001, 0x0800000f,
-        0x00100022, 0x00000001, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x08000000,
-        0x00100012, 0x00000002, 0x0010001a, 0x00000001, 0x0020802a, 0x00000000, 0x00000001, 0x0800000f,
-        0x00100022, 0x00000001, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x08000000,
-        0x00100022, 0x00000002, 0x0010001a, 0x00000001, 0x0020802a, 0x00000000, 0x00000002, 0x09000045,
-        0x001000f2, 0x00000002, 0x00100046, 0x00000002, 0x00107e46, 0x00000000, 0x00106000, 0x00000000,
-        0x0a000037, 0x00100082, 0x00000002, 0x0020803a, 0x00000000, 0x00000002, 0x00004001, 0x3f800000,
-        0x0010003a, 0x00000002, 0x08000038, 0x001000f2, 0x00000000, 0x00100e46, 0x00000002, 0x00208556,
-        0x00000000, 0x00000000, 0x01000015, 0x05000036, 0x00100012, 0x00000002, 0x00004001, 0x00000000,
-        0x06000036, 0x00100082, 0x00000002, 0x0020801a, 0x00000000, 0x00000000, 0x09000037, 0x001000f2,
-        0x00000000, 0x00100006, 0x00000001, 0x00100e46, 0x00000000, 0x00100c06, 0x00000002, 0x01000015,
-        0x0800004f, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000003, 0x00004001, 0x00000003,
-        0x0304001f, 0x0010000a, 0x00000001, 0x09000038, 0x00100012, 0x00000001, 0x0020801a, 0x00000000,
-        0x00000003, 0x0020803a, 0x00000000, 0x00000004, 0x0404001f, 0x0020800a, 0x00000000, 0x00000003,
-        0x08000020, 0x00100022, 0x00000001, 0x0020800a, 0x00000000, 0x00000003, 0x00004001, 0x00000002,
-        0x0304001f, 0x0010001a, 0x00000001, 0x0800000f, 0x00100042, 0x00000001, 0x00101046, 0x00000000,
-        0x00208046, 0x00000000, 0x00000004, 0x08000000, 0x00100012, 0x00000002, 0x0010002a, 0x00000001,
-        0x0020802a, 0x00000000, 0x00000004, 0x0800000f, 0x00100042, 0x00000001, 0x00101046, 0x00000000,
-        0x00208046, 0x00000000, 0x00000005, 0x08000000, 0x00100022, 0x00000002, 0x0010002a, 0x00000001,
-        0x0020802a, 0x00000000, 0x00000005, 0x09000045, 0x001000f2, 0x00000002, 0x00100046, 0x00000002,
-        0x00107e46, 0x00000001, 0x00106000, 0x00000001, 0x0a000037, 0x00100042, 0x00000001, 0x0020803a,
-        0x00000000, 0x00000005, 0x00004001, 0x3f800000, 0x0010003a, 0x00000002, 0x08000038, 0x00100012,
-        0x00000001, 0x0010002a, 0x00000001, 0x0020801a, 0x00000000, 0x00000003, 0x01000015, 0x0a000037,
-        0x00100012, 0x00000001, 0x0010001a, 0x00000001, 0x0010000a, 0x00000001, 0x0020801a, 0x00000000,
-        0x00000003, 0x01000015, 0x07000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00100006,
-        0x00000001, 0x01000012, 0x05000036, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x01000015,
-        0x0a000032, 0x00100012, 0x00000000, 0x0010100a, 0x00000001, 0x0010100a, 0x00000001, 0x8010101a,
-        0x00000041, 0x00000001, 0x07000038, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x0010102a,
-        0x00000001, 0x07000031, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000,
-        0x0304000d, 0x0010000a, 0x00000000, 0x0100003e,
-    };
-    static const DWORD ps_code_bezier_outline[] =
-    {
-#if 0
-        #define BRUSH_TYPE_SOLID    0
-        #define BRUSH_TYPE_LINEAR   1
-        #define BRUSH_TYPE_BITMAP   2
-        #define BRUSH_TYPE_COUNT    3
-
-        struct brush
-        {
-            uint type;
-            float opacity;
-            float4 data[2];
-        } colour_brush, opacity_brush;
-
-        SamplerState s0, s1;
-        Texture2D t0, t1;
-
-        float4 brush_bitmap(struct brush brush, Texture2D t, SamplerState s, float2 position)
-        {
-            float3 transform[2];
-            bool ignore_alpha;
-            float2 texcoord;
-            float4 colour;
-
-            transform[0] = brush.data[0].xyz;
-            transform[1] = brush.data[1].xyz;
-            ignore_alpha = asuint(brush.data[1].w);
-
-            texcoord.x = dot(position.xy, transform[0].xy) + transform[0].z;
-            texcoord.y = dot(position.xy, transform[1].xy) + transform[1].z;
-            colour = t.Sample(s, texcoord);
-            if (ignore_alpha)
-                colour.a = 1.0;
-            return colour;
-        }
-
-        float4 sample_brush(struct brush brush, Texture2D t, SamplerState s, float2 position)
-        {
-            if (brush.type == BRUSH_TYPE_SOLID)
-                return brush.data[0] * brush.opacity;
-            if (brush.type == BRUSH_TYPE_BITMAP)
-                return brush_bitmap(brush, t, s, position) * brush.opacity;
-            return float4(0.0, 0.0, 0.0, brush.opacity);
-        }
-
-        float4 main(float4 position : SV_POSITION, float4 uv : UV,
-                nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM) : SV_Target
-        {
-            float2 du, dv, df;
-            float4 colour;
-
-            colour = sample_brush(colour_brush, t0, s0, position.xy);
-            if (opacity_brush.type < BRUSH_TYPE_COUNT)
-                colour *= sample_brush(opacity_brush, t1, s1, position.xy).a;
-
-            /* Evaluate the implicit form of the curve (u² - v = 0) in texture space,
-             * using the screen-space partial derivatives to convert the calculated
-             * distance to object space.
-             *
-             * d(x, y) = |f(x, y)| / ‖∇f(x, y)‖
-             *         = |f(x, y)| / √((∂f/∂x)² + (∂f/∂y)²)
-             * f(x, y) = u(x, y)² - v(x, y)
-             * ∂f/∂x = 2u · ∂u/∂x - ∂v/∂x
-             * ∂f/∂y = 2u · ∂u/∂y - ∂v/∂y */
-            du = float2(ddx(uv.x), ddy(uv.x));
-            dv = float2(ddx(uv.y), ddy(uv.y));
-            df = 2.0f * uv.x * du - dv;
-
-            clip(dot(df, uv.zw));
-            clip(length(mul(stroke_transform, df)) - abs(uv.x * uv.x - uv.y));
-
-            return colour;
-        }
-#endif
-        0x43425844, 0x02d0d058, 0x91f8cb40, 0x6353fe27, 0x6e2f51f5, 0x00000001, 0x000006a8, 0x00000003,
-        0x0000002c, 0x000000bc, 0x000000f0, 0x4e475349, 0x00000088, 0x00000004, 0x00000008, 0x00000068,
-        0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x00000074, 0x00000000, 0x00000000,
-        0x00000003, 0x00000001, 0x00000f0f, 0x00000077, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
-        0x00000303, 0x00000077, 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x505f5653,
-        0x5449534f, 0x004e4f49, 0x53005655, 0x4b4f5254, 0x52545f45, 0x46534e41, 0x004d524f, 0x4e47534f,
-        0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000,
-        0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x000005b0, 0x00000040, 0x0000016c,
-        0x04000059, 0x00208e46, 0x00000000, 0x00000006, 0x0300005a, 0x00106000, 0x00000000, 0x0300005a,
-        0x00106000, 0x00000001, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04001858, 0x00107000,
-        0x00000001, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03001062, 0x001010f2,
-        0x00000001, 0x03000862, 0x00101032, 0x00000002, 0x03000862, 0x00101032, 0x00000003, 0x03000065,
-        0x001020f2, 0x00000000, 0x02000068, 0x00000003, 0x09000038, 0x001000f2, 0x00000000, 0x00208556,
-        0x00000000, 0x00000000, 0x00208e46, 0x00000000, 0x00000001, 0x0404001f, 0x0020800a, 0x00000000,
-        0x00000000, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000000, 0x00004001,
-        0x00000002, 0x0304001f, 0x0010000a, 0x00000001, 0x0800000f, 0x00100022, 0x00000001, 0x00101046,
-        0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x08000000, 0x00100012, 0x00000002, 0x0010001a,
-        0x00000001, 0x0020802a, 0x00000000, 0x00000001, 0x0800000f, 0x00100022, 0x00000001, 0x00101046,
-        0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x08000000, 0x00100022, 0x00000002, 0x0010001a,
-        0x00000001, 0x0020802a, 0x00000000, 0x00000002, 0x09000045, 0x001000f2, 0x00000002, 0x00100046,
-        0x00000002, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0a000037, 0x00100082, 0x00000002,
-        0x0020803a, 0x00000000, 0x00000002, 0x00004001, 0x3f800000, 0x0010003a, 0x00000002, 0x08000038,
-        0x001000f2, 0x00000000, 0x00100e46, 0x00000002, 0x00208556, 0x00000000, 0x00000000, 0x01000015,
-        0x05000036, 0x00100012, 0x00000002, 0x00004001, 0x00000000, 0x06000036, 0x00100082, 0x00000002,
-        0x0020801a, 0x00000000, 0x00000000, 0x09000037, 0x001000f2, 0x00000000, 0x00100006, 0x00000001,
-        0x00100e46, 0x00000000, 0x00100c06, 0x00000002, 0x01000015, 0x0800004f, 0x00100012, 0x00000001,
-        0x0020800a, 0x00000000, 0x00000003, 0x00004001, 0x00000003, 0x0304001f, 0x0010000a, 0x00000001,
-        0x09000038, 0x00100012, 0x00000001, 0x0020801a, 0x00000000, 0x00000003, 0x0020803a, 0x00000000,
-        0x00000004, 0x0404001f, 0x0020800a, 0x00000000, 0x00000003, 0x08000020, 0x00100022, 0x00000001,
-        0x0020800a, 0x00000000, 0x00000003, 0x00004001, 0x00000002, 0x0304001f, 0x0010001a, 0x00000001,
-        0x0800000f, 0x00100042, 0x00000001, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000004,
-        0x08000000, 0x00100012, 0x00000002, 0x0010002a, 0x00000001, 0x0020802a, 0x00000000, 0x00000004,
-        0x0800000f, 0x00100042, 0x00000001, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000005,
-        0x08000000, 0x00100022, 0x00000002, 0x0010002a, 0x00000001, 0x0020802a, 0x00000000, 0x00000005,
-        0x09000045, 0x001000f2, 0x00000002, 0x00100046, 0x00000002, 0x00107e46, 0x00000001, 0x00106000,
-        0x00000001, 0x0a000037, 0x00100042, 0x00000001, 0x0020803a, 0x00000000, 0x00000005, 0x00004001,
-        0x3f800000, 0x0010003a, 0x00000002, 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001,
-        0x0020801a, 0x00000000, 0x00000003, 0x01000015, 0x0a000037, 0x00100012, 0x00000001, 0x0010001a,
-        0x00000001, 0x0010000a, 0x00000001, 0x0020801a, 0x00000000, 0x00000003, 0x01000015, 0x07000038,
-        0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00100006, 0x00000001, 0x01000012, 0x05000036,
-        0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x01000015, 0x0500000b, 0x00100032, 0x00000000,
-        0x00101046, 0x00000001, 0x0500000c, 0x001000c2, 0x00000000, 0x00101406, 0x00000001, 0x07000000,
-        0x00100012, 0x00000001, 0x0010100a, 0x00000001, 0x0010100a, 0x00000001, 0x0a000032, 0x00100032,
-        0x00000000, 0x00100006, 0x00000001, 0x00100086, 0x00000000, 0x801005d6, 0x00000041, 0x00000000,
-        0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000000, 0x00101ae6, 0x00000001, 0x07000031,
-        0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x00004001, 0x00000000, 0x0304000d, 0x0010002a,
-        0x00000000, 0x07000038, 0x00100062, 0x00000000, 0x00100556, 0x00000000, 0x00101106, 0x00000003,
-        0x09000032, 0x00100032, 0x00000000, 0x00101046, 0x00000002, 0x00100006, 0x00000000, 0x00100596,
-        0x00000000, 0x0700000f, 0x00100012, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000000,
-        0x0500004b, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x0a000032, 0x00100022, 0x00000000,
-        0x0010100a, 0x00000001, 0x0010100a, 0x00000001, 0x8010101a, 0x00000041, 0x00000001, 0x08000000,
-        0x00100012, 0x00000000, 0x8010001a, 0x000000c1, 0x00000000, 0x0010000a, 0x00000000, 0x07000031,
-        0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x0304000d, 0x0010000a,
-        0x00000000, 0x0100003e,
+        0x001010f2, 0x00000001, 0x03000862, 0x00101032, 0x00000002, 0x03000862, 0x00101032, 0x00000003,
+        0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000003, 0x09000038, 0x001000f2, 0x00000000,
+        0x00208556, 0x00000000, 0x00000001, 0x00208e46, 0x00000000, 0x00000002, 0x0404001f, 0x0020800a,
+        0x00000000, 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001,
+        0x00004001, 0x00000002, 0x0304001f, 0x0010000a, 0x00000001, 0x0800000f, 0x00100022, 0x00000001,
+        0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x08000000, 0x00100012, 0x00000002,
+        0x0010001a, 0x00000001, 0x0020802a, 0x00000000, 0x00000002, 0x0800000f, 0x00100022, 0x00000001,
+        0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x08000000, 0x00100022, 0x00000002,
+        0x0010001a, 0x00000001, 0x0020802a, 0x00000000, 0x00000003, 0x09000045, 0x001000f2, 0x00000002,
+        0x00100046, 0x00000002, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0a000037, 0x00100082,
+        0x00000002, 0x0020803a, 0x00000000, 0x00000003, 0x00004001, 0x3f800000, 0x0010003a, 0x00000002,
+        0x08000038, 0x001000f2, 0x00000000, 0x00100e46, 0x00000002, 0x00208556, 0x00000000, 0x00000001,
+        0x01000015, 0x05000036, 0x00100012, 0x00000002, 0x00004001, 0x00000000, 0x06000036, 0x00100082,
+        0x00000002, 0x0020801a, 0x00000000, 0x00000001, 0x09000037, 0x001000f2, 0x00000000, 0x00100006,
+        0x00000001, 0x00100e46, 0x00000000, 0x00100c06, 0x00000002, 0x01000015, 0x0800004f, 0x00100012,
+        0x00000001, 0x0020800a, 0x00000000, 0x00000004, 0x00004001, 0x00000003, 0x0304001f, 0x0010000a,
+        0x00000001, 0x09000038, 0x00100012, 0x00000001, 0x0020801a, 0x00000000, 0x00000004, 0x0020803a,
+        0x00000000, 0x00000005, 0x0404001f, 0x0020800a, 0x00000000, 0x00000004, 0x08000020, 0x00100022,
+        0x00000001, 0x0020800a, 0x00000000, 0x00000004, 0x00004001, 0x00000002, 0x0304001f, 0x0010001a,
+        0x00000001, 0x0800000f, 0x00100042, 0x00000001, 0x00101046, 0x00000000, 0x00208046, 0x00000000,
+        0x00000005, 0x08000000, 0x00100012, 0x00000002, 0x0010002a, 0x00000001, 0x0020802a, 0x00000000,
+        0x00000005, 0x0800000f, 0x00100042, 0x00000001, 0x00101046, 0x00000000, 0x00208046, 0x00000000,
+        0x00000006, 0x08000000, 0x00100022, 0x00000002, 0x0010002a, 0x00000001, 0x0020802a, 0x00000000,
+        0x00000006, 0x09000045, 0x001000f2, 0x00000002, 0x00100046, 0x00000002, 0x00107e46, 0x00000001,
+        0x00106000, 0x00000001, 0x0a000037, 0x00100042, 0x00000001, 0x0020803a, 0x00000000, 0x00000006,
+        0x00004001, 0x3f800000, 0x0010003a, 0x00000002, 0x08000038, 0x00100012, 0x00000001, 0x0010002a,
+        0x00000001, 0x0020801a, 0x00000000, 0x00000004, 0x01000015, 0x0a000037, 0x00100012, 0x00000001,
+        0x0010001a, 0x00000001, 0x0010000a, 0x00000001, 0x0020801a, 0x00000000, 0x00000004, 0x01000015,
+        0x07000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00100006, 0x00000001, 0x01000012,
+        0x05000036, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x01000015, 0x08000027, 0x00100012,
+        0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x00004001, 0x00000000, 0x0500003b, 0x00100022,
+        0x00000000, 0x0010000a, 0x00000000, 0x0500000b, 0x00100032, 0x00000001, 0x00101046, 0x00000001,
+        0x0500000c, 0x001000c2, 0x00000001, 0x00101406, 0x00000001, 0x07000000, 0x00100042, 0x00000000,
+        0x0010100a, 0x00000001, 0x0010100a, 0x00000001, 0x0a000032, 0x001000c2, 0x00000000, 0x00100aa6,
+        0x00000000, 0x00100806, 0x00000001, 0x80100d56, 0x00000041, 0x00000001, 0x0700000f, 0x00100012,
+        0x00000001, 0x00100ae6, 0x00000000, 0x00101ae6, 0x00000001, 0x07000031, 0x00100012, 0x00000001,
+        0x0010000a, 0x00000001, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000001, 0x0010000a,
+        0x00000000, 0x0010000a, 0x00000001, 0x0304000d, 0x0010000a, 0x00000001, 0x07000038, 0x00100032,
+        0x00000001, 0x00100ff6, 0x00000000, 0x00101046, 0x00000003, 0x09000032, 0x001000c2, 0x00000000,
+        0x00101406, 0x00000002, 0x00100aa6, 0x00000000, 0x00100406, 0x00000001, 0x0700000f, 0x00100042,
+        0x00000000, 0x00100ae6, 0x00000000, 0x00100ae6, 0x00000000, 0x0500004b, 0x00100042, 0x00000000,
+        0x0010002a, 0x00000000, 0x0a000032, 0x00100082, 0x00000000, 0x0010100a, 0x00000001, 0x0010100a,
+        0x00000001, 0x8010101a, 0x00000041, 0x00000001, 0x08000000, 0x00100042, 0x00000000, 0x8010003a,
+        0x000000c1, 0x00000000, 0x0010002a, 0x00000000, 0x07000031, 0x00100042, 0x00000000, 0x0010002a,
+        0x00000000, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000000, 0x0010000a, 0x00000000,
+        0x0010002a, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x07000038, 0x00100012, 0x00000000,
+        0x0010003a, 0x00000000, 0x0010102a, 0x00000001, 0x07000031, 0x00100012, 0x00000000, 0x0010000a,
+        0x00000000, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000000, 0x0010001a, 0x00000000,
+        0x0010000a, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x0100003e,
     };
     static const struct shape_info
     {
@@ -2695,23 +2667,17 @@ static HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_t
         unsigned int il_element_count;
         const void *vs_code;
         size_t vs_code_size;
-        const void *ps_code;
-        size_t ps_code_size;
     }
     shape_info[] =
     {
         {D2D_SHAPE_TYPE_OUTLINE,        il_desc_outline,        ARRAY_SIZE(il_desc_outline),
-                                        vs_code_outline,        sizeof(vs_code_outline),
-                                        ps_code_fill,           sizeof(ps_code_fill)},
+                                        vs_code_outline,        sizeof(vs_code_outline)},
         {D2D_SHAPE_TYPE_BEZIER_OUTLINE, il_desc_bezier_outline, ARRAY_SIZE(il_desc_bezier_outline),
-                                        vs_code_bezier_outline, sizeof(vs_code_bezier_outline),
-                                        ps_code_bezier_outline, sizeof(ps_code_bezier_outline)},
+                                        vs_code_bezier_outline, sizeof(vs_code_bezier_outline)},
         {D2D_SHAPE_TYPE_TRIANGLE,       il_desc_triangle,       ARRAY_SIZE(il_desc_triangle),
-                                        vs_code_triangle,       sizeof(vs_code_triangle),
-                                        ps_code_fill,           sizeof(ps_code_fill)},
+                                        vs_code_triangle,       sizeof(vs_code_triangle)},
         {D2D_SHAPE_TYPE_BEZIER,         il_desc_bezier,         ARRAY_SIZE(il_desc_bezier),
-                                        vs_code_bezier,         sizeof(vs_code_bezier),
-                                        ps_code_fill,           sizeof(ps_code_fill)},
+                                        vs_code_bezier,         sizeof(vs_code_bezier)},
     };
     static const struct
     {
@@ -2806,12 +2772,13 @@ static HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_t
             goto err;
         }
 
-        if (FAILED(hr = ID3D10Device_CreatePixelShader(render_target->device, si->ps_code,
-                si->ps_code_size, &render_target->shape_resources[si->shape_type].ps)))
-        {
-            WARN("Failed to create pixel shader for shape type %#x, hr %#x.\n", si->shape_type, hr);
-            goto err;
-        }
+    }
+
+    if (FAILED(hr = ID3D10Device_CreatePixelShader(render_target->device,
+            ps_code, sizeof(ps_code), &render_target->ps)))
+    {
+        WARN("Failed to create pixel shader, hr %#x.\n", hr);
+        goto err;
     }
 
     buffer_desc.ByteWidth = sizeof(indices);
@@ -2931,10 +2898,10 @@ err:
         ID3D10Buffer_Release(render_target->vb);
     if (render_target->ib)
         ID3D10Buffer_Release(render_target->ib);
+    if (render_target->ps)
+        ID3D10PixelShader_Release(render_target->ps);
     for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
     {
-        if (render_target->shape_resources[i].ps)
-            ID3D10PixelShader_Release(render_target->shape_resources[i].ps);
         if (render_target->shape_resources[i].vs)
             ID3D10VertexShader_Release(render_target->shape_resources[i].vs);
         if (render_target->shape_resources[i].il)
-- 
2.1.4




More information about the wine-patches mailing list