On Wed, 11 May 2022 at 16:22, Dmitry Timoshkov <dmitry(a)baikal.ru> wrote:
+HRESULT d2d_image_brush_create(ID2D1Factory *factory, ID2D1Image *image, + const D2D1_IMAGE_BRUSH_PROPERTIES *image_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc, + struct d2d_brush **brush) +{ + if (!(*brush = heap_alloc_zero(sizeof(**brush)))) + return E_OUTOFMEMORY; + + d2d_brush_init(*brush, factory, D2D_BRUSH_TYPE_BITMAP, + brush_desc, (ID2D1BrushVtbl *)&d2d_image_brush_vtbl);
I think you intended to use D2D_BRUSH_TYPE_IMAGE above.
+ if (((*brush)->u.image.image = image)) + ID2D1Image_AddRef((*brush)->u.image.image); + if (image_brush_desc) + { + (*brush)->u.image.extend_mode_x = image_brush_desc->extendModeX; + (*brush)->u.image.extend_mode_y = image_brush_desc->extendModeY; + (*brush)->u.image.interpolation_mode = image_brush_desc->interpolationMode; + }
This ignores "image_brush_desc->sourceRectangle". That's fine to some extent, but might be easy to overlook when implementing d2d_image_brush_SetSourceRectangle()/d2d_image_brush_GetSourceRectangle() later.
+static void d2d_brush_bind_image(struct d2d_brush *brush, struct d2d_device_context *context, + unsigned int brush_idx) +{ + ID3D11SamplerState **sampler_state; + ID3D11DeviceContext *d3d_context; + ID2D1Bitmap *bitmap; + struct d2d_bitmap *src_impl; + HRESULT hr; + + hr = ID2D1Image_QueryInterface(brush->u.image.image, &IID_ID2D1Bitmap, (void **)&bitmap); + if (FAILED(hr)) + { + FIXME("ID2D1Image doesn't support ID2D1Bitmap interface.\n"); + return; + } + + src_impl = unsafe_impl_from_ID2D1Bitmap(bitmap); + + ID3D11Device1_GetImmediateContext(context->d3d_device, &d3d_context); + ID3D11DeviceContext_PSSetShaderResources(d3d_context, brush_idx, 1, &src_impl->srv); + + sampler_state = &context->sampler_states + [brush->u.image.interpolation_mode % D2D_SAMPLER_INTERPOLATION_MODE_COUNT] + [brush->u.image.extend_mode_x % D2D_SAMPLER_EXTEND_MODE_COUNT] + [brush->u.image.extend_mode_y % D2D_SAMPLER_EXTEND_MODE_COUNT]; + + if (!*sampler_state) + { + D3D11_SAMPLER_DESC sampler_desc; + + if (brush->u.image.interpolation_mode == D2D1_INTERPOLATION_MODE_NEAREST_NEIGHBOR) + sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; + else + sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + sampler_desc.AddressU = texture_address_mode_from_extend_mode(brush->u.image.extend_mode_x); + sampler_desc.AddressV = texture_address_mode_from_extend_mode(brush->u.image.extend_mode_y); + sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + sampler_desc.MipLODBias = 0.0f; + sampler_desc.MaxAnisotropy = 0; + sampler_desc.ComparisonFunc = D3D11_COMPARISON_NEVER; + sampler_desc.BorderColor[0] = 0.0f; + sampler_desc.BorderColor[1] = 0.0f; + sampler_desc.BorderColor[2] = 0.0f; + sampler_desc.BorderColor[3] = 0.0f; + sampler_desc.MinLOD = 0.0f; + sampler_desc.MaxLOD = 0.0f; + + if (FAILED(hr = ID3D11Device1_CreateSamplerState(context->d3d_device, &sampler_desc, sampler_state))) + ERR("Failed to create sampler state, hr %#lx.\n", hr); + } + + ID3D11DeviceContext_PSSetSamplers(d3d_context, brush_idx, 1, sampler_state); + ID3D11DeviceContext_Release(d3d_context); + ID2D1Bitmap_Release(bitmap); +}
This doesn't seem wrong, although we could probably introduce a common helper for this and d2d_brush_bind_bitmap(). At the same time though, it's not going to do much as long as the pixel shader (i.e., ps_code[] in d2d_device_context_init()) doesn't handle image brushes. (And in it's current form, we never get here because we set the brush type to D2D_BRUSH_TYPE_BITMAP in d2d_image_brush_create().) It might be best to just go with the FIXME in d2d_brush_bind_resources(), unless we need the brush to actually work.