[PATCH 3/3] d2d1: Reuse PS constant buffer object.

Nikolay Sivov nsivov at codeweavers.com
Tue Jun 8 03:56:49 CDT 2021


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/d2d1/brush.c        |  32 ++-------
 dlls/d2d1/d2d1_private.h |   5 +-
 dlls/d2d1/device.c       | 136 ++++++++++++++++++++++-----------------
 3 files changed, 86 insertions(+), 87 deletions(-)

diff --git a/dlls/d2d1/brush.c b/dlls/d2d1/brush.c
index 70d0c77466d..786fbc7f887 100644
--- a/dlls/d2d1/brush.c
+++ b/dlls/d2d1/brush.c
@@ -1238,35 +1238,17 @@ static BOOL d2d_brush_fill_cb(const struct d2d_brush *brush, struct d2d_brush_cb
     }
 }
 
-HRESULT d2d_brush_get_ps_cb(struct d2d_brush *brush, struct d2d_brush *opacity_brush,
-        BOOL outline, BOOL is_arc, struct d2d_device_context *render_target, ID3D10Buffer **ps_cb)
+HRESULT d2d_brush_init_ps_cb_data(struct d2d_brush *brush, struct d2d_brush *opacity_brush,
+        BOOL outline, BOOL is_arc, struct d2d_ps_cb *cb_data)
 {
-    D3D10_SUBRESOURCE_DATA buffer_data;
-    struct d2d_ps_cb cb_data = {0};
-    D3D10_BUFFER_DESC buffer_desc;
-    HRESULT hr;
-
-    cb_data.outline = outline;
-    cb_data.is_arc = is_arc;
-    if (!d2d_brush_fill_cb(brush, &cb_data.colour_brush))
+    cb_data->outline = outline;
+    cb_data->is_arc = is_arc;
+    if (!d2d_brush_fill_cb(brush, &cb_data->colour_brush))
         return E_NOTIMPL;
-    if (!d2d_brush_fill_cb(opacity_brush, &cb_data.opacity_brush))
+    if (!d2d_brush_fill_cb(opacity_brush, &cb_data->opacity_brush))
         return E_NOTIMPL;
 
-    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 = &cb_data;
-    buffer_data.SysMemPitch = 0;
-    buffer_data.SysMemSlicePitch = 0;
-
-    if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, ps_cb)))
-        ERR("Failed to create constant buffer, hr %#x.\n", hr);
-
-    return hr;
+    return S_OK;
 }
 
 static void d2d_brush_bind_bitmap(struct d2d_brush *brush, struct d2d_device_context *context,
diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h
index 4be52b2fd10..be0ee8a49e7 100644
--- a/dlls/d2d1/d2d1_private.h
+++ b/dlls/d2d1/d2d1_private.h
@@ -150,6 +150,7 @@ struct d2d_device_context
     ID3D10StateBlock *stateblock;
     struct d2d_shape_resources shape_resources[D2D_SHAPE_TYPE_COUNT];
     ID3D10PixelShader *ps;
+    ID3D10Buffer *ps_cb;
     ID3D10Buffer *ib;
     unsigned int vb_stride;
     ID3D10Buffer *vb;
@@ -314,8 +315,8 @@ HRESULT d2d_bitmap_brush_create(ID2D1Factory *factory, ID2D1Bitmap *bitmap,
         struct d2d_brush **brush) DECLSPEC_HIDDEN;
 void d2d_brush_bind_resources(struct d2d_brush *brush, struct d2d_device_context *context,
         unsigned int brush_idx) DECLSPEC_HIDDEN;
-HRESULT d2d_brush_get_ps_cb(struct d2d_brush *brush, struct d2d_brush *opacity_brush, BOOL outline, BOOL is_arc,
-        struct d2d_device_context *render_target, ID3D10Buffer **ps_cb) DECLSPEC_HIDDEN;
+HRESULT d2d_brush_init_ps_cb_data(struct d2d_brush *brush, struct d2d_brush *opacity_brush, BOOL outline, BOOL is_arc,
+        struct d2d_ps_cb *cb_data) DECLSPEC_HIDDEN;
 struct d2d_brush *unsafe_impl_from_ID2D1Brush(ID2D1Brush *iface) DECLSPEC_HIDDEN;
 
 struct d2d_stroke_style
diff --git a/dlls/d2d1/device.c b/dlls/d2d1/device.c
index b078d927858..240bf835ca2 100644
--- a/dlls/d2d1/device.c
+++ b/dlls/d2d1/device.c
@@ -119,7 +119,7 @@ static void d2d_clip_stack_pop(struct d2d_clip_stack *stack)
 
 static void d2d_device_context_draw(struct d2d_device_context *render_target, enum d2d_shape_type shape_type,
         ID3D10Buffer *ib, unsigned int index_count, ID3D10Buffer *vb, unsigned int vb_stride,
-        ID3D10Buffer *vs_cb, ID3D10Buffer *ps_cb, struct d2d_brush *brush, struct d2d_brush *opacity_brush)
+        ID3D10Buffer *vs_cb, struct d2d_brush *brush, struct d2d_brush *opacity_brush)
 {
     struct d2d_shape_resources *shape_resources = &render_target->shape_resources[shape_type];
     ID3D10Device *device = render_target->d3d_device;
@@ -150,7 +150,7 @@ static void d2d_device_context_draw(struct d2d_device_context *render_target, en
     ID3D10Device_IASetVertexBuffers(device, 0, 1, &vb, &vb_stride, &offset);
     ID3D10Device_VSSetConstantBuffers(device, 0, 1, &vs_cb);
     ID3D10Device_VSSetShader(device, shape_resources->vs);
-    ID3D10Device_PSSetConstantBuffers(device, 0, 1, &ps_cb);
+    ID3D10Device_PSSetConstantBuffers(device, 0, 1, &render_target->ps_cb);
     ID3D10Device_PSSetShader(device, render_target->ps);
     ID3D10Device_RSSetViewports(device, 1, &vp);
     if (render_target->clip_stack.count)
@@ -266,6 +266,8 @@ static ULONG STDMETHODCALLTYPE d2d_device_context_inner_Release(IUnknown *iface)
         ID3D10Buffer_Release(context->vb);
         ID3D10Buffer_Release(context->ib);
         ID3D10PixelShader_Release(context->ps);
+        if (context->ps_cb)
+            ID3D10Buffer_Release(context->ps_cb);
         for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
         {
             ID3D10VertexShader_Release(context->shape_resources[i].vs);
@@ -706,12 +708,59 @@ static void STDMETHODCALLTYPE d2d_device_context_FillEllipse(ID2D1DeviceContext
     ID2D1EllipseGeometry_Release(geometry);
 }
 
+static HRESULT d2d_device_context_update_ps_cb(struct d2d_device_context *context,
+        struct d2d_brush *brush, struct d2d_brush *opacity_brush, BOOL outline, BOOL is_arc)
+{
+    D3D10_SUBRESOURCE_DATA buffer_data;
+    struct d2d_ps_cb cb_data = {0};
+    D3D10_BUFFER_DESC buffer_desc;
+    void *data;
+    HRESULT hr;
+
+    if (FAILED(hr = d2d_brush_init_ps_cb_data(brush, opacity_brush, outline, is_arc, &cb_data)))
+    {
+        WARN("Failed to initialize brush constant buffer data, hr %#x.\n", hr);
+        return hr;
+    }
+
+    if (context->ps_cb)
+    {
+        if (SUCCEEDED(hr = ID3D10Buffer_Map(context->ps_cb, D3D10_MAP_WRITE_DISCARD, 0, &data)))
+        {
+            memcpy(data, &cb_data, sizeof(cb_data));
+            ID3D10Buffer_Unmap(context->ps_cb);
+        }
+        else
+            ERR("Failed to map constant buffer, hr %#x.\n", hr);
+    }
+    else
+    {
+        buffer_desc.ByteWidth = sizeof(cb_data);
+        buffer_desc.Usage = D3D10_USAGE_DYNAMIC;
+        buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
+        buffer_desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
+        buffer_desc.MiscFlags = 0;
+
+        buffer_data.pSysMem = &cb_data;
+        buffer_data.SysMemPitch = 0;
+        buffer_data.SysMemSlicePitch = 0;
+
+        if (FAILED(hr = ID3D10Device_CreateBuffer(context->d3d_device, &buffer_desc, &buffer_data,
+                &context->ps_cb)))
+        {
+            ERR("Failed to create constant buffer, hr %#x.\n", hr);
+        }
+    }
+
+    return hr;
+}
+
 static void d2d_device_context_draw_geometry(struct d2d_device_context *render_target,
         const struct d2d_geometry *geometry, struct d2d_brush *brush, float stroke_width)
 {
-    ID3D10Buffer *ib, *vb, *vs_cb, *ps_cb_bezier, *ps_cb_arc;
     D3D10_SUBRESOURCE_DATA buffer_data;
     D3D10_BUFFER_DESC buffer_desc;
+    ID3D10Buffer *ib, *vb, *vs_cb;
     const D2D1_MATRIX_3X2_F *w;
     float tmp_x, tmp_y;
     HRESULT hr;
@@ -765,18 +814,10 @@ static void d2d_device_context_draw_geometry(struct d2d_device_context *render_t
         return;
     }
 
-    if (FAILED(hr = d2d_brush_get_ps_cb(brush, NULL, TRUE, FALSE, render_target, &ps_cb_bezier)))
-    {
-        WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
-        ID3D10Buffer_Release(vs_cb);
-        return;
-    }
-
-    if (FAILED(hr = d2d_brush_get_ps_cb(brush, NULL, TRUE, TRUE, render_target, &ps_cb_arc)))
+    if (FAILED(hr = d2d_device_context_update_ps_cb(render_target, brush, NULL, TRUE, FALSE)))
     {
-        WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
+        WARN("Failed to update constant buffer, hr %#x.\n", hr);
         ID3D10Buffer_Release(vs_cb);
-        ID3D10Buffer_Release(ps_cb_bezier);
         return;
     }
 
@@ -804,7 +845,7 @@ static void d2d_device_context_draw_geometry(struct d2d_device_context *render_t
         }
 
         d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_OUTLINE, ib, 3 * geometry->outline.face_count, vb,
-                sizeof(*geometry->outline.vertices), vs_cb, ps_cb_bezier, brush, NULL);
+                sizeof(*geometry->outline.vertices), vs_cb, brush, NULL);
 
         ID3D10Buffer_Release(vb);
         ID3D10Buffer_Release(ib);
@@ -835,7 +876,7 @@ static void d2d_device_context_draw_geometry(struct d2d_device_context *render_t
 
         d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_BEZIER_OUTLINE, ib,
                 3 * geometry->outline.bezier_face_count, vb,
-                sizeof(*geometry->outline.beziers), vs_cb, ps_cb_bezier, brush, NULL);
+                sizeof(*geometry->outline.beziers), vs_cb, brush, NULL);
 
         ID3D10Buffer_Release(vb);
         ID3D10Buffer_Release(ib);
@@ -864,17 +905,16 @@ static void d2d_device_context_draw_geometry(struct d2d_device_context *render_t
             goto done;
         }
 
-        d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_ARC_OUTLINE, ib,
-                3 * geometry->outline.arc_face_count, vb,
-                sizeof(*geometry->outline.arcs), vs_cb, ps_cb_arc, brush, NULL);
+        if (SUCCEEDED(d2d_device_context_update_ps_cb(render_target, brush, NULL, TRUE, TRUE)))
+            d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_ARC_OUTLINE, ib,
+                    3 * geometry->outline.arc_face_count, vb,
+                    sizeof(*geometry->outline.arcs), vs_cb, brush, NULL);
 
         ID3D10Buffer_Release(vb);
         ID3D10Buffer_Release(ib);
     }
 
 done:
-    ID3D10Buffer_Release(ps_cb_arc);
-    ID3D10Buffer_Release(ps_cb_bezier);
     ID3D10Buffer_Release(vs_cb);
 }
 
@@ -897,9 +937,9 @@ static void STDMETHODCALLTYPE d2d_device_context_DrawGeometry(ID2D1DeviceContext
 static void d2d_device_context_fill_geometry(struct d2d_device_context *render_target,
         const struct d2d_geometry *geometry, struct d2d_brush *brush, struct d2d_brush *opacity_brush)
 {
-    ID3D10Buffer *ib, *vb, *vs_cb, *ps_cb_bezier, *ps_cb_arc;
     D3D10_SUBRESOURCE_DATA buffer_data;
     D3D10_BUFFER_DESC buffer_desc;
+    ID3D10Buffer *ib, *vb, *vs_cb;
     D2D1_MATRIX_3X2_F *w;
     float tmp_x, tmp_y;
     HRESULT hr;
@@ -953,18 +993,10 @@ static void d2d_device_context_fill_geometry(struct d2d_device_context *render_t
         return;
     }
 
-    if (FAILED(hr = d2d_brush_get_ps_cb(brush, opacity_brush, FALSE, FALSE, render_target, &ps_cb_bezier)))
-    {
-        WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
-        ID3D10Buffer_Release(vs_cb);
-        return;
-    }
-
-    if (FAILED(hr = d2d_brush_get_ps_cb(brush, opacity_brush, FALSE, TRUE, render_target, &ps_cb_arc)))
+    if (FAILED(hr = d2d_device_context_update_ps_cb(render_target, brush, opacity_brush, FALSE, FALSE)))
     {
-        WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
+        WARN("Failed to update ps constant buffer, hr %#x.\n", hr);
         ID3D10Buffer_Release(vs_cb);
-        ID3D10Buffer_Release(ps_cb_bezier);
         return;
     }
 
@@ -992,7 +1024,7 @@ static void d2d_device_context_fill_geometry(struct d2d_device_context *render_t
         }
 
         d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, ib, 3 * geometry->fill.face_count, vb,
-                sizeof(*geometry->fill.vertices), vs_cb, ps_cb_bezier, brush, opacity_brush);
+                sizeof(*geometry->fill.vertices), vs_cb, brush, opacity_brush);
 
         ID3D10Buffer_Release(vb);
         ID3D10Buffer_Release(ib);
@@ -1011,7 +1043,7 @@ static void d2d_device_context_fill_geometry(struct d2d_device_context *render_t
         }
 
         d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_CURVE, NULL, geometry->fill.bezier_vertex_count, vb,
-                sizeof(*geometry->fill.bezier_vertices), vs_cb, ps_cb_bezier, brush, opacity_brush);
+                sizeof(*geometry->fill.bezier_vertices), vs_cb, brush, opacity_brush);
 
         ID3D10Buffer_Release(vb);
     }
@@ -1028,15 +1060,14 @@ static void d2d_device_context_fill_geometry(struct d2d_device_context *render_t
             goto done;
         }
 
-        d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_CURVE, NULL, geometry->fill.arc_vertex_count, vb,
-                sizeof(*geometry->fill.arc_vertices), vs_cb, ps_cb_arc, brush, opacity_brush);
+        if (SUCCEEDED(d2d_device_context_update_ps_cb(render_target, brush, opacity_brush, FALSE, TRUE)))
+            d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_CURVE, NULL, geometry->fill.arc_vertex_count, vb,
+                    sizeof(*geometry->fill.arc_vertices), vs_cb, brush, opacity_brush);
 
         ID3D10Buffer_Release(vb);
     }
 
 done:
-    ID3D10Buffer_Release(ps_cb_arc);
-    ID3D10Buffer_Release(ps_cb_bezier);
     ID3D10Buffer_Release(vs_cb);
 }
 
@@ -1634,9 +1665,9 @@ static void STDMETHODCALLTYPE d2d_device_context_Clear(ID2D1DeviceContext *iface
 {
     struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
     D3D10_SUBRESOURCE_DATA buffer_data;
-    struct d2d_ps_cb ps_cb_data = {0};
     D3D10_BUFFER_DESC buffer_desc;
-    ID3D10Buffer *vs_cb, *ps_cb;
+    struct d2d_brush brush;
+    ID3D10Buffer *vs_cb;
     D2D1_COLOR_F *c;
     HRESULT hr;
 
@@ -1676,34 +1707,19 @@ static void STDMETHODCALLTYPE d2d_device_context_Clear(ID2D1DeviceContext *iface
         return;
     }
 
-    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;
+    memset(&brush, 0, sizeof(brush));
+    brush.type = D2D_BRUSH_TYPE_SOLID;
+    brush.opacity = 1.0f;
+    c = &brush.u.solid.color;
     if (colour)
         *c = *colour;
     if (render_target->desc.pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
         c->a = 1.0f;
-    c->r *= c->a;
-    c->g *= c->a;
-    c->b *= c->a;
-
-    ps_cb_data.opacity_brush.type = D2D_BRUSH_TYPE_COUNT;
-
-    buffer_desc.ByteWidth = sizeof(ps_cb_data);
-    buffer_data.pSysMem = &ps_cb_data;
-
-    if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ps_cb)))
-    {
-        WARN("Failed to create constant buffer, hr %#x.\n", hr);
-        ID3D10Buffer_Release(vs_cb);
-        return;
-    }
 
+    d2d_device_context_update_ps_cb(render_target, &brush, NULL, FALSE, FALSE);
     d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, render_target->ib, 6,
-            render_target->vb, render_target->vb_stride, vs_cb, ps_cb, NULL, NULL);
+            render_target->vb, render_target->vb_stride, vs_cb, NULL, NULL);
 
-    ID3D10Buffer_Release(ps_cb);
     ID3D10Buffer_Release(vs_cb);
 }
 
-- 
2.30.2




More information about the wine-devel mailing list