Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/d2d1/brush.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-)
diff --git a/dlls/d2d1/brush.c b/dlls/d2d1/brush.c index 07d2e26a143..496a399aa6e 100644 --- a/dlls/d2d1/brush.c +++ b/dlls/d2d1/brush.c @@ -818,6 +818,15 @@ static inline struct d2d_brush *impl_from_ID2D1BitmapBrush1(ID2D1BitmapBrush1 *i return CONTAINING_RECORD(iface, struct d2d_brush, ID2D1Brush_iface); }
+static void d2d_bitmap_brush_reset_sampler_state(struct d2d_brush *brush) +{ + if (brush->u.bitmap.sampler_state) + { + ID3D10SamplerState_Release(brush->u.bitmap.sampler_state); + brush->u.bitmap.sampler_state = NULL; + } +} + static HRESULT STDMETHODCALLTYPE d2d_bitmap_brush_QueryInterface(ID2D1BitmapBrush1 *iface, REFIID iid, void **out) { @@ -923,11 +932,10 @@ static void STDMETHODCALLTYPE d2d_bitmap_brush_SetExtendModeX(ID2D1BitmapBrush1
TRACE("iface %p, mode %#x.\n", iface, mode);
- brush->u.bitmap.extend_mode_x = mode; - if (brush->u.bitmap.sampler_state) + if (brush->u.bitmap.extend_mode_x != mode) { - ID3D10SamplerState_Release(brush->u.bitmap.sampler_state); - brush->u.bitmap.sampler_state = NULL; + brush->u.bitmap.extend_mode_x = mode; + d2d_bitmap_brush_reset_sampler_state(brush); } }
@@ -937,11 +945,10 @@ static void STDMETHODCALLTYPE d2d_bitmap_brush_SetExtendModeY(ID2D1BitmapBrush1
TRACE("iface %p, mode %#x.\n", iface, mode);
- brush->u.bitmap.extend_mode_y = mode; - if (brush->u.bitmap.sampler_state) + if (brush->u.bitmap.extend_mode_y != mode) { - ID3D10SamplerState_Release(brush->u.bitmap.sampler_state); - brush->u.bitmap.sampler_state = NULL; + brush->u.bitmap.extend_mode_y = mode; + d2d_bitmap_brush_reset_sampler_state(brush); } }
@@ -962,11 +969,10 @@ static void STDMETHODCALLTYPE d2d_bitmap_brush_SetInterpolationMode(ID2D1BitmapB return; }
- brush->u.bitmap.interpolation_mode = d2d1_1_interp_mode_from_d2d1(mode); - if (brush->u.bitmap.sampler_state) + if (brush->u.bitmap.interpolation_mode != d2d1_1_interp_mode_from_d2d1(mode)) { - ID3D10SamplerState_Release(brush->u.bitmap.sampler_state); - brush->u.bitmap.sampler_state = NULL; + brush->u.bitmap.interpolation_mode = d2d1_1_interp_mode_from_d2d1(mode); + d2d_bitmap_brush_reset_sampler_state(brush); } }
@@ -1050,11 +1056,10 @@ static void STDMETHODCALLTYPE d2d_bitmap_brush_SetInterpolationMode1(ID2D1Bitmap return; }
- brush->u.bitmap.interpolation_mode = mode; - if (brush->u.bitmap.sampler_state) + if (brush->u.bitmap.interpolation_mode != mode) { - ID3D10SamplerState_Release(brush->u.bitmap.sampler_state); - brush->u.bitmap.sampler_state = NULL; + brush->u.bitmap.interpolation_mode = mode; + d2d_bitmap_brush_reset_sampler_state(brush); } }
Signed-off-by: Nikolay Sivov nsivov@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);
On Mon, 7 Jun 2021 at 12:36, Nikolay Sivov nsivov@codeweavers.com wrote:
- 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);
}
- }
Does that memcmp() help much? It seems tempting to just store a single "ps_cb" in the d2d_device_context structure, and always map with WRITE_DISCARD here.
On Mon, 7 Jun 2021 at 12:36, Nikolay Sivov nsivov@codeweavers.com wrote:
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com
dlls/d2d1/brush.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-)
Note that the number of possible unique sampler states is fairly limited in d2d1. It may make more sense to just cache these in the d2d_device_context structure, instead of storing them in the d2d_brush structure.