Wine-devel
Threads by month
- ----- 2026 -----
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
October 2018
- 60 participants
- 608 discussions
[PATCH vkd3d 01/10] vkd3d: Set the numer of samples for graphics pipelines.
by Józef Kucia 25 Oct '18
by Józef Kucia 25 Oct '18
25 Oct '18
From: Józef Kucia <jkucia(a)codeweavers.com>
Signed-off-by: Józef Kucia <jkucia(a)codeweavers.com>
---
libs/vkd3d/resource.c | 2 +-
libs/vkd3d/state.c | 14 ++++++++------
libs/vkd3d/vkd3d_private.h | 1 +
3 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c
index 68c189ad5bd4..55abd50c2c67 100644
--- a/libs/vkd3d/resource.c
+++ b/libs/vkd3d/resource.c
@@ -334,7 +334,7 @@ static VkImageType vk_image_type_from_d3d12_resource_dimension(D3D12_RESOURCE_DI
}
}
-static VkSampleCountFlagBits vk_samples_from_dxgi_sample_desc(const DXGI_SAMPLE_DESC *desc)
+VkSampleCountFlagBits vk_samples_from_dxgi_sample_desc(const DXGI_SAMPLE_DESC *desc)
{
switch (desc->Count)
{
diff --git a/libs/vkd3d/state.c b/libs/vkd3d/state.c
index f6ccb247553c..0deea28edb6b 100644
--- a/libs/vkd3d/state.c
+++ b/libs/vkd3d/state.c
@@ -1874,6 +1874,7 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
struct vkd3d_shader_signature input_signature;
struct VkSubpassDescription sub_pass_desc;
struct VkRenderPassCreateInfo pass_desc;
+ VkSampleCountFlagBits sample_count;
const struct vkd3d_format *format;
enum VkVertexInputRate input_rate;
unsigned int i, j;
@@ -1914,6 +1915,10 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
return E_INVALIDARG;
}
+ sample_count = vk_samples_from_dxgi_sample_desc(&desc->SampleDesc);
+ if (desc->SampleDesc.Count != 1 && desc->SampleDesc.Quality)
+ WARN("Ignoring sample quality %u.\n", desc->SampleDesc.Quality);
+
rt_count = desc->NumRenderTargets;
if (rt_count > ARRAY_SIZE(graphics->attachments) - 1)
{
@@ -1943,7 +1948,7 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
graphics->attachments[0].flags = 0;
graphics->attachments[0].format = format->vk_format;
- graphics->attachments[0].samples = VK_SAMPLE_COUNT_1_BIT;
+ graphics->attachments[0].samples = sample_count;
if (desc->DepthStencilState.DepthEnable)
{
graphics->attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
@@ -2002,7 +2007,7 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
graphics->attachments[idx].flags = 0;
graphics->attachments[idx].format = format->vk_format;
- graphics->attachments[idx].samples = VK_SAMPLE_COUNT_1_BIT;
+ graphics->attachments[idx].samples = sample_count;
graphics->attachments[idx].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
graphics->attachments[idx].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
graphics->attachments[idx].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
@@ -2202,7 +2207,7 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
graphics->ms_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
graphics->ms_desc.pNext = NULL;
graphics->ms_desc.flags = 0;
- graphics->ms_desc.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
+ graphics->ms_desc.rasterizationSamples = sample_count;
graphics->ms_desc.sampleShadingEnable = VK_FALSE;
graphics->ms_desc.minSampleShading = 0.0f;
graphics->ms_desc.pSampleMask = NULL;
@@ -2211,9 +2216,6 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
ds_desc_from_d3d12(&graphics->ds_desc, &desc->DepthStencilState);
- if (desc->SampleDesc.Count != 1)
- FIXME("Ignoring sample desc %u, %u.\n", desc->SampleDesc.Count, desc->SampleDesc.Quality);
-
graphics->root_signature = root_signature;
list_init(&graphics->compiled_pipelines);
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h
index f60dc5f96676..5f5798852290 100644
--- a/libs/vkd3d/vkd3d_private.h
+++ b/libs/vkd3d/vkd3d_private.h
@@ -848,6 +848,7 @@ static inline unsigned int d3d12_resource_desc_get_layer_count(const D3D12_RESOU
}
enum VkCompareOp vk_compare_op_from_d3d12(D3D12_COMPARISON_FUNC op) DECLSPEC_HIDDEN;
+VkSampleCountFlagBits vk_samples_from_dxgi_sample_desc(const DXGI_SAMPLE_DESC *desc) DECLSPEC_HIDDEN;
bool is_valid_feature_level(D3D_FEATURE_LEVEL feature_level) DECLSPEC_HIDDEN;
bool check_feature_level_support(D3D_FEATURE_LEVEL feature_level) DECLSPEC_HIDDEN;
--
2.18.1
2
1
From: Aaryaman Vasishta <jem456.vasishta(a)gmail.com>
Signed-off-by: Aaryaman Vasishta <jem456.vasishta(a)gmail.com>
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
This supersedes patch 153076.
---
dlls/d3drm/d3drm.c | 40 ++++++++++++++++++++++++-----
dlls/d3drm/tests/d3drm.c | 66 ++++++++++++++++++++----------------------------
2 files changed, 61 insertions(+), 45 deletions(-)
diff --git a/dlls/d3drm/d3drm.c b/dlls/d3drm/d3drm.c
index 3ea16327bfc..d0f20235a8f 100644
--- a/dlls/d3drm/d3drm.c
+++ b/dlls/d3drm/d3drm.c
@@ -638,12 +638,24 @@ static HRESULT WINAPI d3drm1_LoadTexture(IDirect3DRM *iface,
struct d3drm_texture *object;
HRESULT hr;
- FIXME("iface %p, filename %s, texture %p stub!\n", iface, debugstr_a(filename), texture);
+ TRACE("iface %p, filename %s, texture %p.\n", iface, debugstr_a(filename), texture);
+
+ if (!texture)
+ return D3DRMERR_BADVALUE;
if (FAILED(hr = d3drm_texture_create(&object, iface)))
return hr;
*texture = &object->IDirect3DRMTexture_iface;
+ if (FAILED(hr = IDirect3DRMTexture_InitFromFile(*texture, filename)))
+ {
+ IDirect3DRMTexture_Release(*texture);
+ *texture = NULL;
+ if (!filename)
+ return D3DRMERR_BADVALUE;
+
+ return hr == D3DRMERR_BADOBJECT ? D3DRMERR_FILENOTFOUND : hr;
+ }
return D3DRM_OK;
}
@@ -1143,15 +1155,22 @@ static HRESULT WINAPI d3drm2_LoadTexture(IDirect3DRM2 *iface,
const char *filename, IDirect3DRMTexture2 **texture)
{
struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
- struct d3drm_texture *object;
+ IDirect3DRMTexture3 *texture3;
HRESULT hr;
- FIXME("iface %p, filename %s, texture %p stub!\n", iface, debugstr_a(filename), texture);
+ TRACE("iface %p, filename %s, texture %p.\n", iface, debugstr_a(filename), texture);
- if (FAILED(hr = d3drm_texture_create(&object, &d3drm->IDirect3DRM_iface)))
+ if (!texture)
+ return D3DRMERR_BADVALUE;
+
+ if (FAILED(hr = IDirect3DRM3_LoadTexture(&d3drm->IDirect3DRM3_iface, filename, &texture3)))
+ {
+ *texture = NULL;
return hr;
+ }
- *texture = &object->IDirect3DRMTexture2_iface;
+ hr = IDirect3DRMTexture3_QueryInterface(texture3, &IID_IDirect3DRMTexture2, (void **)texture);
+ IDirect3DRMTexture3_Release(texture3);
return hr;
}
@@ -1818,12 +1837,21 @@ static HRESULT WINAPI d3drm3_LoadTexture(IDirect3DRM3 *iface,
struct d3drm_texture *object;
HRESULT hr;
- FIXME("iface %p, filename %s, texture %p stub!\n", iface, debugstr_a(filename), texture);
+ TRACE("iface %p, filename %s, texture %p.\n", iface, debugstr_a(filename), texture);
+
+ if (!texture)
+ return D3DRMERR_BADVALUE;
if (FAILED(hr = d3drm_texture_create(&object, &d3drm->IDirect3DRM_iface)))
return hr;
*texture = &object->IDirect3DRMTexture3_iface;
+ if (FAILED(hr = IDirect3DRMTexture3_InitFromFile(*texture, filename)))
+ {
+ IDirect3DRMTexture3_Release(*texture);
+ *texture = NULL;
+ return hr == D3DRMERR_BADOBJECT ? D3DRMERR_FILENOTFOUND : hr;
+ }
return D3DRM_OK;
}
diff --git a/dlls/d3drm/tests/d3drm.c b/dlls/d3drm/tests/d3drm.c
index 91ee68ca435..5157952d63d 100644
--- a/dlls/d3drm/tests/d3drm.c
+++ b/dlls/d3drm/tests/d3drm.c
@@ -5601,45 +5601,36 @@ static void test_load_texture(void)
/* Test all failures together. */
texture1 = (IDirect3DRMTexture *)0xdeadbeef;
hr = IDirect3DRM_LoadTexture(d3drm1, NULL, &texture1);
- todo_wine ok(hr == D3DRMERR_BADVALUE, "Got unexpected hr %#x.\n", hr);
- todo_wine ok(!texture1, "Got unexpected texture %p.\n", texture1);
+ ok(hr == D3DRMERR_BADVALUE, "Got unexpected hr %#x.\n", hr);
+ ok(!texture1, "Got unexpected texture %p.\n", texture1);
texture1 = (IDirect3DRMTexture *)0xdeadbeef;
hr = IDirect3DRM_LoadTexture(d3drm1, "", &texture1);
- todo_wine ok(hr == D3DRMERR_FILENOTFOUND, "Got unexpected hr %#x.\n", hr);
- todo_wine ok(!texture1, "Got unexpected texture %p.\n", texture1);
- if (hr == D3DRMERR_FILENOTFOUND)
- {
- hr = IDirect3DRM_LoadTexture(d3drm1, NULL, NULL);
- ok(hr == D3DRMERR_BADVALUE, "Got unexpected hr %#x.\n", hr);
- }
+ ok(hr == D3DRMERR_FILENOTFOUND, "Got unexpected hr %#x.\n", hr);
+ ok(!texture1, "Got unexpected texture %p.\n", texture1);
+ hr = IDirect3DRM_LoadTexture(d3drm1, NULL, NULL);
+ ok(hr == D3DRMERR_BADVALUE, "Got unexpected hr %#x.\n", hr);
texture2 = (IDirect3DRMTexture2 *)0xdeadbeef;
hr = IDirect3DRM2_LoadTexture(d3drm2, NULL, &texture2);
- todo_wine ok(hr == D3DRMERR_FILENOTFOUND, "Got unexpected hr %#x.\n", hr);
- todo_wine ok(!texture2, "Got unexpected texture %p.\n", texture2);
+ ok(hr == D3DRMERR_FILENOTFOUND, "Got unexpected hr %#x.\n", hr);
+ ok(!texture2, "Got unexpected texture %p.\n", texture2);
texture2 = (IDirect3DRMTexture2 *)0xdeadbeef;
hr = IDirect3DRM2_LoadTexture(d3drm2, "", &texture2);
- todo_wine ok(hr == D3DRMERR_FILENOTFOUND, "Got unexpected hr %#x.\n", hr);
- todo_wine ok(!texture2, "Got unexpected texture %p.\n", texture2);
- if (hr == D3DRMERR_FILENOTFOUND)
- {
- hr = IDirect3DRM2_LoadTexture(d3drm2, NULL, NULL);
- ok(hr == D3DRMERR_BADVALUE, "Got unexpected hr %#x.\n", hr);
- }
+ ok(hr == D3DRMERR_FILENOTFOUND, "Got unexpected hr %#x.\n", hr);
+ ok(!texture2, "Got unexpected texture %p.\n", texture2);
+ hr = IDirect3DRM2_LoadTexture(d3drm2, NULL, NULL);
+ ok(hr == D3DRMERR_BADVALUE, "Got unexpected hr %#x.\n", hr);
texture3 = (IDirect3DRMTexture3 *)0xdeadbeef;
hr = IDirect3DRM3_LoadTexture(d3drm3, NULL, &texture3);
- todo_wine ok(hr == D3DRMERR_FILENOTFOUND, "Got unexpected hr %#x.\n", hr);
- todo_wine ok(!texture3, "Got unexpected texture %p.\n", texture3);
+ ok(hr == D3DRMERR_FILENOTFOUND, "Got unexpected hr %#x.\n", hr);
+ ok(!texture3, "Got unexpected texture %p.\n", texture3);
texture3 = (IDirect3DRMTexture3 *)0xdeadbeef;
hr = IDirect3DRM_LoadTexture(d3drm3, "", &texture3);
- todo_wine ok(hr == D3DRMERR_FILENOTFOUND, "Got unexpected hr %#x.\n", hr);
- todo_wine ok(!texture3, "Got unexpected texture %p.\n", texture3);
- if (hr == D3DRMERR_FILENOTFOUND)
- {
- hr = IDirect3DRM3_LoadTexture(d3drm3, NULL, NULL);
- ok(hr == D3DRMERR_BADVALUE, "Got unexpected hr %#x.\n", hr);
- }
+ ok(hr == D3DRMERR_FILENOTFOUND, "Got unexpected hr %#x.\n", hr);
+ ok(!texture3, "Got unexpected texture %p.\n", texture3);
+ hr = IDirect3DRM3_LoadTexture(d3drm3, NULL, NULL);
+ ok(hr == D3DRMERR_BADVALUE, "Got unexpected hr %#x.\n", hr);
for (i = 0; i < ARRAY_SIZE(tests); ++i)
{
@@ -5648,13 +5639,12 @@ static void test_load_texture(void)
hr = IDirect3DRM_LoadTexture(d3drm1, filename, &texture1);
ok(SUCCEEDED(hr), "Test %u: Failed to load texture, hr %#x.\n", i, hr);
ref2 = get_refcount((IUnknown *)d3drm1);
- todo_wine ok(ref2 > ref1, "Test %u: expected ref2 > ref1, got ref1 = %u, ref2 = %u.\n", i, ref1, ref2);
+ ok(ref2 > ref1, "Test %u: expected ref2 > ref1, got ref1 %u, ref2 %u.\n", i, ref1, ref2);
hr = IDirect3DRMTexture_InitFromFile(texture1, filename);
- todo_wine ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
+ ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
/* InitFromFile() seems to AddRef() IDirect3DRM even if it fails. */
- if (hr == D3DRMERR_BADOBJECT)
- IDirect3DRM_Release(d3drm1);
+ IDirect3DRM_Release(d3drm1);
d3drm_img = IDirect3DRMTexture_GetImage(texture1);
ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
test_bitmap_data(i * 7, d3drm_img, FALSE, tests[i].w, tests[i].h, tests[i].palettized);
@@ -5678,12 +5668,11 @@ static void test_load_texture(void)
hr = IDirect3DRM2_LoadTexture(d3drm2, filename, &texture2);
ok(SUCCEEDED(hr), "Test %u: Failed to load texture, hr %#x.\n", i, hr);
ref2 = get_refcount((IUnknown *)d3drm1);
- todo_wine ok(ref2 > ref1, "Test %u: expected ref2 > ref1, got ref1 = %u, ref2 = %u.\n", i, ref1, ref2);
+ ok(ref2 > ref1, "Test %u: expected ref2 > ref1, got ref1 %u, ref2 %u.\n", i, ref1, ref2);
hr = IDirect3DRMTexture2_InitFromFile(texture2, filename);
- todo_wine ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
- if (hr == D3DRMERR_BADOBJECT)
- IDirect3DRM_Release(d3drm1);
+ ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
+ IDirect3DRM_Release(d3drm1);
d3drm_img = IDirect3DRMTexture2_GetImage(texture2);
ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
test_bitmap_data(i * 7 + 2, d3drm_img, TRUE, tests[i].w, tests[i].h, tests[i].palettized);
@@ -5707,12 +5696,11 @@ static void test_load_texture(void)
hr = IDirect3DRM3_LoadTexture(d3drm3, filename, &texture3);
ok(SUCCEEDED(hr), "Test %u: Failed to load texture, hr %#x.\n", i, hr);
ref2 = get_refcount((IUnknown *)d3drm1);
- todo_wine ok(ref2 > ref1, "Test %u: expected ref2 > ref1, got ref1 = %u, ref2 = %u.\n", i, ref1, ref2);
+ ok(ref2 > ref1, "Test %u: expected ref2 > ref1, got ref1 %u, ref2 %u.\n", i, ref1, ref2);
hr = IDirect3DRMTexture3_InitFromFile(texture3, filename);
- todo_wine ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
- if (hr == D3DRMERR_BADOBJECT)
- IDirect3DRM_Release(d3drm1);
+ ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
+ IDirect3DRM_Release(d3drm1);
d3drm_img = IDirect3DRMTexture3_GetImage(texture3);
ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
test_bitmap_data(i * 7 + 4, d3drm_img, TRUE, tests[i].w, tests[i].h, tests[i].palettized);
--
2.11.0
1
0
[PATCH v2 1/2] d3drm: Partially implement d3drm_texture*_InitFromFile().
by Henri Verbeet 25 Oct '18
by Henri Verbeet 25 Oct '18
25 Oct '18
From: Aaryaman Vasishta <jem456.vasishta(a)gmail.com>
Signed-off-by: Aaryaman Vasishta <jem456.vasishta(a)gmail.com>
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
v2: Make it work with 64-bit pointers as well.
This supersedes patch 153075.
---
dlls/d3drm/tests/d3drm.c | 53 ++++----
dlls/d3drm/texture.c | 312 ++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 329 insertions(+), 36 deletions(-)
diff --git a/dlls/d3drm/tests/d3drm.c b/dlls/d3drm/tests/d3drm.c
index 9bc9a84444a..91ee68ca435 100644
--- a/dlls/d3drm/tests/d3drm.c
+++ b/dlls/d3drm/tests/d3drm.c
@@ -5656,9 +5656,8 @@ static void test_load_texture(void)
if (hr == D3DRMERR_BADOBJECT)
IDirect3DRM_Release(d3drm1);
d3drm_img = IDirect3DRMTexture_GetImage(texture1);
- todo_wine ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
- if (d3drm_img)
- test_bitmap_data(i * 7, d3drm_img, FALSE, tests[i].w, tests[i].h, tests[i].palettized);
+ ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
+ test_bitmap_data(i * 7, d3drm_img, FALSE, tests[i].w, tests[i].h, tests[i].palettized);
IDirect3DRMTexture_Release(texture1);
ref2 = get_refcount((IUnknown *)d3drm1);
ok(ref1 == ref2, "Test %u: expected ref1 == ref2, got ref1 = %u, ref2 = %u.\n", i, ref1, ref2);
@@ -5666,15 +5665,14 @@ static void test_load_texture(void)
NULL, &IID_IDirect3DRMTexture, (void **)&texture1);
ok(SUCCEEDED(hr), "Test %u: Failed to create texture, hr %#x.\n", i, hr);
hr = IDirect3DRMTexture_InitFromFile(texture1, NULL);
- todo_wine ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
+ ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
hr = IDirect3DRMTexture_InitFromFile(texture1, "");
- todo_wine ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
+ ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
hr = IDirect3DRMTexture_InitFromFile(texture1, filename);
- todo_wine ok(SUCCEEDED(hr), "Test %u: Failed to initialise texture from file, hr %#x.\n", i, hr);
+ ok(SUCCEEDED(hr), "Test %u: Failed to initialise texture from file, hr %#x.\n", i, hr);
d3drm_img = IDirect3DRMTexture_GetImage(texture1);
- todo_wine ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
- if (d3drm_img)
- test_bitmap_data(i * 7 + 1, d3drm_img, FALSE, tests[i].w, tests[i].h, tests[i].palettized);
+ ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
+ test_bitmap_data(i * 7 + 1, d3drm_img, FALSE, tests[i].w, tests[i].h, tests[i].palettized);
IDirect3DRMTexture_Release(texture1);
hr = IDirect3DRM2_LoadTexture(d3drm2, filename, &texture2);
@@ -5687,9 +5685,8 @@ static void test_load_texture(void)
if (hr == D3DRMERR_BADOBJECT)
IDirect3DRM_Release(d3drm1);
d3drm_img = IDirect3DRMTexture2_GetImage(texture2);
- todo_wine ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
- if (d3drm_img)
- test_bitmap_data(i * 7 + 2, d3drm_img, TRUE, tests[i].w, tests[i].h, tests[i].palettized);
+ ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
+ test_bitmap_data(i * 7 + 2, d3drm_img, TRUE, tests[i].w, tests[i].h, tests[i].palettized);
IDirect3DRMTexture2_Release(texture2);
ref2 = get_refcount((IUnknown *)d3drm1);
ok(ref1 == ref2, "Test %u: expected ref1 == ref2, got ref1 = %u, ref2 = %u.\n", i, ref1, ref2);
@@ -5697,15 +5694,14 @@ static void test_load_texture(void)
NULL, &IID_IDirect3DRMTexture2, (void **)&texture2);
ok(SUCCEEDED(hr), "Test %u: Failed to create texture, hr %#x.\n", i, hr);
hr = IDirect3DRMTexture2_InitFromFile(texture2, NULL);
- todo_wine ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
+ ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
hr = IDirect3DRMTexture2_InitFromFile(texture2, "");
- todo_wine ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
+ ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
hr = IDirect3DRMTexture2_InitFromFile(texture2, filename);
- todo_wine ok(SUCCEEDED(hr), "Test %u: Failed to initialise texture from file, hr %#x.\n", i, hr);
+ ok(SUCCEEDED(hr), "Test %u: Failed to initialise texture from file, hr %#x.\n", i, hr);
d3drm_img = IDirect3DRMTexture2_GetImage(texture2);
- todo_wine ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
- if (d3drm_img)
- test_bitmap_data(i * 7 + 3, d3drm_img, TRUE, tests[i].w, tests[i].h, tests[i].palettized);
+ ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
+ test_bitmap_data(i * 7 + 3, d3drm_img, TRUE, tests[i].w, tests[i].h, tests[i].palettized);
IDirect3DRMTexture2_Release(texture2);
hr = IDirect3DRM3_LoadTexture(d3drm3, filename, &texture3);
@@ -5718,17 +5714,15 @@ static void test_load_texture(void)
if (hr == D3DRMERR_BADOBJECT)
IDirect3DRM_Release(d3drm1);
d3drm_img = IDirect3DRMTexture3_GetImage(texture3);
- todo_wine ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
- if (d3drm_img)
- test_bitmap_data(i * 7 + 4, d3drm_img, TRUE, tests[i].w, tests[i].h, tests[i].palettized);
+ ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
+ test_bitmap_data(i * 7 + 4, d3drm_img, TRUE, tests[i].w, tests[i].h, tests[i].palettized);
/* Test whether querying a version 1 texture from version 3 causes a
* change in the loading behavior. */
hr = IDirect3DRMTexture3_QueryInterface(texture3, &IID_IDirect3DRMTexture, (void **)&texture1);
ok(SUCCEEDED(hr), "Failed to get IDirect3DRMTexture interface, hr %#x.\n", hr);
d3drm_img = IDirect3DRMTexture_GetImage(texture1);
- todo_wine ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
- if (d3drm_img)
- test_bitmap_data(i * 7 + 5, d3drm_img, TRUE, tests[i].w, tests[i].h, tests[i].palettized);
+ ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
+ test_bitmap_data(i * 7 + 5, d3drm_img, TRUE, tests[i].w, tests[i].h, tests[i].palettized);
IDirect3DRMTexture_Release(texture1);
IDirect3DRMTexture3_Release(texture3);
ref2 = get_refcount((IUnknown *)d3drm1);
@@ -5738,15 +5732,14 @@ static void test_load_texture(void)
NULL, &IID_IDirect3DRMTexture3, (void **)&texture3);
ok(SUCCEEDED(hr), "Test %u: Failed to create texture, hr %#x.\n", i, hr);
hr = IDirect3DRMTexture3_InitFromFile(texture3, NULL);
- todo_wine ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
+ ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
hr = IDirect3DRMTexture3_InitFromFile(texture3, "");
- todo_wine ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
+ ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
hr = IDirect3DRMTexture3_InitFromFile(texture3, filename);
- todo_wine ok(SUCCEEDED(hr), "Test %u: Failed to initialize texture from file, hr %#x.\n", i, hr);
+ ok(SUCCEEDED(hr), "Test %u: Failed to initialize texture from file, hr %#x.\n", i, hr);
d3drm_img = IDirect3DRMTexture3_GetImage(texture3);
- todo_wine ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
- if (d3drm_img)
- test_bitmap_data(i * 7 + 6, d3drm_img, TRUE, tests[i].w, tests[i].h, tests[i].palettized);
+ ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
+ test_bitmap_data(i * 7 + 6, d3drm_img, TRUE, tests[i].w, tests[i].h, tests[i].palettized);
IDirect3DRMTexture3_Release(texture3);
ret = DeleteFileA(filename);
diff --git a/dlls/d3drm/texture.c b/dlls/d3drm/texture.c
index fd56e76ff92..7741718ce90 100644
--- a/dlls/d3drm/texture.c
+++ b/dlls/d3drm/texture.c
@@ -2,6 +2,7 @@
* Implementation of IDirect3DRMTextureX interfaces
*
* Copyright 2012 Christian Costa
+ * Copyright 2016 Aaryaman Vasishta
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -67,6 +68,289 @@ static BOOL d3drm_validate_image(D3DRMIMAGE *image)
return TRUE;
}
+static BOOL d3drm_image_palettise(D3DRMIMAGE *image, unsigned char *src_data,
+ SIZE_T w, SIZE_T h, BOOL flip)
+{
+ unsigned char *dst_data, *src_ptr, *dst_ptr;
+ SIZE_T src_pitch, dst_pitch, i, x, y;
+ D3DRMPALETTEENTRY *palette, *entry;
+ unsigned int colour_count = 0;
+
+ if (w > (~(SIZE_T)0 - 3) / h)
+ return FALSE;
+
+ src_pitch = flip ? -w * 3 : w * 3;
+ dst_pitch = (w + 3) & ~3;
+
+ if (!(dst_data = heap_alloc(dst_pitch * h)))
+ {
+ WARN("Failed to allocate image buffer.\n");
+ return FALSE;
+ }
+ memset(dst_data, 0xff, dst_pitch * h);
+
+ if (!(palette = heap_alloc(256 * sizeof(*palette))))
+ {
+ WARN("Failed to allocate palette.\n");
+ heap_free(dst_data);
+ return FALSE;
+ }
+
+ src_ptr = flip ? &src_data[(h - 1) * w * 3] : src_data;
+ dst_ptr = dst_data;
+
+ for (y = 0; y < h; ++y)
+ {
+ for (x = 0; x < w; ++x)
+ {
+ for (i = 0; i < colour_count; ++i)
+ {
+ entry = &palette[i];
+ if (entry->red == src_ptr[x * 3 + 0]
+ && entry->green == src_ptr[x * 3 + 1]
+ && entry->blue == src_ptr[x * 3 + 2])
+ break;
+ }
+
+ if (i == colour_count)
+ {
+ if (colour_count == 256)
+ {
+ heap_free(dst_data);
+ heap_free(palette);
+ return FALSE;
+ }
+
+ entry = &palette[colour_count++];
+ entry->red = src_ptr[x * 3 + 0];
+ entry->green = src_ptr[x * 3 + 1];
+ entry->blue = src_ptr[x * 3 + 2];
+ entry->flags = D3DRMPALETTE_READONLY;
+ }
+
+ dst_ptr[x] = i;
+ }
+
+ src_ptr += src_pitch;
+ dst_ptr += dst_pitch;
+ }
+
+ image->depth = 8;
+ image->rgb = 0;
+ image->bytes_per_line = dst_pitch;
+ image->buffer1 = dst_data;
+ image->red_mask = 0xff;
+ image->green_mask = 0xff;
+ image->blue_mask = 0xff;
+ image->palette_size = colour_count;
+ if (!(image->palette = heap_realloc(palette, colour_count * sizeof(*palette))))
+ image->palette = palette;
+
+ return TRUE;
+}
+
+static HRESULT d3drm_image_load_32(D3DRMIMAGE *image, unsigned char *src_data,
+ LONGLONG src_data_size, SIZE_T w, SIZE_T h, BOOL flip)
+{
+ unsigned char *dst_data, *src_ptr, *dst_ptr;
+ SIZE_T src_pitch, dst_pitch, x, y;
+
+ if (d3drm_image_palettise(image, src_data, w, h, flip))
+ return D3DRM_OK;
+
+ if (w > (~(SIZE_T)0 / 4) / h)
+ return D3DRMERR_BADALLOC;
+
+ src_pitch = flip ? -w * 3 : w * 3;
+ dst_pitch = w * 4;
+
+ if (!(dst_data = heap_alloc(dst_pitch * h)))
+ {
+ WARN("Failed to allocate image buffer.\n");
+ return D3DRMERR_BADALLOC;
+ }
+
+ src_ptr = flip ? &src_data[(h - 1) * w * 3] : src_data;
+ dst_ptr = dst_data;
+
+ for (y = 0; y < h; ++y)
+ {
+ for (x = 0; x < w; ++x)
+ {
+ dst_ptr[x * 4 + 0] = src_ptr[x * 3 + 0];
+ dst_ptr[x * 4 + 1] = src_ptr[x * 3 + 1];
+ dst_ptr[x * 4 + 2] = src_ptr[x * 3 + 2];
+ dst_ptr[x * 4 + 3] = 0xff;
+ }
+
+ src_ptr += src_pitch;
+ dst_ptr += dst_pitch;
+ }
+
+ image->depth = 32;
+ image->rgb = 1;
+ image->bytes_per_line = dst_pitch;
+ image->buffer1 = dst_data;
+ image->red_mask = 0xff0000;
+ image->green_mask = 0x00ff00;
+ image->blue_mask = 0x0000ff;
+ image->palette_size = 0;
+ image->palette = NULL;
+
+ return D3DRM_OK;
+}
+
+static HRESULT d3drm_image_load_8(D3DRMIMAGE *image, const RGBQUAD *palette,
+ unsigned char *src_data, LONGLONG src_data_size, SIZE_T w, SIZE_T h, BOOL flip)
+{
+ unsigned char *dst_data;
+ SIZE_T i;
+
+ if (w > ~(SIZE_T)0 / h)
+ return D3DRMERR_BADALLOC;
+
+ if (!(dst_data = heap_alloc(w * h)))
+ {
+ WARN("Failed to allocate image buffer.\n");
+ return D3DRMERR_BADALLOC;
+ }
+
+ if (!(image->palette = heap_alloc(256 * sizeof(*image->palette))))
+ {
+ WARN("Failed to allocate palette.\n");
+ heap_free(dst_data);
+ return D3DRMERR_BADALLOC;
+ }
+
+ memcpy(image->palette, palette, 256 * sizeof(*image->palette));
+ for (i = 0; i < 256; ++i)
+ {
+ image->palette[i].flags = D3DRMPALETTE_READONLY;
+ }
+
+ if (flip)
+ {
+ for (i = 0; i < h; ++i)
+ {
+ memcpy(&dst_data[i * w], &src_data[(h - 1 - i) * w], w);
+ }
+ }
+ else
+ {
+ memcpy(dst_data, src_data, w * h);
+ }
+
+ image->depth = 8;
+ image->rgb = 0;
+ image->bytes_per_line = w;
+ image->buffer1 = dst_data;
+ image->red_mask = 0xff;
+ image->green_mask = 0xff;
+ image->blue_mask = 0xff;
+ image->palette_size = 256;
+
+ return D3DRM_OK;
+}
+
+static void CDECL destroy_image_callback(IDirect3DRMObject *obj, void *arg)
+{
+ D3DRMIMAGE *image = arg;
+
+ TRACE("texture object %p, image %p.\n", obj, image);
+
+ heap_free(image->buffer1);
+ heap_free(image);
+}
+
+static HRESULT d3drm_texture_load(struct d3drm_texture *texture,
+ const char *path, BOOL flip, D3DRMIMAGE **image_out)
+{
+ BITMAPFILEHEADER *header;
+ unsigned int w, h, bpp;
+ HANDLE file, mapping;
+ LARGE_INTEGER size;
+ D3DRMIMAGE *image;
+ BITMAPINFO *info;
+ LONGLONG rem;
+ HRESULT hr;
+
+ if ((file = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
+ return D3DRMERR_BADOBJECT;
+
+ mapping = CreateFileMappingW(file, NULL, PAGE_READONLY, 0, 0, NULL);
+ CloseHandle(file);
+ if (!mapping || mapping == INVALID_HANDLE_VALUE)
+ return D3DRMERR_BADVALUE;
+
+ if (!GetFileSizeEx(mapping, &size))
+ {
+ CloseHandle(mapping);
+ return D3DRMERR_BADVALUE;
+ }
+ rem = size.QuadPart;
+
+ header = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
+ CloseHandle(mapping);
+ if (!header)
+ return D3DRMERR_BADVALUE;
+
+ hr = D3DRMERR_BADALLOC;
+ if (!(image = heap_alloc_zero(sizeof(*image))))
+ goto fail;
+
+ hr = D3DRMERR_BADFILE;
+ if (rem < sizeof(*header) || header->bfType != 0x4d42 /* BM */)
+ goto fail;
+ rem -= sizeof(*header);
+
+ info = (BITMAPINFO *)&header[1];
+ /* Only allow version 1 DIB's (BITMAPINFOHEADER) to be loaded. */
+ if (rem < sizeof(info->bmiHeader) || info->bmiHeader.biSize != sizeof(info->bmiHeader))
+ goto fail;
+ rem -= sizeof(info->bmiHeader);
+
+ w = info->bmiHeader.biWidth;
+ h = abs(info->bmiHeader.biHeight);
+ bpp = info->bmiHeader.biBitCount == 24 ? 32 : info->bmiHeader.biBitCount;
+ if (bpp != 8 && bpp != 32)
+ goto fail;
+
+ image->width = w;
+ image->height = h;
+ image->aspectx = 1;
+ image->aspecty = 1;
+ if (bpp == 8)
+ {
+ rem -= 256 * sizeof(*info->bmiColors);
+ if (w > rem / h)
+ goto fail;
+ hr = d3drm_image_load_8(image, info->bmiColors, (unsigned char *)&info->bmiColors[256], rem, w, h, flip);
+ }
+ else
+ {
+ if (w > (rem / 3) / h)
+ goto fail;
+ hr = d3drm_image_load_32(image, (unsigned char *)&info->bmiColors, rem, w, h, flip);
+ }
+ if (FAILED(hr))
+ goto fail;
+
+ /* Use an internal destroy callback to destroy the image struct. */
+ hr = IDirect3DRMObject_AddDestroyCallback(&texture->IDirect3DRMTexture3_iface, destroy_image_callback, image);
+
+ *image_out = image;
+
+ UnmapViewOfFile(header);
+
+ return hr;
+
+fail:
+ heap_free(image);
+ UnmapViewOfFile(header);
+
+ return hr;
+}
+
static HRESULT WINAPI d3drm_texture1_QueryInterface(IDirect3DRMTexture *iface, REFIID riid, void **out)
{
struct d3drm_texture *texture = impl_from_IDirect3DRMTexture(iface);
@@ -171,9 +455,16 @@ static HRESULT WINAPI d3drm_texture1_GetClassName(IDirect3DRMTexture *iface, DWO
static HRESULT WINAPI d3drm_texture1_InitFromFile(IDirect3DRMTexture *iface, const char *filename)
{
- FIXME("iface %p, filename %s stub!\n", iface, debugstr_a(filename));
+ struct d3drm_texture *texture = impl_from_IDirect3DRMTexture(iface);
+ D3DRMIMAGE *image;
+ HRESULT hr;
- return E_NOTIMPL;
+ TRACE("iface %p, filename %s.\n", iface, debugstr_a(filename));
+
+ if (FAILED(hr = d3drm_texture_load(texture, filename, FALSE, &image)))
+ return hr;
+
+ return IDirect3DRMTexture3_InitFromImage(&texture->IDirect3DRMTexture3_iface, image);
}
static HRESULT WINAPI d3drm_texture1_InitFromSurface(IDirect3DRMTexture *iface,
@@ -473,9 +764,11 @@ static HRESULT WINAPI d3drm_texture2_GetClassName(IDirect3DRMTexture2 *iface, DW
static HRESULT WINAPI d3drm_texture2_InitFromFile(IDirect3DRMTexture2 *iface, const char *filename)
{
- FIXME("iface %p, filename %s stub!\n", iface, debugstr_a(filename));
+ struct d3drm_texture *texture = impl_from_IDirect3DRMTexture2(iface);
- return E_NOTIMPL;
+ TRACE("iface %p, filename %s.\n", iface, debugstr_a(filename));
+
+ return IDirect3DRMTexture3_InitFromFile(&texture->IDirect3DRMTexture3_iface, filename);
}
static HRESULT WINAPI d3drm_texture2_InitFromSurface(IDirect3DRMTexture2 *iface,
@@ -833,9 +1126,16 @@ static HRESULT WINAPI d3drm_texture3_GetClassName(IDirect3DRMTexture3 *iface, DW
static HRESULT WINAPI d3drm_texture3_InitFromFile(IDirect3DRMTexture3 *iface, const char *filename)
{
- FIXME("iface %p, filename %s stub!\n", iface, debugstr_a(filename));
+ struct d3drm_texture *texture = impl_from_IDirect3DRMTexture3(iface);
+ D3DRMIMAGE *image;
+ HRESULT hr;
- return E_NOTIMPL;
+ TRACE("iface %p, filename %s.\n", iface, debugstr_a(filename));
+
+ if (FAILED(hr = d3drm_texture_load(texture, filename, TRUE, &image)))
+ return hr;
+
+ return IDirect3DRMTexture3_InitFromImage(iface, image);
}
static HRESULT WINAPI d3drm_texture3_InitFromSurface(IDirect3DRMTexture3 *iface,
--
2.11.0
1
0
Signed-off-by: Kim Malmo <berencamlost(a)msn.com>
---
po/nb_NO.po | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/po/nb_NO.po b/po/nb_NO.po
index 7580e4e547..b861c2bb81 100644
--- a/po/nb_NO.po
+++ b/po/nb_NO.po
@@ -5,7 +5,7 @@ msgstr ""
"Project-Id-Version: Wine\n"
"Report-Msgid-Bugs-To: https://bugs.winehq.org\n"
"POT-Creation-Date: N/A\n"
-"PO-Revision-Date: 2018-10-07 20:50+0200\n"
+"PO-Revision-Date: 2018-10-25 11:58+0200\n"
"Last-Translator: Kim Malmo <berencamlost(a)msn.com>\n"
"Language-Team: Norwegian Bokmål <alexsornes(a)gmail.com>\n"
"Language: nb_NO\n"
@@ -308,25 +308,23 @@ msgstr "Avbryter..."
#: browseui.rc:29
msgid "%1!u! %2 remaining"
-msgstr ""
+msgstr "%1!u! %2 gjenstår"
#: browseui.rc:30
msgid "%1!u! %2 and %3!u! %4 remaining"
-msgstr ""
+msgstr "%1!u! %2 og %3!u! %4 gjenstår"
#: browseui.rc:31
-#, fuzzy
-#| msgid "&Seconds"
msgid "seconds"
-msgstr "&Sekunder"
+msgstr "sekunder"
#: browseui.rc:32
msgid "minutes"
-msgstr ""
+msgstr "minutter"
#: browseui.rc:33
msgid "hours"
-msgstr ""
+msgstr "timer"
#: comctl32.rc:68 winefile.rc:157
msgid "Properties for %s"
--
2.17.1
1
0
From: Aaryaman Vasishta <jem456.vasishta(a)gmail.com>
Signed-off-by: Aaryaman Vasishta <jem456.vasishta(a)gmail.com>
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
dlls/d3drm/d3drm.c | 40 ++++++++++++++++++++++++-----
dlls/d3drm/tests/d3drm.c | 66 ++++++++++++++++++++----------------------------
2 files changed, 61 insertions(+), 45 deletions(-)
diff --git a/dlls/d3drm/d3drm.c b/dlls/d3drm/d3drm.c
index 3ea16327bfc..d0f20235a8f 100644
--- a/dlls/d3drm/d3drm.c
+++ b/dlls/d3drm/d3drm.c
@@ -638,12 +638,24 @@ static HRESULT WINAPI d3drm1_LoadTexture(IDirect3DRM *iface,
struct d3drm_texture *object;
HRESULT hr;
- FIXME("iface %p, filename %s, texture %p stub!\n", iface, debugstr_a(filename), texture);
+ TRACE("iface %p, filename %s, texture %p.\n", iface, debugstr_a(filename), texture);
+
+ if (!texture)
+ return D3DRMERR_BADVALUE;
if (FAILED(hr = d3drm_texture_create(&object, iface)))
return hr;
*texture = &object->IDirect3DRMTexture_iface;
+ if (FAILED(hr = IDirect3DRMTexture_InitFromFile(*texture, filename)))
+ {
+ IDirect3DRMTexture_Release(*texture);
+ *texture = NULL;
+ if (!filename)
+ return D3DRMERR_BADVALUE;
+
+ return hr == D3DRMERR_BADOBJECT ? D3DRMERR_FILENOTFOUND : hr;
+ }
return D3DRM_OK;
}
@@ -1143,15 +1155,22 @@ static HRESULT WINAPI d3drm2_LoadTexture(IDirect3DRM2 *iface,
const char *filename, IDirect3DRMTexture2 **texture)
{
struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
- struct d3drm_texture *object;
+ IDirect3DRMTexture3 *texture3;
HRESULT hr;
- FIXME("iface %p, filename %s, texture %p stub!\n", iface, debugstr_a(filename), texture);
+ TRACE("iface %p, filename %s, texture %p.\n", iface, debugstr_a(filename), texture);
- if (FAILED(hr = d3drm_texture_create(&object, &d3drm->IDirect3DRM_iface)))
+ if (!texture)
+ return D3DRMERR_BADVALUE;
+
+ if (FAILED(hr = IDirect3DRM3_LoadTexture(&d3drm->IDirect3DRM3_iface, filename, &texture3)))
+ {
+ *texture = NULL;
return hr;
+ }
- *texture = &object->IDirect3DRMTexture2_iface;
+ hr = IDirect3DRMTexture3_QueryInterface(texture3, &IID_IDirect3DRMTexture2, (void **)texture);
+ IDirect3DRMTexture3_Release(texture3);
return hr;
}
@@ -1818,12 +1837,21 @@ static HRESULT WINAPI d3drm3_LoadTexture(IDirect3DRM3 *iface,
struct d3drm_texture *object;
HRESULT hr;
- FIXME("iface %p, filename %s, texture %p stub!\n", iface, debugstr_a(filename), texture);
+ TRACE("iface %p, filename %s, texture %p.\n", iface, debugstr_a(filename), texture);
+
+ if (!texture)
+ return D3DRMERR_BADVALUE;
if (FAILED(hr = d3drm_texture_create(&object, &d3drm->IDirect3DRM_iface)))
return hr;
*texture = &object->IDirect3DRMTexture3_iface;
+ if (FAILED(hr = IDirect3DRMTexture3_InitFromFile(*texture, filename)))
+ {
+ IDirect3DRMTexture3_Release(*texture);
+ *texture = NULL;
+ return hr == D3DRMERR_BADOBJECT ? D3DRMERR_FILENOTFOUND : hr;
+ }
return D3DRM_OK;
}
diff --git a/dlls/d3drm/tests/d3drm.c b/dlls/d3drm/tests/d3drm.c
index 91ee68ca435..5157952d63d 100644
--- a/dlls/d3drm/tests/d3drm.c
+++ b/dlls/d3drm/tests/d3drm.c
@@ -5601,45 +5601,36 @@ static void test_load_texture(void)
/* Test all failures together. */
texture1 = (IDirect3DRMTexture *)0xdeadbeef;
hr = IDirect3DRM_LoadTexture(d3drm1, NULL, &texture1);
- todo_wine ok(hr == D3DRMERR_BADVALUE, "Got unexpected hr %#x.\n", hr);
- todo_wine ok(!texture1, "Got unexpected texture %p.\n", texture1);
+ ok(hr == D3DRMERR_BADVALUE, "Got unexpected hr %#x.\n", hr);
+ ok(!texture1, "Got unexpected texture %p.\n", texture1);
texture1 = (IDirect3DRMTexture *)0xdeadbeef;
hr = IDirect3DRM_LoadTexture(d3drm1, "", &texture1);
- todo_wine ok(hr == D3DRMERR_FILENOTFOUND, "Got unexpected hr %#x.\n", hr);
- todo_wine ok(!texture1, "Got unexpected texture %p.\n", texture1);
- if (hr == D3DRMERR_FILENOTFOUND)
- {
- hr = IDirect3DRM_LoadTexture(d3drm1, NULL, NULL);
- ok(hr == D3DRMERR_BADVALUE, "Got unexpected hr %#x.\n", hr);
- }
+ ok(hr == D3DRMERR_FILENOTFOUND, "Got unexpected hr %#x.\n", hr);
+ ok(!texture1, "Got unexpected texture %p.\n", texture1);
+ hr = IDirect3DRM_LoadTexture(d3drm1, NULL, NULL);
+ ok(hr == D3DRMERR_BADVALUE, "Got unexpected hr %#x.\n", hr);
texture2 = (IDirect3DRMTexture2 *)0xdeadbeef;
hr = IDirect3DRM2_LoadTexture(d3drm2, NULL, &texture2);
- todo_wine ok(hr == D3DRMERR_FILENOTFOUND, "Got unexpected hr %#x.\n", hr);
- todo_wine ok(!texture2, "Got unexpected texture %p.\n", texture2);
+ ok(hr == D3DRMERR_FILENOTFOUND, "Got unexpected hr %#x.\n", hr);
+ ok(!texture2, "Got unexpected texture %p.\n", texture2);
texture2 = (IDirect3DRMTexture2 *)0xdeadbeef;
hr = IDirect3DRM2_LoadTexture(d3drm2, "", &texture2);
- todo_wine ok(hr == D3DRMERR_FILENOTFOUND, "Got unexpected hr %#x.\n", hr);
- todo_wine ok(!texture2, "Got unexpected texture %p.\n", texture2);
- if (hr == D3DRMERR_FILENOTFOUND)
- {
- hr = IDirect3DRM2_LoadTexture(d3drm2, NULL, NULL);
- ok(hr == D3DRMERR_BADVALUE, "Got unexpected hr %#x.\n", hr);
- }
+ ok(hr == D3DRMERR_FILENOTFOUND, "Got unexpected hr %#x.\n", hr);
+ ok(!texture2, "Got unexpected texture %p.\n", texture2);
+ hr = IDirect3DRM2_LoadTexture(d3drm2, NULL, NULL);
+ ok(hr == D3DRMERR_BADVALUE, "Got unexpected hr %#x.\n", hr);
texture3 = (IDirect3DRMTexture3 *)0xdeadbeef;
hr = IDirect3DRM3_LoadTexture(d3drm3, NULL, &texture3);
- todo_wine ok(hr == D3DRMERR_FILENOTFOUND, "Got unexpected hr %#x.\n", hr);
- todo_wine ok(!texture3, "Got unexpected texture %p.\n", texture3);
+ ok(hr == D3DRMERR_FILENOTFOUND, "Got unexpected hr %#x.\n", hr);
+ ok(!texture3, "Got unexpected texture %p.\n", texture3);
texture3 = (IDirect3DRMTexture3 *)0xdeadbeef;
hr = IDirect3DRM_LoadTexture(d3drm3, "", &texture3);
- todo_wine ok(hr == D3DRMERR_FILENOTFOUND, "Got unexpected hr %#x.\n", hr);
- todo_wine ok(!texture3, "Got unexpected texture %p.\n", texture3);
- if (hr == D3DRMERR_FILENOTFOUND)
- {
- hr = IDirect3DRM3_LoadTexture(d3drm3, NULL, NULL);
- ok(hr == D3DRMERR_BADVALUE, "Got unexpected hr %#x.\n", hr);
- }
+ ok(hr == D3DRMERR_FILENOTFOUND, "Got unexpected hr %#x.\n", hr);
+ ok(!texture3, "Got unexpected texture %p.\n", texture3);
+ hr = IDirect3DRM3_LoadTexture(d3drm3, NULL, NULL);
+ ok(hr == D3DRMERR_BADVALUE, "Got unexpected hr %#x.\n", hr);
for (i = 0; i < ARRAY_SIZE(tests); ++i)
{
@@ -5648,13 +5639,12 @@ static void test_load_texture(void)
hr = IDirect3DRM_LoadTexture(d3drm1, filename, &texture1);
ok(SUCCEEDED(hr), "Test %u: Failed to load texture, hr %#x.\n", i, hr);
ref2 = get_refcount((IUnknown *)d3drm1);
- todo_wine ok(ref2 > ref1, "Test %u: expected ref2 > ref1, got ref1 = %u, ref2 = %u.\n", i, ref1, ref2);
+ ok(ref2 > ref1, "Test %u: expected ref2 > ref1, got ref1 %u, ref2 %u.\n", i, ref1, ref2);
hr = IDirect3DRMTexture_InitFromFile(texture1, filename);
- todo_wine ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
+ ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
/* InitFromFile() seems to AddRef() IDirect3DRM even if it fails. */
- if (hr == D3DRMERR_BADOBJECT)
- IDirect3DRM_Release(d3drm1);
+ IDirect3DRM_Release(d3drm1);
d3drm_img = IDirect3DRMTexture_GetImage(texture1);
ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
test_bitmap_data(i * 7, d3drm_img, FALSE, tests[i].w, tests[i].h, tests[i].palettized);
@@ -5678,12 +5668,11 @@ static void test_load_texture(void)
hr = IDirect3DRM2_LoadTexture(d3drm2, filename, &texture2);
ok(SUCCEEDED(hr), "Test %u: Failed to load texture, hr %#x.\n", i, hr);
ref2 = get_refcount((IUnknown *)d3drm1);
- todo_wine ok(ref2 > ref1, "Test %u: expected ref2 > ref1, got ref1 = %u, ref2 = %u.\n", i, ref1, ref2);
+ ok(ref2 > ref1, "Test %u: expected ref2 > ref1, got ref1 %u, ref2 %u.\n", i, ref1, ref2);
hr = IDirect3DRMTexture2_InitFromFile(texture2, filename);
- todo_wine ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
- if (hr == D3DRMERR_BADOBJECT)
- IDirect3DRM_Release(d3drm1);
+ ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
+ IDirect3DRM_Release(d3drm1);
d3drm_img = IDirect3DRMTexture2_GetImage(texture2);
ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
test_bitmap_data(i * 7 + 2, d3drm_img, TRUE, tests[i].w, tests[i].h, tests[i].palettized);
@@ -5707,12 +5696,11 @@ static void test_load_texture(void)
hr = IDirect3DRM3_LoadTexture(d3drm3, filename, &texture3);
ok(SUCCEEDED(hr), "Test %u: Failed to load texture, hr %#x.\n", i, hr);
ref2 = get_refcount((IUnknown *)d3drm1);
- todo_wine ok(ref2 > ref1, "Test %u: expected ref2 > ref1, got ref1 = %u, ref2 = %u.\n", i, ref1, ref2);
+ ok(ref2 > ref1, "Test %u: expected ref2 > ref1, got ref1 %u, ref2 %u.\n", i, ref1, ref2);
hr = IDirect3DRMTexture3_InitFromFile(texture3, filename);
- todo_wine ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
- if (hr == D3DRMERR_BADOBJECT)
- IDirect3DRM_Release(d3drm1);
+ ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
+ IDirect3DRM_Release(d3drm1);
d3drm_img = IDirect3DRMTexture3_GetImage(texture3);
ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
test_bitmap_data(i * 7 + 4, d3drm_img, TRUE, tests[i].w, tests[i].h, tests[i].palettized);
--
2.11.0
2
1
25 Oct '18
From: Aaryaman Vasishta <jem456.vasishta(a)gmail.com>
Signed-off-by: Aaryaman Vasishta <jem456.vasishta(a)gmail.com>
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
dlls/d3drm/tests/d3drm.c | 53 ++++----
dlls/d3drm/texture.c | 312 ++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 329 insertions(+), 36 deletions(-)
diff --git a/dlls/d3drm/tests/d3drm.c b/dlls/d3drm/tests/d3drm.c
index 9bc9a84444a..91ee68ca435 100644
--- a/dlls/d3drm/tests/d3drm.c
+++ b/dlls/d3drm/tests/d3drm.c
@@ -5656,9 +5656,8 @@ static void test_load_texture(void)
if (hr == D3DRMERR_BADOBJECT)
IDirect3DRM_Release(d3drm1);
d3drm_img = IDirect3DRMTexture_GetImage(texture1);
- todo_wine ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
- if (d3drm_img)
- test_bitmap_data(i * 7, d3drm_img, FALSE, tests[i].w, tests[i].h, tests[i].palettized);
+ ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
+ test_bitmap_data(i * 7, d3drm_img, FALSE, tests[i].w, tests[i].h, tests[i].palettized);
IDirect3DRMTexture_Release(texture1);
ref2 = get_refcount((IUnknown *)d3drm1);
ok(ref1 == ref2, "Test %u: expected ref1 == ref2, got ref1 = %u, ref2 = %u.\n", i, ref1, ref2);
@@ -5666,15 +5665,14 @@ static void test_load_texture(void)
NULL, &IID_IDirect3DRMTexture, (void **)&texture1);
ok(SUCCEEDED(hr), "Test %u: Failed to create texture, hr %#x.\n", i, hr);
hr = IDirect3DRMTexture_InitFromFile(texture1, NULL);
- todo_wine ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
+ ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
hr = IDirect3DRMTexture_InitFromFile(texture1, "");
- todo_wine ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
+ ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
hr = IDirect3DRMTexture_InitFromFile(texture1, filename);
- todo_wine ok(SUCCEEDED(hr), "Test %u: Failed to initialise texture from file, hr %#x.\n", i, hr);
+ ok(SUCCEEDED(hr), "Test %u: Failed to initialise texture from file, hr %#x.\n", i, hr);
d3drm_img = IDirect3DRMTexture_GetImage(texture1);
- todo_wine ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
- if (d3drm_img)
- test_bitmap_data(i * 7 + 1, d3drm_img, FALSE, tests[i].w, tests[i].h, tests[i].palettized);
+ ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
+ test_bitmap_data(i * 7 + 1, d3drm_img, FALSE, tests[i].w, tests[i].h, tests[i].palettized);
IDirect3DRMTexture_Release(texture1);
hr = IDirect3DRM2_LoadTexture(d3drm2, filename, &texture2);
@@ -5687,9 +5685,8 @@ static void test_load_texture(void)
if (hr == D3DRMERR_BADOBJECT)
IDirect3DRM_Release(d3drm1);
d3drm_img = IDirect3DRMTexture2_GetImage(texture2);
- todo_wine ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
- if (d3drm_img)
- test_bitmap_data(i * 7 + 2, d3drm_img, TRUE, tests[i].w, tests[i].h, tests[i].palettized);
+ ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
+ test_bitmap_data(i * 7 + 2, d3drm_img, TRUE, tests[i].w, tests[i].h, tests[i].palettized);
IDirect3DRMTexture2_Release(texture2);
ref2 = get_refcount((IUnknown *)d3drm1);
ok(ref1 == ref2, "Test %u: expected ref1 == ref2, got ref1 = %u, ref2 = %u.\n", i, ref1, ref2);
@@ -5697,15 +5694,14 @@ static void test_load_texture(void)
NULL, &IID_IDirect3DRMTexture2, (void **)&texture2);
ok(SUCCEEDED(hr), "Test %u: Failed to create texture, hr %#x.\n", i, hr);
hr = IDirect3DRMTexture2_InitFromFile(texture2, NULL);
- todo_wine ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
+ ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
hr = IDirect3DRMTexture2_InitFromFile(texture2, "");
- todo_wine ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
+ ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
hr = IDirect3DRMTexture2_InitFromFile(texture2, filename);
- todo_wine ok(SUCCEEDED(hr), "Test %u: Failed to initialise texture from file, hr %#x.\n", i, hr);
+ ok(SUCCEEDED(hr), "Test %u: Failed to initialise texture from file, hr %#x.\n", i, hr);
d3drm_img = IDirect3DRMTexture2_GetImage(texture2);
- todo_wine ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
- if (d3drm_img)
- test_bitmap_data(i * 7 + 3, d3drm_img, TRUE, tests[i].w, tests[i].h, tests[i].palettized);
+ ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
+ test_bitmap_data(i * 7 + 3, d3drm_img, TRUE, tests[i].w, tests[i].h, tests[i].palettized);
IDirect3DRMTexture2_Release(texture2);
hr = IDirect3DRM3_LoadTexture(d3drm3, filename, &texture3);
@@ -5718,17 +5714,15 @@ static void test_load_texture(void)
if (hr == D3DRMERR_BADOBJECT)
IDirect3DRM_Release(d3drm1);
d3drm_img = IDirect3DRMTexture3_GetImage(texture3);
- todo_wine ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
- if (d3drm_img)
- test_bitmap_data(i * 7 + 4, d3drm_img, TRUE, tests[i].w, tests[i].h, tests[i].palettized);
+ ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
+ test_bitmap_data(i * 7 + 4, d3drm_img, TRUE, tests[i].w, tests[i].h, tests[i].palettized);
/* Test whether querying a version 1 texture from version 3 causes a
* change in the loading behavior. */
hr = IDirect3DRMTexture3_QueryInterface(texture3, &IID_IDirect3DRMTexture, (void **)&texture1);
ok(SUCCEEDED(hr), "Failed to get IDirect3DRMTexture interface, hr %#x.\n", hr);
d3drm_img = IDirect3DRMTexture_GetImage(texture1);
- todo_wine ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
- if (d3drm_img)
- test_bitmap_data(i * 7 + 5, d3drm_img, TRUE, tests[i].w, tests[i].h, tests[i].palettized);
+ ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
+ test_bitmap_data(i * 7 + 5, d3drm_img, TRUE, tests[i].w, tests[i].h, tests[i].palettized);
IDirect3DRMTexture_Release(texture1);
IDirect3DRMTexture3_Release(texture3);
ref2 = get_refcount((IUnknown *)d3drm1);
@@ -5738,15 +5732,14 @@ static void test_load_texture(void)
NULL, &IID_IDirect3DRMTexture3, (void **)&texture3);
ok(SUCCEEDED(hr), "Test %u: Failed to create texture, hr %#x.\n", i, hr);
hr = IDirect3DRMTexture3_InitFromFile(texture3, NULL);
- todo_wine ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
+ ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
hr = IDirect3DRMTexture3_InitFromFile(texture3, "");
- todo_wine ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
+ ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
hr = IDirect3DRMTexture3_InitFromFile(texture3, filename);
- todo_wine ok(SUCCEEDED(hr), "Test %u: Failed to initialize texture from file, hr %#x.\n", i, hr);
+ ok(SUCCEEDED(hr), "Test %u: Failed to initialize texture from file, hr %#x.\n", i, hr);
d3drm_img = IDirect3DRMTexture3_GetImage(texture3);
- todo_wine ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
- if (d3drm_img)
- test_bitmap_data(i * 7 + 6, d3drm_img, TRUE, tests[i].w, tests[i].h, tests[i].palettized);
+ ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
+ test_bitmap_data(i * 7 + 6, d3drm_img, TRUE, tests[i].w, tests[i].h, tests[i].palettized);
IDirect3DRMTexture3_Release(texture3);
ret = DeleteFileA(filename);
diff --git a/dlls/d3drm/texture.c b/dlls/d3drm/texture.c
index fd56e76ff92..58be588a1d6 100644
--- a/dlls/d3drm/texture.c
+++ b/dlls/d3drm/texture.c
@@ -2,6 +2,7 @@
* Implementation of IDirect3DRMTextureX interfaces
*
* Copyright 2012 Christian Costa
+ * Copyright 2016 Aaryaman Vasishta
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -67,6 +68,289 @@ static BOOL d3drm_validate_image(D3DRMIMAGE *image)
return TRUE;
}
+static BOOL d3drm_image_palettise(D3DRMIMAGE *image, unsigned char *src_data,
+ unsigned int w, unsigned int h, BOOL flip)
+{
+ unsigned char *dst_data, *src_ptr, *dst_ptr;
+ unsigned int src_pitch, dst_pitch, i, x, y;
+ D3DRMPALETTEENTRY *palette, *entry;
+ unsigned int colour_count = 0;
+
+ if (w > (~(SIZE_T)0 - 3) / h)
+ return FALSE;
+
+ src_pitch = flip ? -w * 3 : w * 3;
+ dst_pitch = (w + 3) & ~3;
+
+ if (!(dst_data = heap_alloc(dst_pitch * h)))
+ {
+ WARN("Failed to allocate image buffer.\n");
+ return FALSE;
+ }
+ memset(dst_data, 0xff, dst_pitch * h);
+
+ if (!(palette = heap_alloc(256 * sizeof(*palette))))
+ {
+ WARN("Failed to allocate palette.\n");
+ heap_free(dst_data);
+ return FALSE;
+ }
+
+ src_ptr = flip ? &src_data[(h - 1) * w * 3] : src_data;
+ dst_ptr = dst_data;
+
+ for (y = 0; y < h; ++y)
+ {
+ for (x = 0; x < w; ++x)
+ {
+ for (i = 0; i < colour_count; ++i)
+ {
+ entry = &palette[i];
+ if (entry->red == src_ptr[x * 3 + 0]
+ && entry->green == src_ptr[x * 3 + 1]
+ && entry->blue == src_ptr[x * 3 + 2])
+ break;
+ }
+
+ if (i == colour_count)
+ {
+ if (colour_count == 256)
+ {
+ heap_free(dst_data);
+ heap_free(palette);
+ return FALSE;
+ }
+
+ entry = &palette[colour_count++];
+ entry->red = src_ptr[x * 3 + 0];
+ entry->green = src_ptr[x * 3 + 1];
+ entry->blue = src_ptr[x * 3 + 2];
+ entry->flags = D3DRMPALETTE_READONLY;
+ }
+
+ dst_ptr[x] = i;
+ }
+
+ src_ptr += src_pitch;
+ dst_ptr += dst_pitch;
+ }
+
+ image->depth = 8;
+ image->rgb = 0;
+ image->bytes_per_line = dst_pitch;
+ image->buffer1 = dst_data;
+ image->red_mask = 0xff;
+ image->green_mask = 0xff;
+ image->blue_mask = 0xff;
+ image->palette_size = colour_count;
+ if (!(image->palette = heap_realloc(palette, colour_count * sizeof(*palette))))
+ image->palette = palette;
+
+ return TRUE;
+}
+
+static HRESULT d3drm_image_load_32(D3DRMIMAGE *image, unsigned char *src_data,
+ LONGLONG src_data_size, unsigned int w, unsigned int h, BOOL flip)
+{
+ unsigned char *dst_data, *src_ptr, *dst_ptr;
+ unsigned int src_pitch, dst_pitch, x, y;
+
+ if (d3drm_image_palettise(image, src_data, w, h, flip))
+ return D3DRM_OK;
+
+ if (w > (~(SIZE_T)0 / 4) / h)
+ return D3DRMERR_BADALLOC;
+
+ src_pitch = flip ? -w * 3 : w * 3;
+ dst_pitch = w * 4;
+
+ if (!(dst_data = heap_alloc(dst_pitch * h)))
+ {
+ WARN("Failed to allocate image buffer.\n");
+ return D3DRMERR_BADALLOC;
+ }
+
+ src_ptr = flip ? &src_data[(h - 1) * w * 3] : src_data;
+ dst_ptr = dst_data;
+
+ for (y = 0; y < h; ++y)
+ {
+ for (x = 0; x < w; ++x)
+ {
+ dst_ptr[x * 4 + 0] = src_ptr[x * 3 + 0];
+ dst_ptr[x * 4 + 1] = src_ptr[x * 3 + 1];
+ dst_ptr[x * 4 + 2] = src_ptr[x * 3 + 2];
+ dst_ptr[x * 4 + 3] = 0xff;
+ }
+
+ src_ptr += src_pitch;
+ dst_ptr += dst_pitch;
+ }
+
+ image->depth = 32;
+ image->rgb = 1;
+ image->bytes_per_line = dst_pitch;
+ image->buffer1 = dst_data;
+ image->red_mask = 0xff0000;
+ image->green_mask = 0x00ff00;
+ image->blue_mask = 0x0000ff;
+ image->palette_size = 0;
+ image->palette = NULL;
+
+ return D3DRM_OK;
+}
+
+static HRESULT d3drm_image_load_8(D3DRMIMAGE *image, const RGBQUAD *palette,
+ unsigned char *src_data, LONGLONG src_data_size, unsigned int w, unsigned int h, BOOL flip)
+{
+ unsigned char *dst_data;
+ unsigned int i;
+
+ if (w > ~(SIZE_T)0 / h)
+ return D3DRMERR_BADALLOC;
+
+ if (!(dst_data = heap_alloc(w * h)))
+ {
+ WARN("Failed to allocate image buffer.\n");
+ return D3DRMERR_BADALLOC;
+ }
+
+ if (!(image->palette = heap_alloc(256 * sizeof(*image->palette))))
+ {
+ WARN("Failed to allocate palette.\n");
+ heap_free(dst_data);
+ return D3DRMERR_BADALLOC;
+ }
+
+ memcpy(image->palette, palette, 256 * sizeof(*image->palette));
+ for (i = 0; i < 256; ++i)
+ {
+ image->palette[i].flags = D3DRMPALETTE_READONLY;
+ }
+
+ if (flip)
+ {
+ for (i = 0; i < h; ++i)
+ {
+ memcpy(&dst_data[i * w], &src_data[(h - 1 - i) * w], w);
+ }
+ }
+ else
+ {
+ memcpy(dst_data, src_data, w * h);
+ }
+
+ image->depth = 8;
+ image->rgb = 0;
+ image->bytes_per_line = w;
+ image->buffer1 = dst_data;
+ image->red_mask = 0xff;
+ image->green_mask = 0xff;
+ image->blue_mask = 0xff;
+ image->palette_size = 256;
+
+ return D3DRM_OK;
+}
+
+static void CDECL destroy_image_callback(IDirect3DRMObject *obj, void *arg)
+{
+ D3DRMIMAGE *image = arg;
+
+ TRACE("texture object %p, image %p.\n", obj, image);
+
+ heap_free(image->buffer1);
+ heap_free(image);
+}
+
+static HRESULT d3drm_texture_load(struct d3drm_texture *texture,
+ const char *path, BOOL flip, D3DRMIMAGE **image_out)
+{
+ BITMAPFILEHEADER *header;
+ unsigned int w, h, bpp;
+ HANDLE file, mapping;
+ LARGE_INTEGER size;
+ D3DRMIMAGE *image;
+ BITMAPINFO *info;
+ LONGLONG rem;
+ HRESULT hr;
+
+ if ((file = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
+ return D3DRMERR_BADOBJECT;
+
+ mapping = CreateFileMappingW(file, NULL, PAGE_READONLY, 0, 0, NULL);
+ CloseHandle(file);
+ if (!mapping || mapping == INVALID_HANDLE_VALUE)
+ return D3DRMERR_BADVALUE;
+
+ if (!GetFileSizeEx(mapping, &size))
+ {
+ CloseHandle(mapping);
+ return D3DRMERR_BADVALUE;
+ }
+ rem = size.QuadPart;
+
+ header = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
+ CloseHandle(mapping);
+ if (!header)
+ return D3DRMERR_BADVALUE;
+
+ hr = D3DRMERR_BADALLOC;
+ if (!(image = heap_alloc_zero(sizeof(*image))))
+ goto fail;
+
+ hr = D3DRMERR_BADFILE;
+ if (rem < sizeof(*header) || header->bfType != 0x4d42 /* BM */)
+ goto fail;
+ rem -= sizeof(*header);
+
+ info = (BITMAPINFO *)&header[1];
+ /* Only allow version 1 DIB's (BITMAPINFOHEADER) to be loaded. */
+ if (rem < sizeof(info->bmiHeader) || info->bmiHeader.biSize != sizeof(info->bmiHeader))
+ goto fail;
+ rem -= sizeof(info->bmiHeader);
+
+ w = info->bmiHeader.biWidth;
+ h = abs(info->bmiHeader.biHeight);
+ bpp = info->bmiHeader.biBitCount == 24 ? 32 : info->bmiHeader.biBitCount;
+ if (bpp != 8 && bpp != 32)
+ goto fail;
+
+ image->width = w;
+ image->height = h;
+ image->aspectx = 1;
+ image->aspecty = 1;
+ if (bpp == 8)
+ {
+ rem -= 256 * sizeof(*info->bmiColors);
+ if (w > rem / h)
+ goto fail;
+ hr = d3drm_image_load_8(image, info->bmiColors, (unsigned char *)&info->bmiColors[256], rem, w, h, flip);
+ }
+ else
+ {
+ if (w > (rem / 3) / h)
+ goto fail;
+ hr = d3drm_image_load_32(image, (unsigned char *)&info->bmiColors, rem, w, h, flip);
+ }
+ if (FAILED(hr))
+ goto fail;
+
+ /* Use an internal destroy callback to destroy the image struct. */
+ hr = IDirect3DRMObject_AddDestroyCallback(&texture->IDirect3DRMTexture3_iface, destroy_image_callback, image);
+
+ *image_out = image;
+
+ UnmapViewOfFile(header);
+
+ return hr;
+
+fail:
+ heap_free(image);
+ UnmapViewOfFile(header);
+
+ return hr;
+}
+
static HRESULT WINAPI d3drm_texture1_QueryInterface(IDirect3DRMTexture *iface, REFIID riid, void **out)
{
struct d3drm_texture *texture = impl_from_IDirect3DRMTexture(iface);
@@ -171,9 +455,16 @@ static HRESULT WINAPI d3drm_texture1_GetClassName(IDirect3DRMTexture *iface, DWO
static HRESULT WINAPI d3drm_texture1_InitFromFile(IDirect3DRMTexture *iface, const char *filename)
{
- FIXME("iface %p, filename %s stub!\n", iface, debugstr_a(filename));
+ struct d3drm_texture *texture = impl_from_IDirect3DRMTexture(iface);
+ D3DRMIMAGE *image;
+ HRESULT hr;
- return E_NOTIMPL;
+ TRACE("iface %p, filename %s.\n", iface, debugstr_a(filename));
+
+ if (FAILED(hr = d3drm_texture_load(texture, filename, FALSE, &image)))
+ return hr;
+
+ return IDirect3DRMTexture3_InitFromImage(&texture->IDirect3DRMTexture3_iface, image);
}
static HRESULT WINAPI d3drm_texture1_InitFromSurface(IDirect3DRMTexture *iface,
@@ -473,9 +764,11 @@ static HRESULT WINAPI d3drm_texture2_GetClassName(IDirect3DRMTexture2 *iface, DW
static HRESULT WINAPI d3drm_texture2_InitFromFile(IDirect3DRMTexture2 *iface, const char *filename)
{
- FIXME("iface %p, filename %s stub!\n", iface, debugstr_a(filename));
+ struct d3drm_texture *texture = impl_from_IDirect3DRMTexture2(iface);
- return E_NOTIMPL;
+ TRACE("iface %p, filename %s.\n", iface, debugstr_a(filename));
+
+ return IDirect3DRMTexture3_InitFromFile(&texture->IDirect3DRMTexture3_iface, filename);
}
static HRESULT WINAPI d3drm_texture2_InitFromSurface(IDirect3DRMTexture2 *iface,
@@ -833,9 +1126,16 @@ static HRESULT WINAPI d3drm_texture3_GetClassName(IDirect3DRMTexture3 *iface, DW
static HRESULT WINAPI d3drm_texture3_InitFromFile(IDirect3DRMTexture3 *iface, const char *filename)
{
- FIXME("iface %p, filename %s stub!\n", iface, debugstr_a(filename));
+ struct d3drm_texture *texture = impl_from_IDirect3DRMTexture3(iface);
+ D3DRMIMAGE *image;
+ HRESULT hr;
- return E_NOTIMPL;
+ TRACE("iface %p, filename %s.\n", iface, debugstr_a(filename));
+
+ if (FAILED(hr = d3drm_texture_load(texture, filename, TRUE, &image)))
+ return hr;
+
+ return IDirect3DRMTexture3_InitFromImage(iface, image);
}
static HRESULT WINAPI d3drm_texture3_InitFromSurface(IDirect3DRMTexture3 *iface,
--
2.11.0
2
1
[PATCH v4] comctl32: Implement handling of EM_SETCUEBANNER/EM_GETCUEBANNER messages.
by Sergio Gómez Del Real 24 Oct '18
by Sergio Gómez Del Real 24 Oct '18
24 Oct '18
Signed-off-by: Sergio Gómez Del Real <sdelreal(a)codeweavers.com>
---
dlls/comctl32/edit.c | 65 +++++++++++++++++++++++++++++++++++
dlls/comctl32/tests/edit.c | 69 ++++++++++++++++++++++++++++++++++++++
2 files changed, 134 insertions(+)
diff --git a/dlls/comctl32/edit.c b/dlls/comctl32/edit.c
index f0180adfbe..3da7b98491 100644
--- a/dlls/comctl32/edit.c
+++ b/dlls/comctl32/edit.c
@@ -131,6 +131,7 @@ typedef struct
should be sent to the first parent. */
HWND hwndListBox; /* handle of ComboBox's listbox or NULL */
INT wheelDeltaRemainder; /* scroll wheel delta left over after scrolling whole lines */
+ WCHAR *cue_banner_text;
/*
* only for multi line controls
*/
@@ -2181,6 +2182,12 @@ static void EDIT_PaintLine(EDITSTATE *es, HDC dc, INT line, BOOL rev)
x += EDIT_PaintText(es, dc, x, y, line, e - li, li + ll - e, FALSE);
} else
x += EDIT_PaintText(es, dc, x, y, line, 0, ll, FALSE);
+
+ if (es->cue_banner_text && es->text_length == 0 && !(es->flags & EF_FOCUSED))
+ {
+ SetTextColor(dc, GetSysColor(COLOR_GRAYTEXT));
+ TextOutW(dc, x, y, es->cue_banner_text, strlenW(es->cue_banner_text));
+ }
}
@@ -4152,6 +4159,55 @@ static LRESULT EDIT_EM_GetThumb(EDITSTATE *es)
EDIT_WM_HScroll(es, EM_GETTHUMB, 0));
}
+static inline WCHAR *heap_strdupW(const WCHAR *str)
+{
+ int len = strlenW(str) + 1;
+ WCHAR *ret = heap_alloc(len * sizeof(WCHAR));
+ lstrcpynW(ret, str, len);
+ return ret;
+}
+
+/*********************************************************************
+ *
+ * EM_SETCUEBANNER
+ *
+ */
+static BOOL EDIT_EM_SetCueBanner(EDITSTATE *es, const WCHAR *cue_text)
+{
+ if (es->style & ES_MULTILINE || !cue_text)
+ return FALSE;
+
+ heap_free(es->cue_banner_text);
+ es->cue_banner_text = heap_strdupW(cue_text);
+
+ return TRUE;
+}
+
+/*********************************************************************
+ *
+ * EM_GETCUEBANNER
+ *
+ */
+static BOOL EDIT_EM_GetCueBanner(EDITSTATE *es, WCHAR *buf, DWORD size)
+{
+ if (!es->cue_banner_text)
+ {
+ if (!(es->style & ES_MULTILINE) && buf && size)
+ *buf = 0;
+ return FALSE;
+ }
+ else
+ {
+ if (buf && size)
+ {
+ if (size > strlenW(es->cue_banner_text))
+ size = strlenW(es->cue_banner_text) + 1;
+ lstrcpynW(buf, es->cue_banner_text, size);
+ }
+ return TRUE;
+ }
+}
+
/********************************************************************
*
@@ -4489,6 +4545,7 @@ static LRESULT EDIT_WM_NCDestroy(EDITSTATE *es)
SetWindowLongPtrW( es->hwndSelf, 0, 0 );
heap_free(es->undo_text);
+ heap_free(es->cue_banner_text);
heap_free(es);
return 0;
@@ -4703,6 +4760,14 @@ static LRESULT CALLBACK EDIT_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPAR
result = EDIT_EM_CharFromPos(es, (short)LOWORD(lParam), (short)HIWORD(lParam));
break;
+ case EM_SETCUEBANNER:
+ result = EDIT_EM_SetCueBanner(es, (const WCHAR *)lParam);
+ break;
+
+ case EM_GETCUEBANNER:
+ result = EDIT_EM_GetCueBanner(es, (WCHAR *)wParam, (DWORD)lParam);
+ break;
+
/* End of the EM_ messages which were in numerical order; what order
* are these in? vaguely alphabetical?
*/
diff --git a/dlls/comctl32/tests/edit.c b/dlls/comctl32/tests/edit.c
index a5097d1cbb..0d24ca7dcf 100644
--- a/dlls/comctl32/tests/edit.c
+++ b/dlls/comctl32/tests/edit.c
@@ -3061,6 +3061,74 @@ static const struct message killfocus_combined_seq[] =
{ 0 }
};
+static void test_cue_banner(void)
+{
+ HWND hwnd_edit;
+ BOOL ret;
+ static WCHAR testW[] = {'T','e','s','t',0};
+ static WCHAR testcmp1W[] = {'T','e','s','t',0};
+ static WCHAR testcmp2W[] = {'T','e','s',0};
+ static WCHAR getcuetestW[5] = {'T',0};
+ static WCHAR emptyW[] = {0};
+
+ hwnd_edit = create_editcontrolW(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
+
+ ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, (WPARAM)getcuetestW, 5);
+ if (lstrcmpW(getcuetestW, emptyW) != 0)
+ {
+ win_skip("skipping for Win XP and 2003 Server.\n");
+ DestroyWindow(hwnd_edit);
+ return;
+ }
+ ok(lstrcmpW(getcuetestW, emptyW) == 0, "First char is %c\n", getcuetestW[0]);
+ ok(ret == FALSE, "EM_GETCUEBANNER should have returned FALSE.\n");
+
+ ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, 0, 0);
+ ok(ret == FALSE, "EM_GETCUEBANNER should have returned FALSE.\n");
+
+ ret = SendMessageW(hwnd_edit, EM_SETCUEBANNER, 0, 0);
+ ok(ret == FALSE, "EM_SETCUEBANNER should have returned FALSE.\n");
+
+ ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, 0, 0);
+ ok(ret == FALSE, "EM_GETCUEBANNER should have returned FALSE.\n");
+
+ ret = SendMessageW(hwnd_edit, EM_SETCUEBANNER, 0, (LPARAM)testW);
+ ok(ret == TRUE, "EM_SETCUEBANNER should have returned TRUE.\n");
+
+ ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, 0, 5);
+ ok(ret == TRUE, "EM_GETCUEBANNER should have returned FALSE.\n");
+
+ ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, (WPARAM)getcuetestW, 5);
+ ok(ret == TRUE, "EM_GETCUEBANNER should have returned TRUE.\n");
+ ok(lstrcmpW(getcuetestW, testW) == 0, "EM_GETCUEBANNER returned string %s.\n", wine_dbgstr_w(getcuetestW));
+
+ ret = SendMessageW(hwnd_edit, EM_SETCUEBANNER, 0, (LPARAM)emptyW);
+ ok(ret == TRUE, "EM_SETCUEBANNER should have returned TRUE.\n");
+
+ ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, (WPARAM)getcuetestW, 5);
+ ok(ret == TRUE, "EM_GETCUEBANNER should have returned TRUE.\n");
+ ok(lstrcmpW(getcuetestW, emptyW) == 0, "EM_GETCUEBANNER returned string %s.\n", wine_dbgstr_w(getcuetestW));
+
+ /* EM_GETCUEBANNER's buffer size includes null char */
+ ret = SendMessageW(hwnd_edit, EM_SETCUEBANNER, 0, (LPARAM)testW);
+ ok(ret == TRUE, "EM_SETCUEBANNER should have returned TRUE.\n");
+ memset(testW, 0, lstrlenW(testcmp1W)*sizeof(WCHAR));
+ ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, (WPARAM)testW, (LPARAM)lstrlenW(testcmp1W)+1);
+ ok(ret == TRUE, "EM_GETCUEBANNER should have returned TRUE.\n");
+ ok(lstrcmpW(testW, testcmp1W) == 0, "EM_GETCUEBANNER returned string %s.\n", wine_dbgstr_w(testW));
+ memset(testW, 0, lstrlenW(testcmp1W)*sizeof(WCHAR));
+ ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, (WPARAM)testW, (LPARAM)lstrlenW(testcmp1W));
+ ok(lstrcmpW(testW, testcmp2W) == 0, "EM_GETCUEBANNER returned string %s.\n", wine_dbgstr_w(testW));
+ DestroyWindow(hwnd_edit);
+
+ /* setting cue banner fails for multi-line edit controls */
+ hwnd_edit = create_editcontrolW(ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE, 0);
+ ret = SendMessageW(hwnd_edit, EM_SETCUEBANNER, 0, (LPARAM)testW);
+ ok(ret == FALSE, "EM_SETCUEBANNER.\n");
+
+ DestroyWindow(hwnd_edit);
+}
+
static void test_change_focus(void)
{
HWND hwnd, parent_wnd;
@@ -3138,6 +3206,7 @@ START_TEST(edit)
test_EM_GETLINE();
test_wordbreak_proc();
test_change_focus();
+ test_cue_banner();
UnregisterWindowClasses();
--
2.17.1
2
4
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/gdiplus/pen.c | 7 +------
dlls/gdiplus/tests/pen.c | 38 ++++++++++++++++++++++++++++++++++++++
include/gdiplusflat.h | 1 +
3 files changed, 40 insertions(+), 6 deletions(-)
diff --git a/dlls/gdiplus/pen.c b/dlls/gdiplus/pen.c
index ad45bcb5d5..8bcb91819a 100644
--- a/dlls/gdiplus/pen.c
+++ b/dlls/gdiplus/pen.c
@@ -480,17 +480,12 @@ GpStatus WINGDIPAPI GdipScalePenTransform(GpPen *pen, REAL sx, REAL sy, GpMatrix
GpStatus WINGDIPAPI GdipRotatePenTransform(GpPen *pen, REAL angle, GpMatrixOrder order)
{
- static int calls;
-
TRACE("(%p,%0.2f,%u)\n", pen, angle, order);
if(!pen)
return InvalidParameter;
- if(!(calls++))
- FIXME("not implemented\n");
-
- return NotImplemented;
+ return GdipRotateMatrix(&pen->transform, angle, order);
}
GpStatus WINGDIPAPI GdipMultiplyPenTransform(GpPen *pen, GDIPCONST GpMatrix *matrix,
diff --git a/dlls/gdiplus/tests/pen.c b/dlls/gdiplus/tests/pen.c
index 530967afb2..ceab92acff 100644
--- a/dlls/gdiplus/tests/pen.c
+++ b/dlls/gdiplus/tests/pen.c
@@ -588,6 +588,44 @@ static void test_transform(void)
expectf(-15.0, values[4]);
expectf(-76.0, values[5]);
+ /* Rotate */
+ status = GdipResetPenTransform(pen);
+ expect(Ok, status);
+
+ status = GdipSetMatrixElements(matrix, 2.0, 1.0, 1.0, 4.0, 1.0, 2.0);
+ expect(Ok, status);
+
+ status = GdipSetPenTransform(pen, matrix);
+ expect(Ok, status);
+
+ status = GdipRotatePenTransform(NULL, 10.0, MatrixOrderPrepend);
+ expect(InvalidParameter, status);
+
+ status = GdipRotatePenTransform(pen, 45.0, MatrixOrderPrepend);
+ expect(Ok, status);
+
+ get_pen_transform(pen, values);
+ expectf(2.12, values[0]);
+ expectf(3.54, values[1]);
+ expectf(-0.71, values[2]);
+ expectf(2.12, values[3]);
+ expectf(1.0, values[4]);
+ expectf(2.0, values[5]);
+
+ status = GdipScalePenTransform(pen, 2.0, -10.0, MatrixOrderAppend);
+ expect(Ok, status);
+
+ status = GdipRotatePenTransform(pen, 180.0, MatrixOrderAppend);
+ expect(Ok, status);
+
+ get_pen_transform(pen, values);
+ expectf(-4.24, values[0]);
+ expectf(35.36, values[1]);
+ expectf(1.41, values[2]);
+ expectf(21.21, values[3]);
+ expectf(-2.0, values[4]);
+ expectf(20.0, values[5]);
+
GdipDeletePen(pen);
GdipDeleteMatrix(matrix);
diff --git a/include/gdiplusflat.h b/include/gdiplusflat.h
index 5593ac51b6..ad944d6a34 100644
--- a/include/gdiplusflat.h
+++ b/include/gdiplusflat.h
@@ -631,6 +631,7 @@ GpStatus WINGDIPAPI GdipGetPenMode(GpPen*,GpPenAlignment*);
GpStatus WINGDIPAPI GdipGetPenTransform(GpPen *, GpMatrix *);
GpStatus WINGDIPAPI GdipMultiplyPenTransform(GpPen *,GDIPCONST GpMatrix *,GpMatrixOrder);
GpStatus WINGDIPAPI GdipResetPenTransform(GpPen*);
+GpStatus WINGDIPAPI GdipRotatePenTransform(GpPen*,REAL,GpMatrixOrder);
GpStatus WINGDIPAPI GdipScalePenTransform(GpPen*,REAL,REAL,GpMatrixOrder);
GpStatus WINGDIPAPI GdipSetPenBrushFill(GpPen*,GpBrush*);
GpStatus WINGDIPAPI GdipSetPenColor(GpPen*,ARGB);
--
2.19.1
2
1
[PATCH 1/6] shell32/autocomplete: Introduce helpers for proper enumeration
by Gabriel Ivăncescu 24 Oct '18
by Gabriel Ivăncescu 24 Oct '18
24 Oct '18
These will be used to implement proper string enumeration, because Windows
doesn't reset and re-enumerate it everytime autocompletion happens, and it
also sorts them like Windows does.
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
---
For now, the first two patches in the series do nothing because the helpers
are unused; they will be used afterwards, and were split to avoid the
patches becoming too large.
These helpers pave the way to implement the string sorting and
ResetEnumerator, two of the TODO also listed at the top (tests provided at
the end of the series). I will now describe the reason I ended up with this
sort implementation.
Merge Sort has been used to sort the strings because it is stable, and
because it minimizes the amount of comparisons, which is essential for
case-insensitive string comparisons. However it's not a plain bottom-up
merge sort, it sorts in the same order as a recursive Merge Sort, but
using iteration and a tiny stack. This is done to improve performance,
which is quite significant in this case (bottom-up merge sort trashes the
cache too much).
When using Total Commander with a virtual database fs and an expand happens
with around 450,000 items, it takes roughly 1.2 seconds on my CPU and 2
seconds on my older Core 2 Quad. Profiling shows that about 70% of the time
is spent enumerating (and sorting), with the rest 30% just populating the
listbox on the large expand, and it's way worse with a simple iterative
Merge Sort, because it is very bad for the CPU's cache.
Compared to a straight iterative bottom-up Merge Sort, it is at least 25%
faster, and even more on older CPU with less cache. Compared with glibc's
qsort (which also happens to be a merge sort on my setup) it is roughly 13%
faster, which is a nice gain. But regardless, qsort can't be used since
there's no guarantee it's a merge sort (and stable sort), it was just done
for performance comparison purposes.
The remaining 30%-40% time wasted on populating the listbox can be eliminated
completely but that will happen in the future, not in this patch series,
as LBS_NODATA for listboxes will have to be implemented first. This would
reduce the time in this context from around 1 second to 0.6-0.7 seconds,
which is much more manageable in my book.
dlls/shell32/autocomplete.c | 230 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 230 insertions(+)
diff --git a/dlls/shell32/autocomplete.c b/dlls/shell32/autocomplete.c
index dfe7638..ee3a6be 100644
--- a/dlls/shell32/autocomplete.c
+++ b/dlls/shell32/autocomplete.c
@@ -33,6 +33,7 @@
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
+#include <limits.h>
#define COBJMACROS
@@ -62,6 +63,8 @@ typedef struct
LONG ref;
BOOL initialized;
BOOL enabled;
+ UINT enum_strs_num;
+ WCHAR **enum_strs;
HWND hwndEdit;
HWND hwndListBox;
WNDPROC wpOrigEditProc;
@@ -103,10 +106,236 @@ static void set_text_and_selection(IAutoCompleteImpl *ac, HWND hwnd, WCHAR *text
CallWindowProcW(proc, hwnd, EM_SETSEL, start, end);
}
+static BOOL sort_strs_excluding_pairs(WCHAR **strs, UINT numstrs)
+{
+ /*
+ Merge Sort the strings iteratively (excluding pairs, which are assumed sorted already),
+ using a stack instead of bottom-up mergesort, because the latter is cache unfriendly.
+
+ The largest stack possible for a 32-bit UINT input (in terms of elements) looks like:
+
+ 0, 31, 30, 29, ... , 1 (because we exclude pairs so we stop at 1)
+
+ The initial 0 is the first stack slot which is special and must always compare false
+ */
+ WCHAR **tmp;
+ BYTE stack[1 /* first special slot */ + (sizeof(UINT) * CHAR_BIT - 1)], w;
+ UINT a, top;
+
+ if (numstrs <= 2) return TRUE;
+ if (!(tmp = heap_alloc(numstrs * sizeof(*tmp)))) return FALSE;
+
+ stack[0] = 0;
+ top = 0;
+
+ /* w contains the log2 (degree) of the width; i.e. width is 1 << w */
+ w = 1;
+
+ for (a = 0;;)
+ {
+ UINT b = a + (1 << w), i = a, j = b, end = min(b + (1 << w), numstrs);
+ WCHAR **p = tmp;
+ for (;;)
+ {
+ if (strcmpiW(strs[i], strs[j]) <= 0)
+ {
+ *p++ = strs[i++];
+ if (i == b) break;
+ }
+ else
+ {
+ *p++ = strs[j++];
+ if (j == end)
+ {
+ /* Copy them in reverse since i < dst */
+ UINT dst = a + p - tmp, k = b - i;
+ do strs[dst + k - 1] = strs[i + k - 1]; while (--k);
+ break;
+ }
+ }
+ }
+ memcpy(&strs[a], tmp, (p - tmp) * sizeof(*strs));
+
+ /* If the top is the same width as our current one, sort them as a block */
+ if (w == stack[top])
+ {
+ top--;
+ w++;
+ a -= 1 << w;
+ continue;
+ }
+
+ /* Otherwise push it and start from the smallest width for the next block */
+ if (end + 2 < numstrs)
+ {
+ stack[++top] = w;
+ a = end;
+ w = 1;
+ continue;
+ }
+
+ /* If there's no next block at all, sort it with double the top width */
+ if (end == numstrs)
+ {
+ if (top == 0)
+ break;
+ w = stack[top--] + 1;
+ a -= 1 << w;
+ continue;
+ }
+
+ /* Otherwise we have a partial block, merge it into the current block */
+ w++;
+ }
+
+ heap_free(tmp);
+ return TRUE;
+}
+
+static void enumerate_strings(IAutoCompleteImpl *ac)
+{
+ /*
+ Enumerate all of the strings and sort them in the internal list. Rough summary:
+
+ - Enumerate the strings and place their addresses in a chain of blocks (stack-like)
+ - Sort pairs from the chain of blocks into a contiguous array of pointers to them
+ - Merge Sort the contiguous array/list (excluding pairs, since it's already done)
+
+ We don't free the enumerated strings (except on error) to avoid needless
+ copies, until the next reset (or the object itself is destroyed)
+ */
+ struct
+ {
+ void *prev;
+ LPOLESTR str[511 * 2]; /* this must be kept *even* */
+ } *prevblock, *curblock;
+
+ UINT i, cur, numstrs = 0;
+ LPOLESTR *strs;
+
+ prevblock = NULL;
+ for (;;)
+ {
+ LONG rem;
+ if ((curblock = heap_alloc(sizeof(*curblock))) == NULL)
+ {
+ if (!prevblock)
+ return;
+ curblock = prevblock;
+ cur = ARRAY_SIZE(curblock->str);
+ goto fail_and_free_blocks;
+ }
+ curblock->prev = prevblock;
+ rem = ARRAY_SIZE(curblock->str);
+
+ while (rem > 0)
+ {
+ ULONG n = 0;
+ cur = ARRAY_SIZE(curblock->str) - rem;
+ IEnumString_Next(ac->enumstr, rem, &curblock->str[cur], &n);
+ if (n == 0)
+ goto break_from_enumeration;
+ rem -= n;
+ }
+ prevblock = curblock;
+ numstrs += ARRAY_SIZE(curblock->str);
+ }
+
+break_from_enumeration:
+ /* Allocate even if there were zero strings enumerated, to mark it non-NULL */
+ numstrs += cur;
+ if (!(strs = heap_alloc(numstrs * sizeof(*strs))))
+ {
+ fail_and_free_blocks:
+ do
+ {
+ LPOLESTR *str = curblock->str;
+ while (cur--)
+ CoTaskMemFree(str[cur]);
+ prevblock = curblock->prev;
+ heap_free(curblock);
+ curblock = prevblock;
+ cur = ARRAY_SIZE(curblock->str);
+ } while (curblock);
+ return;
+ }
+ if (numstrs == 0)
+ {
+ ac->enum_strs = strs;
+ ac->enum_strs_num = numstrs;
+ heap_free(curblock);
+ return;
+ }
+
+ /* Start by sorting pairs from the blocks into the contiguous list */
+ i = numstrs;
+ if (numstrs % 2)
+ strs[--i] = curblock->str[--cur];
+ do
+ {
+ while (cur)
+ {
+ WCHAR *a = curblock->str[cur - 2], *b = curblock->str[cur - 1], *c;
+ if (strcmpiW(a, b) > 0)
+ c = a, a = b, b = c;
+ strs[i - 2] = a;
+ strs[i - 1] = b;
+ i -= 2;
+ cur -= 2;
+ }
+ prevblock = curblock->prev;
+ heap_free(curblock);
+ curblock = prevblock;
+ cur = ARRAY_SIZE(curblock->str);
+ } while (curblock);
+
+ /* Now sort the rest of the list */
+ if (!sort_strs_excluding_pairs(strs, numstrs))
+ {
+ do
+ CoTaskMemFree(strs[--numstrs]);
+ while (numstrs);
+ heap_free(strs);
+ return;
+ }
+
+ ac->enum_strs = strs;
+ ac->enum_strs_num = numstrs;
+}
+
+static UINT find_first_matching_enum_str(IAutoCompleteImpl *ac, WCHAR *text, UINT len)
+{
+ WCHAR **strs = ac->enum_strs;
+ UINT index = ~0, a = 0, b = ac->enum_strs_num;
+ while (a < b)
+ {
+ UINT i = (a + b - 1) / 2;
+ int cmp = strncmpiW(text, strs[i], len);
+ if (cmp == 0) index = i;
+ if (cmp <= 0) b = i;
+ else a = i + 1;
+ }
+ return index;
+}
+
+static void free_enum_strs(IAutoCompleteImpl *ac)
+{
+ WCHAR **strs = ac->enum_strs;
+ if (strs)
+ {
+ UINT i = ac->enum_strs_num;
+ ac->enum_strs = NULL;
+ while (i--)
+ CoTaskMemFree(strs[i]);
+ heap_free(strs);
+ }
+}
+
static void hide_listbox(IAutoCompleteImpl *ac, HWND hwnd)
{
ShowWindow(hwnd, SW_HIDE);
SendMessageW(hwnd, LB_RESETCONTENT, 0, 0);
+ free_enum_strs(ac);
}
static size_t format_quick_complete(WCHAR *dst, const WCHAR *qc, const WCHAR *str, size_t str_len)
@@ -386,6 +615,7 @@ static void autocomplete_text(IAutoCompleteImpl *ac, HWND hwnd, enum autoappend_
static void destroy_autocomplete_object(IAutoCompleteImpl *ac)
{
ac->hwndEdit = NULL;
+ free_enum_strs(ac);
if (ac->hwndListBox)
DestroyWindow(ac->hwndListBox);
IAutoComplete2_Release(&ac->IAutoComplete2_iface);
--
1.9.1
2
11
Signed-off-by: Jactry Zeng <jzeng(a)codeweavers.com>
---
dlls/kernel32/process.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c
index 32e751719e..799519e1ac 100644
--- a/dlls/kernel32/process.c
+++ b/dlls/kernel32/process.c
@@ -2146,7 +2146,7 @@ static NTSTATUS exec_loader( const RTL_USER_PROCESS_PARAMETERS *params, int sock
wine_exec_wine_binary( loader, argv, getenv("WINELOADER") );
}
#ifdef __APPLE__
- while (errno == ENOTSUP && exec_only && terminate_main_thread());
+ while (errno == ENOTSUP && terminate_main_thread());
#else
while (0);
#endif
--
2.15.2 (Apple Git-101.1)
2
1