[PATCH 2/2] d2d1: Reuse PS constant buffers.

Nikolay Sivov nsivov at codeweavers.com
Mon Jun 7 05:36:22 CDT 2021


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/d2d1/brush.c        | 59 +++++++++++++++++++++++++++++-----------
 dlls/d2d1/d2d1_private.h | 13 ++++++++-
 dlls/d2d1/device.c       | 13 ++++++---
 3 files changed, 64 insertions(+), 21 deletions(-)

diff --git a/dlls/d2d1/brush.c b/dlls/d2d1/brush.c
index 496a399aa6e..034ec5121e8 100644
--- a/dlls/d2d1/brush.c
+++ b/dlls/d2d1/brush.c
@@ -1267,32 +1267,59 @@ 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,
-        BOOL outline, BOOL is_arc, struct d2d_device_context *render_target, ID3D10Buffer **ps_cb)
+        enum d2d_device_context_ps_cb cb_type, struct d2d_device_context *context, ID3D10Buffer **ps_cb)
 {
     D3D10_SUBRESOURCE_DATA buffer_data;
     struct d2d_ps_cb cb_data = {0};
     D3D10_BUFFER_DESC buffer_desc;
-    HRESULT hr;
+    HRESULT hr = S_OK;
+    void *data;
 
-    cb_data.outline = outline;
-    cb_data.is_arc = is_arc;
-    if (!d2d_brush_fill_cb(brush, render_target, &cb_data.colour_brush))
+    cb_data.outline = cb_type == D2D_PS_CB_DRAW_BEZIER || cb_type == D2D_PS_CB_DRAW_ARC;
+    cb_data.is_arc = cb_type == D2D_PS_CB_DRAW_ARC || cb_type == D2D_PS_CB_FILL_ARC;
+    if (!d2d_brush_fill_cb(brush, context, &cb_data.colour_brush))
         return E_NOTIMPL;
-    if (!d2d_brush_fill_cb(opacity_brush, render_target, &cb_data.opacity_brush))
+    if (!d2d_brush_fill_cb(opacity_brush, context, &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;
+    if (context->ps_cb[cb_type])
+    {
+        if (memcmp(&cb_data, &context->cb_data[cb_type], sizeof(cb_data)))
+        {
+            if (SUCCEEDED(hr = ID3D10Buffer_Map(context->ps_cb[cb_type],
+                    D3D10_MAP_WRITE_DISCARD, 0, &data)))
+            {
+                memcpy(data, &cb_data, sizeof(cb_data));
+                ID3D10Buffer_Unmap(context->ps_cb[cb_type]);
+            }
+            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[cb_type])))
+        {
+            ERR("Failed to create constant buffer, hr %#x.\n", hr);
+        }
+    }
 
-    buffer_data.pSysMem = &cb_data;
-    buffer_data.SysMemPitch = 0;
-    buffer_data.SysMemSlicePitch = 0;
+    if ((*ps_cb = context->ps_cb[cb_type]))
+        ID3D10Buffer_AddRef(*ps_cb);
 
-    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);
+    if (SUCCEEDED(hr))
+        memcpy(&context->cb_data[cb_type], &cb_data, sizeof(cb_data));
 
     return hr;
 }
diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h
index 199439b4616..2a1399b7729 100644
--- a/dlls/d2d1/d2d1_private.h
+++ b/dlls/d2d1/d2d1_private.h
@@ -126,6 +126,15 @@ struct d2d_device_context_ops
     HRESULT (*device_context_present)(IUnknown *outer_unknown);
 };
 
+enum d2d_device_context_ps_cb
+{
+    D2D_PS_CB_DRAW_BEZIER,
+    D2D_PS_CB_DRAW_ARC,
+    D2D_PS_CB_FILL_BEZIER,
+    D2D_PS_CB_FILL_ARC,
+    D2D_PS_CB_COUNT,
+};
+
 struct d2d_device_context
 {
     ID2D1DeviceContext ID2D1DeviceContext_iface;
@@ -149,6 +158,8 @@ struct d2d_device_context
     ID3D10Buffer *vb;
     ID3D10RasterizerState *rs;
     ID3D10BlendState *bs;
+    ID3D10Buffer *ps_cb[D2D_PS_CB_COUNT];
+    struct d2d_ps_cb cb_data[D2D_PS_CB_COUNT];
 
     struct d2d_error_state error;
     D2D1_DRAWING_STATE_DESCRIPTION1 drawing_state;
@@ -304,7 +315,7 @@ HRESULT d2d_bitmap_brush_create(ID2D1Factory *factory, ID2D1Bitmap *bitmap,
         const D2D1_BITMAP_BRUSH_PROPERTIES1 *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, BOOL outline, BOOL is_arc,
+HRESULT d2d_brush_get_ps_cb(struct d2d_brush *brush, struct d2d_brush *opacity_brush, enum d2d_device_context_ps_cb cb_type,
         struct d2d_device_context *render_target, ID3D10Buffer **ps_cb) DECLSPEC_HIDDEN;
 struct d2d_brush *unsafe_impl_from_ID2D1Brush(ID2D1Brush *iface) DECLSPEC_HIDDEN;
 
diff --git a/dlls/d2d1/device.c b/dlls/d2d1/device.c
index 23ce03dce5e..d3f344ad834 100644
--- a/dlls/d2d1/device.c
+++ b/dlls/d2d1/device.c
@@ -271,6 +271,11 @@ static ULONG STDMETHODCALLTYPE d2d_device_context_inner_Release(IUnknown *iface)
             ID3D10VertexShader_Release(context->shape_resources[i].vs);
             ID3D10InputLayout_Release(context->shape_resources[i].il);
         }
+        for (i = 0; i < D2D_PS_CB_COUNT; ++i)
+        {
+            if (context->ps_cb[i])
+                ID3D10Buffer_Release(context->ps_cb[i]);
+        }
         context->stateblock->lpVtbl->Release(context->stateblock);
         if (context->target)
             ID2D1Bitmap1_Release(&context->target->ID2D1Bitmap1_iface);
@@ -754,14 +759,14 @@ 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)))
+    if (FAILED(hr = d2d_brush_get_ps_cb(brush, NULL, D2D_PS_CB_DRAW_BEZIER, 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_brush_get_ps_cb(brush, NULL, D2D_PS_CB_DRAW_ARC, render_target, &ps_cb_arc)))
     {
         WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
         ID3D10Buffer_Release(vs_cb);
@@ -942,14 +947,14 @@ 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)))
+    if (FAILED(hr = d2d_brush_get_ps_cb(brush, opacity_brush, D2D_PS_CB_FILL_BEZIER, 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_brush_get_ps_cb(brush, opacity_brush, D2D_PS_CB_FILL_ARC, render_target, &ps_cb_arc)))
     {
         WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
         ID3D10Buffer_Release(vs_cb);
-- 
2.30.2




More information about the wine-devel mailing list