Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- 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
June 2018
- 68 participants
- 1149 messages
[PATCH v4] msvcrt: Use already existent oneexit_table functions for _onexit and _c_exit
by Piotr Caban
From: Fabian Maurer <dark.shadow4(a)web.de>
Signed-off-by: Fabian Maurer <dark.shadow4(a)web.de>
Signed-off-by: Piotr Caban <piotr(a)codeweavers.com>
v4:
- don't use __MSVCRT_ prefix for internal functions
- simplified atexit functions order test
---
dlls/msvcrt/exit.c | 201
+++++++++++++++++++++------------------------
dlls/ucrtbase/tests/misc.c | 56 ++++++++++++-
2 files changed, 149 insertions(+), 108 deletions(-)
June 23, 2018
[PATCH v2 2/2] wined3d: Add new test for DXTn volume textures.
by Connor McAdams
To properly test the functionality of DXTn volume textures, I have added
new tests for DXT1, DXT3, and DXT5 replacing the old DXT5 test. I also
check for alpha values, which the previous test did not do.
Signed-off-by: Connor McAdams <conmanx360(a)gmail.com>
---
dlls/d3d9/tests/visual.c | 183 +++++++++++++++++++++++++++++++----------------
1 file changed, 123 insertions(+), 60 deletions(-)
diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c
index b36c189..29fd27b 100644
--- a/dlls/d3d9/tests/visual.c
+++ b/dlls/d3d9/tests/visual.c
@@ -17741,26 +17741,73 @@ done:
DestroyWindow(window);
}
-static void volume_dxt5_test(void)
+static void volume_dxtn_test(void)
{
IDirect3DVolumeTexture9 *texture;
IDirect3DDevice9 *device;
D3DLOCKED_BOX box;
IDirect3D9 *d3d;
- unsigned int i;
+ struct surface_readback rb;
+ IDirect3DSurface9 *rt;
+ DWORD i, x;
ULONG refcount;
DWORD color;
HWND window;
HRESULT hr;
- static const char texture_data[] =
+ static const BYTE dxt1_texture_data[] =
+ {
+ 0x00, 0xF8, 0x00, 0xF8, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xE0, 0x07, 0xE0, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0x1F, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00
+ };
+ static const BYTE dxt3_texture_data[] =
+ {
+ 0xFF, 0xEE, 0xFF, 0xEE, 0xFF, 0xEE, 0xFF, 0xEE, 0x00, 0xf8, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xDD, 0xFF, 0xDD, 0xFF, 0xDD, 0xFF, 0xDD, 0xe0, 0x07, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xCC, 0xFF, 0xCC, 0xFF, 0xCC, 0xFF, 0xCC, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xBB, 0xFF, 0xBB, 0xFF, 0xBB, 0xFF, 0xBB, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00
+ };
+ static const BYTE dxt5_texture_data[] =
{
/* A 8x4x2 texture consisting of 4 4x4 blocks. The colors of the blocks are red, green, blue and white. */
- 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0x80, 0x0D, 0xD8, 0x80, 0x0D, 0xD8, 0x00, 0xf8, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00
};
+ static const DWORD dxt1_expected_colors[] =
+ {
+ 0xFFFF0000, 0x00000000, 0xFF00FF00, 0xFF00FF00,
+ 0xFF0000FF, 0xFF0000FF, 0xFFFFFFFF, 0xFFFFFFFF,
+ };
+ static const DWORD dxt3_expected_colors[] =
+ {
+ 0xFFFF0000, 0xEEFF0000, 0xFF00FF00, 0xDD00FF00,
+ 0xFF0000FF, 0xCC0000FF, 0xFFFFFFFF, 0xBBFFFFFF,
+ };
+ static const DWORD dxt5_expected_colors[] =
+ {
+ 0xFFFF0000, 0x00FF0000, 0xFF00FF00, 0xFF00FF00,
+ 0xFF0000FF, 0xFF0000FF, 0xFFFFFFFF, 0xFFFFFFFF
+ };
+
+ static const struct
+ {
+ const char *dxtn;
+ const BYTE *tex_data;
+ DWORD tex_size;
+ D3DFORMAT fmt;
+ const DWORD *expected_colors;
+ }
+ dxtn_tex[] =
+ {
+ {"DXT1", dxt1_texture_data, sizeof(dxt1_texture_data), D3DFMT_DXT1, dxt1_expected_colors},
+ {"DXT3", dxt3_texture_data, sizeof(dxt3_texture_data), D3DFMT_DXT3, dxt3_expected_colors},
+ {"DXT5", dxt5_texture_data, sizeof(dxt5_texture_data), D3DFMT_DXT5, dxt5_expected_colors},
+ };
+
static const struct
{
struct vec3 position;
@@ -17778,70 +17825,86 @@ static void volume_dxt5_test(void)
{{ 1.0f, -1.0f, 1.0f}, { 1.0f, 0.0f, 0.75f}},
{{ 1.0f, 1.0f, 1.0f}, { 1.0f, 1.0f, 0.75f}},
};
- static const DWORD expected_colors[] = {0x00ff0000, 0x0000ff00, 0x000000ff, 0x00ffffff};
- window = create_window();
- d3d = Direct3DCreate9(D3D_SDK_VERSION);
- ok(!!d3d, "Failed to create a D3D object.\n");
- if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
- D3DFMT_X8R8G8B8, 0, D3DRTYPE_VOLUMETEXTURE, D3DFMT_DXT5)))
- {
- skip("DXT5 volume textures are not supported, skipping test.\n");
- goto done;
- }
- if (!(device = create_device(d3d, window, window, TRUE)))
+ for (x = 0; x < 3; ++x)
{
- skip("Failed to create a D3D device, skipping tests.\n");
- goto done;
- }
+ window = create_window();
+ d3d = Direct3DCreate9(D3D_SDK_VERSION);
+ ok(!!d3d, "Failed to create a D3D object.\n");
+ if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
+ D3DFMT_A8B8G8R8, 0, D3DRTYPE_VOLUMETEXTURE, dxtn_tex[x].fmt)))
+ {
+ skip("%s volume textures are not supported, skipping test.\n", dxtn_tex[x].dxtn);
+ continue;
+ }
+ if (!(device = create_device(d3d, window, window, TRUE)))
+ {
+ skip("Failed to create a D3D device, skipping tests.\n");
+ continue;
+ }
- hr = IDirect3DDevice9_CreateVolumeTexture(device, 8, 4, 2, 1, 0, D3DFMT_DXT5,
- D3DPOOL_MANAGED, &texture, NULL);
- ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
+ hr = IDirect3DDevice9_CreateVolumeTexture(device, 8, 4, 2, 1, 0, dxtn_tex[x].fmt,
+ D3DPOOL_MANAGED, &texture, NULL);
+ ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
- hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &box, NULL, 0);
- ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
- memcpy(box.pBits, texture_data, sizeof(texture_data));
- hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
- ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
+ hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &box, NULL, 0);
+ ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
+ memcpy(box.pBits, dxtn_tex[x].tex_data, dxtn_tex[x].tex_size);
- hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE3(0));
- ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
- hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
- ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
- hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
- ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
- hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
- ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
- hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
- ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
- hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
- ok(SUCCEEDED(hr), "Failed to set mag filter, hr %#x.\n", hr);
+ hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
+ ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
- hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00ff00ff, 1.0f, 0);
- ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
- hr = IDirect3DDevice9_BeginScene(device);
- ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
- hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[0], sizeof(*quads));
- ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
- hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[4], sizeof(*quads));
- ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
- hr = IDirect3DDevice9_EndScene(device);
- ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
+ hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE3(0));
+ ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
+ hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
+ ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
+ hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+ ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
+ hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
+ hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
+ ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
+ hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
+ ok(SUCCEEDED(hr), "Failed to set mag filter, hr %#x.\n", hr);
- for (i = 0; i < 4; i++)
- {
- color = getPixelColor(device, 80 + 160 * i, 240);
- ok (color_match(color, expected_colors[i], 1),
- "Expected color 0x%08x, got 0x%08x, case %u.\n", expected_colors[i], color, i);
+ hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00ff00ff, 1.0f, 0);
+ ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
+ hr = IDirect3DDevice9_BeginScene(device);
+ ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
+ hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[0], sizeof(*quads));
+ ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
+ hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[4], sizeof(*quads));
+ ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
+ hr = IDirect3DDevice9_EndScene(device);
+ ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
+
+ for (i = 0; i < 8; ++i)
+ {
+ hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt);
+ if(FAILED(hr))
+ {
+ trace("Can't get the render target, hr %#x.\n", hr);
+ color = 0x00000000;
+ }
+ else
+ {
+ get_rt_readback(rt, &rb);
+ color = get_readback_color(&rb, 40 + 80 * i, 240);
+ release_surface_readback(&rb);
+ IDirect3DSurface9_Release(rt);
+ }
+ ok (color_match(color, dxtn_tex[x].expected_colors[i], 1),
+ "Expected color 0x%08x, got 0x%08x, case %u.\n", dxtn_tex[x].expected_colors[i], color, i);
+ }
+
+ hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
+ ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr);
+ IDirect3DVolumeTexture9_Release(texture);
+
+ refcount = IDirect3DDevice9_Release(device);
+ ok(!refcount, "Device has %u references left.\n", refcount);
}
- hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
- ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr);
- IDirect3DVolumeTexture9_Release(texture);
- refcount = IDirect3DDevice9_Release(device);
- ok(!refcount, "Device has %u references left.\n", refcount);
-done:
IDirect3D9_Release(d3d);
DestroyWindow(window);
}
@@ -24131,7 +24194,7 @@ START_TEST(visual)
zenable_test();
fog_special_test();
volume_srgb_test();
- volume_dxt5_test();
+ volume_dxtn_test();
add_dirty_rect_test();
multisampled_depth_buffer_test();
resz_test();
--
2.7.4
June 22, 2018
[PATCH v2 1/2] wined3d: Add decompression functions for DXT1, DXT3, and DXT5
by Connor McAdams
This adds decompression functions for DXT1, DXT3, and DXT5 formats,
which covers all the possible DXT formats. These are used for
decompressing DXTn volume textures, and converting them to b8g8r8a8.
This patch also makes sure only 3D DXTn textures are uploaded by
performing a check in the wined3d_texture_upload_data function.
Signed-off-by: Connor McAdams <conmanx360(a)gmail.com>
---
dlls/wined3d/texture.c | 26 ++++
dlls/wined3d/utils.c | 323 ++++++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 333 insertions(+), 16 deletions(-)
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index c316906..a998b9c 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -1948,6 +1948,32 @@ void wined3d_texture_upload_data(struct wined3d_texture *texture, unsigned int s
bo.addr += src_box->left * format->byte_count;
}
+ if (format->id == WINED3DFMT_DXT5 || format->id == WINED3DFMT_DXT4 ||
+ format->id == WINED3DFMT_DXT3 || format->id == WINED3DFMT_DXT2 ||
+ format->id == WINED3DFMT_DXT1)
+ {
+ if (target == GL_TEXTURE_3D)
+ {
+ struct wined3d_format temp;
+
+ f = *format;
+ temp.upload = f.upload;
+ format = &f;
+ format = wined3d_get_format(gl_info, WINED3DFMT_B8G8R8A8_UNORM, WINED3DUSAGE_TEXTURE);
+ f = *format;
+ f.upload = temp.upload;
+ f.conv_byte_count = 4;
+ format = &f;
+ texture->resource.format_flags &= ~WINED3DFMT_FLAG_BLOCKS;
+ }
+ else
+ {
+ f = *format;
+ f.upload = NULL;
+ format = &f;
+ }
+ }
+
if (format->upload)
{
unsigned int dst_row_pitch, dst_slice_pitch;
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index 937c1bc..719f23e 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -840,6 +840,307 @@ static void convert_s8_uint_d24_float(const BYTE *src, BYTE *dst, UINT src_row_p
}
}
+static void dxt5_decompress_block(const BYTE *src, BYTE *dst, UINT width, UINT height, UINT depth,
+ UINT x_pos, UINT y_pos, UINT z_pos, UINT dst_slice_pitch, UINT64 cur_block)
+{
+ UINT64 alpha_block, alpha_index, color_block, color_index;
+ const UINT64 *source;
+ DWORD *dest;
+ DWORD alpha_lookup;
+ DWORD bgra;
+ DWORD temp;
+ DWORD i, x, y;
+ WORD color[2];
+ BYTE alpha_val, color_val;
+ BYTE alpha[8];
+ BYTE r[4];
+ BYTE g[4];
+ BYTE b[4];
+
+ source = (const UINT64 *)(src + cur_block * 16);
+ alpha_block = source[0];
+ color_block = source[1];
+
+ alpha[0] = alpha_block & 0xff;
+ alpha[1] = (alpha_block >> 8) & 0xff;
+
+ if (alpha[0] > alpha[1])
+ {
+ for (i = 0; i < 6; ++i)
+ alpha[2 + i] = (((6 - i) * alpha[0]) + ((1 + i) * alpha[1])) / 7;
+ }
+ else if (alpha[0] <= alpha[1])
+ {
+ for (i = 0; i < 4; ++i)
+ alpha[2 + i] = (((4 - i) * alpha[0]) + ((1 + i) * alpha[1])) / 5;
+ alpha[6] = 0;
+ alpha[7] = 255;
+ }
+
+ color[0] = color_block & 0xffff;
+ color[1] = (color_block >> 16) & 0xffff;
+
+ for (i = 0; i < 2; ++i)
+ {
+ temp = (color[i] >> 11) * 255 + 16;
+ r[i] = (temp / 32 + temp) / 32;
+ temp = ((color[i] >> 5) & 0x3f) * 255 + 32;
+ g[i] = (temp / 64 + temp) / 64;
+ temp = (color[i] & 0x1f) * 255 + 16;
+ b[i] = (temp / 32 + temp) / 32;
+ }
+
+ for (i = 0; i < 2; ++i)
+ {
+ r[2 + i] = (2 * r[0 + i] + r[1 - i]) / 3;
+ g[2 + i] = (2 * g[0 + i] + g[1 - i]) / 3;
+ b[2 + i] = (2 * b[0 + i] + b[1 - i]) / 3;
+ }
+
+ color_index = (color_block >> 32) & 0xffffffff;
+ alpha_index = (alpha_block >> 16);
+
+ dest = (DWORD *)(dst + z_pos * dst_slice_pitch);
+
+ for (y = 0; y < 4; ++y)
+ {
+ if (y_pos + y >= height)
+ break;
+ for (x = 0; x < 4; ++x)
+ {
+ if (x_pos + x >= width)
+ break;
+
+ color_val = 0;
+ alpha_val = 0;
+ bgra = 0;
+
+ color_val = (color_index >> (y * 8));
+ color_val = (color_val >> (x * 2)) & 0x3;
+ alpha_lookup = (alpha_index >> (y * 12)) & 0xfff;
+ alpha_val = (alpha_lookup >> (x * 3)) & 0x7;
+ bgra = ((alpha[alpha_val] << 24) | (r[color_val] << 16) | (g[color_val] << 8) | b[color_val]);
+ dest[(y_pos + y) * width + (x_pos + x)] = bgra;
+ }
+ }
+}
+
+static void convert_dxt5_b8g8r8a8_unorm(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
+ UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
+{
+ UINT64 current_block;
+ DWORD x, y, z;
+
+ current_block = 0;
+
+ for (z = 0; z < depth; ++z)
+ {
+ for (y = 0; y < height; y += 4)
+ {
+ for (x = 0; x < width; x += 4)
+ {
+ dxt5_decompress_block(src, dst, width, height, depth, x, y, z, dst_slice_pitch, current_block);
+ current_block++;
+ }
+ }
+ }
+}
+
+static void dxt3_decompress_block(const BYTE *src, BYTE *dst, UINT width, UINT height, UINT depth,
+ UINT x_pos, UINT y_pos, UINT z_pos, UINT dst_slice_pitch, UINT64 cur_block)
+{
+ UINT64 alpha_block, alpha_lookup, color_block, color_index;
+ const UINT64 *source;
+ DWORD *dest;
+ DWORD bgra;
+ DWORD temp;
+ DWORD i, x, y;
+ WORD color[2];
+ BYTE alpha_val, color_val;
+ BYTE r[4];
+ BYTE g[4];
+ BYTE b[4];
+
+ source = (const UINT64 *)(src + cur_block * 16);
+ alpha_block = source[0];
+ color_block = source[1];
+
+ color[0] = color_block & 0xffff;
+ color[1] = (color_block >> 16) & 0xffff;
+
+ for (i = 0; i < 2; ++i)
+ {
+ temp = (color[i] >> 11) * 255 + 16;
+ r[i] = (temp / 32 + temp) / 32;
+ temp = ((color[i] >> 5) & 0x3f) * 255 + 32;
+ g[i] = (temp / 64 + temp) / 64;
+ temp = (color[i] & 0x1f) * 255 + 16;
+ b[i] = (temp / 32 + temp) / 32;
+ }
+
+ for (i = 0; i < 2; ++i)
+ {
+ r[2 + i] = (2 * r[0 + i] + r[1 - i]) / 3;
+ g[2 + i] = (2 * g[0 + i] + g[1 - i]) / 3;
+ b[2 + i] = (2 * b[0 + i] + b[1 - i]) / 3;
+ }
+
+ color_index = (color_block >> 32) & 0xffffffff;
+ dest = (DWORD *)(dst + z_pos * dst_slice_pitch);
+
+ for (y = 0; y < 4; ++y)
+ {
+ if (y_pos + y >= height)
+ break;
+ for (x = 0; x < 4; ++x)
+ {
+ if (x_pos + x >= width)
+ break;
+
+ color_val = 0;
+ alpha_val = 0;
+ bgra = 0;
+
+ color_val = (color_index >> (y * 8));
+ color_val = (color_val >> (x * 2)) & 0x3;
+
+ alpha_lookup = (alpha_block >> (y * 16)) & 0xffff;
+ alpha_val = (alpha_lookup >> (x * 4)) & 0xf;
+ temp = alpha_val * 255 + 8;
+ alpha_val = (temp / 16 + temp) / 16;
+
+ bgra = ((alpha_val << 24) | (r[color_val] << 16) | (g[color_val] << 8) | b[color_val]);
+ dest[(y_pos + y) * width + (x_pos + x)] = bgra;
+ }
+ }
+}
+
+static void convert_dxt3_b8g8r8a8_unorm(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
+ UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
+{
+ UINT64 current_block;
+ DWORD x, y, z;
+
+ current_block = 0;
+
+ for (z = 0; z < depth; ++z)
+ {
+ for (y = 0; y < height; y += 4)
+ {
+ for (x = 0; x < width; x += 4)
+ {
+ dxt3_decompress_block(src, dst, width, height, depth, x, y, z, dst_slice_pitch, current_block);
+ current_block++;
+ }
+ }
+ }
+}
+
+static void dxt1_decompress_block(const BYTE *src, BYTE *dst, UINT width, UINT height, UINT depth,
+ UINT x_pos, UINT y_pos, UINT z_pos, UINT dst_slice_pitch, UINT64 cur_block)
+{
+ UINT64 color_block, color_index;
+ const UINT64 *source;
+ DWORD *dest;
+ DWORD bgra;
+ DWORD temp;
+ DWORD i, x, y;
+ WORD color[2];
+ BYTE color_val;
+ BYTE alpha;
+ BYTE r[4];
+ BYTE g[4];
+ BYTE b[4];
+ BYTE use_alpha;
+
+ source = (const UINT64 *)(src + cur_block * 8);
+ color_block = source[0];
+
+ color[0] = color_block & 0xffff;
+ color[1] = (color_block >> 16) & 0xffff;
+
+ for (i = 0; i < 2; ++i)
+ {
+ temp = (color[i] >> 11) * 255 + 16;
+ r[i] = (temp / 32 + temp) / 32;
+ temp = ((color[i] >> 5) & 0x3f) * 255 + 32;
+ g[i] = (temp / 64 + temp) / 64;
+ temp = (color[i] & 0x1f) * 255 + 16;
+ b[i] = (temp / 32 + temp) / 32;
+ }
+
+ if (color[0] > color[1])
+ {
+ for (i = 0; i < 2; ++i)
+ {
+ r[2 + i] = (2 * r[0 + i] + r[1 - i]) / 3;
+ g[2 + i] = (2 * g[0 + i] + g[1 - i]) / 3;
+ b[2 + i] = (2 * b[0 + i] + b[1 - i]) / 3;
+ }
+ use_alpha = 0;
+ }
+ else if (color[0] <= color[1])
+ {
+ r[2] = (r[0] + r[1]) / 2;
+ g[2] = (g[0] + g[1]) / 2;
+ b[2] = (b[0] + b[1]) / 2;
+
+ r[3] = 0;
+ g[3] = 0;
+ b[3] = 0;
+
+ use_alpha = 1;
+ }
+
+ color_index = (color_block >> 32) & 0xffffffff;
+ dest = (DWORD *)(dst + z_pos * dst_slice_pitch);
+
+ for (y = 0; y < 4; ++y)
+ {
+ if (y_pos + y >= height)
+ break;
+ for (x = 0; x < 4; ++x)
+ {
+ if (x_pos + x >= width)
+ break;
+
+ color_val = 0;
+ bgra = 0;
+
+ color_val = (color_index >> (y * 8));
+ color_val = (color_val >> (x * 2)) & 0x3;
+ if (color_val == 3 && use_alpha == 1)
+ alpha = 0;
+ else
+ alpha = 255;
+
+ bgra = ((alpha << 24) | (r[color_val] << 16) | (g[color_val] << 8) | b[color_val]);
+ dest[(y_pos + y) * width + (x_pos + x)] = bgra;
+ }
+ }
+}
+
+static void convert_dxt1_b8g8r8a8_unorm(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
+ UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
+{
+ UINT64 current_block;
+ DWORD x, y, z;
+
+ current_block = 0;
+
+ for (z = 0; z < depth; ++z)
+ {
+ for (y = 0; y < height; y += 4)
+ {
+ for (x = 0; x < width; x += 4)
+ {
+ dxt1_decompress_block(src, dst, width, height, depth, x, y, z, dst_slice_pitch, current_block);
+ current_block++;
+ }
+ }
+ }
+}
+
static void x8_d24_unorm_upload(const BYTE *src, BYTE *dst,
unsigned int src_row_pitch, unsigned int src_slice_pitch,
unsigned int dst_row_pitch, unsigned int dst_slice_pitch,
@@ -1118,27 +1419,27 @@ static const struct wined3d_format_texture_info format_texture_info[] =
GL_RGBA, GL_UNSIGNED_BYTE, 0,
WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
| WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_COMPRESSED,
- EXT_TEXTURE_COMPRESSION_S3TC, NULL},
+ EXT_TEXTURE_COMPRESSION_S3TC, convert_dxt1_b8g8r8a8_unorm},
{WINED3DFMT_DXT2, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 0,
GL_RGBA, GL_UNSIGNED_BYTE, 0,
WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
| WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_COMPRESSED,
- EXT_TEXTURE_COMPRESSION_S3TC, NULL},
+ EXT_TEXTURE_COMPRESSION_S3TC, convert_dxt3_b8g8r8a8_unorm},
{WINED3DFMT_DXT3, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 0,
GL_RGBA, GL_UNSIGNED_BYTE, 0,
WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
| WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_COMPRESSED,
- EXT_TEXTURE_COMPRESSION_S3TC, NULL},
+ EXT_TEXTURE_COMPRESSION_S3TC, convert_dxt3_b8g8r8a8_unorm},
{WINED3DFMT_DXT4, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 0,
GL_RGBA, GL_UNSIGNED_BYTE, 0,
WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
| WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_COMPRESSED,
- EXT_TEXTURE_COMPRESSION_S3TC, NULL},
+ EXT_TEXTURE_COMPRESSION_S3TC, convert_dxt5_b8g8r8a8_unorm},
{WINED3DFMT_DXT5, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 0,
GL_RGBA, GL_UNSIGNED_BYTE, 0,
WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
| WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_COMPRESSED,
- EXT_TEXTURE_COMPRESSION_S3TC, NULL},
+ EXT_TEXTURE_COMPRESSION_S3TC, convert_dxt5_b8g8r8a8_unorm},
{WINED3DFMT_BC1_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 0,
GL_RGBA, GL_UNSIGNED_BYTE, 0,
WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
@@ -3394,17 +3695,7 @@ static void apply_format_fixups(struct wined3d_adapter *adapter, struct wined3d_
* for dx9 GPUs support it, some do not, so not supporting DXTn volumes is OK for d3d9.
*
* Note that GL_NV_texture_compression_vtc adds this functionality to OpenGL, but the
- * block layout is not compatible with the one used by d3d. See volume_dxt5_test. */
- idx = get_format_idx(WINED3DFMT_DXT1);
- gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
- idx = get_format_idx(WINED3DFMT_DXT2);
- gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
- idx = get_format_idx(WINED3DFMT_DXT3);
- gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
- idx = get_format_idx(WINED3DFMT_DXT4);
- gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
- idx = get_format_idx(WINED3DFMT_DXT5);
- gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
+ * block layout is not compatible with the one used by d3d. See volume_dxtn_test. */
idx = get_format_idx(WINED3DFMT_BC1_UNORM);
gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
idx = get_format_idx(WINED3DFMT_BC1_UNORM_SRGB);
--
2.7.4
June 22, 2018
[PATCH v2 0/2] wined3d: Add DXTn Volume Texture Support
by Connor McAdams
This patchset adds support for DXTn volume textures by using the CPU to
decompress and convert them into a format the GPU can handle. It only
decompresses DXTn volume textures, and leaves regular 2D DXTn textures
alone.
Connor McAdams (2):
wined3d: Add decompression functions for DXT1, DXT3, and DXT5
wined3d: Add new test for DXTn volume textures.
dlls/d3d9/tests/visual.c | 183 ++++++++++++++++++---------
dlls/wined3d/texture.c | 26 ++++
dlls/wined3d/utils.c | 323 ++++++++++++++++++++++++++++++++++++++++++++---
3 files changed, 456 insertions(+), 76 deletions(-)
--
2.7.4
June 22, 2018
Re: [PATCH 3/4] shell32/tests: Add tests for SHGetKnownFolderPath() flags.
by Fabian Maurer
While probably not very relevant, when doing something like
----------
SHSetKnownFolderPath(&FOLDERID_SavedGames, KF_FLAG_DONT_UNEXPAND,
NULL, new_path);
SHGetKnownFolderPath(&FOLDERID_SavedGames, KF_FLAG_DONT_UNEXPAND, 0,
&path2);
----------
then KF_FLAG_DONT_UNEXPAND still doesn't seem to do anything.I figured that's
where the flag was useful, but it is completely ignored.
Do we want a testcase for that too?
Regards,
Fabian Maurer
June 22, 2018
[PATCH v3] msvcrt: Use already existent oneexit_table functions for _onexit and _c_exit
by Fabian Maurer
For that to work, MSVCRT__register_onexit_function and
MSVCRT__execute_onexit_table have to available all the time,
not only when _MSVCR_VER>=140
tests based on code by Piotr Caban
v2:
Create exit_event2 in test function, so it exists in child process
v3:
Keep exitlock
Keep _MSVCR_VER>=140 functions _MSVCR_VER>=140
Signed-off-by: Fabian Maurer <dark.shadow4(a)web.de>
---
dlls/msvcrt/exit.c | 195 ++++++++++++++++++-------------------
dlls/ucrtbase/tests/misc.c | 74 +++++++++++++-
2 files changed, 166 insertions(+), 103 deletions(-)
diff --git a/dlls/msvcrt/exit.c b/dlls/msvcrt/exit.c
index 7e1805569c4..602a80a0513 100644
--- a/dlls/msvcrt/exit.c
+++ b/dlls/msvcrt/exit.c
@@ -29,9 +29,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
#define LOCK_EXIT _mlock(_EXIT_LOCK1)
#define UNLOCK_EXIT _munlock(_EXIT_LOCK1)
-static MSVCRT__onexit_t *MSVCRT_atexit_table = NULL;
-static int MSVCRT_atexit_table_size = 0;
-static int MSVCRT_atexit_registered = 0; /* Points to free slot */
static MSVCRT_purecall_handler purecall_handler = NULL;
typedef struct MSVCRT__onexit_table_t
@@ -41,6 +38,8 @@ typedef struct MSVCRT__onexit_table_t
MSVCRT__onexit_t *_end;
} MSVCRT__onexit_table_t;
+static MSVCRT__onexit_table_t MSVCRT_atexit_table;
+
typedef void (__stdcall *_tls_callback_type)(void*,ULONG,void*);
static _tls_callback_type tls_atexit_callback;
@@ -61,21 +60,97 @@ static int MSVCRT_error_mode = MSVCRT__OUT_TO_DEFAULT;
void (*CDECL _aexit_rtn)(int) = MSVCRT__exit;
+static int __MSVCRT__initialize_onexit_table(MSVCRT__onexit_table_t *table)
+{
+ if (!table)
+ return -1;
+
+ if (table->_first == table->_end)
+ table->_last = table->_end = table->_first = NULL;
+ return 0;
+}
+
+
+/* INTERNAL: register onexit function */
+static int __MSVCRT__register_onexit_function(MSVCRT__onexit_table_t *table, MSVCRT__onexit_t func)
+{
+ if (!table)
+ return -1;
+
+ EnterCriticalSection(&MSVCRT_onexit_cs);
+ if (!table->_first)
+ {
+ table->_first = MSVCRT_calloc(32, sizeof(void *));
+ if (!table->_first)
+ {
+ WARN("failed to allocate initial table.\n");
+ LeaveCriticalSection(&MSVCRT_onexit_cs);
+ return -1;
+ }
+ table->_last = table->_first;
+ table->_end = table->_first + 32;
+ }
+
+ /* grow if full */
+ if (table->_last == table->_end)
+ {
+ int len = table->_end - table->_first;
+ MSVCRT__onexit_t *tmp = MSVCRT_realloc(table->_first, 2 * len * sizeof(void *));
+ if (!tmp)
+ {
+ WARN("failed to grow table.\n");
+ LeaveCriticalSection(&MSVCRT_onexit_cs);
+ return -1;
+ }
+ table->_first = tmp;
+ table->_end = table->_first + 2 * len;
+ table->_last = table->_first + len;
+ }
+
+ *table->_last = func;
+ table->_last++;
+ LeaveCriticalSection(&MSVCRT_onexit_cs);
+ return 0;
+}
+
+/* INTERNAL: call onexit functions */
+static int __MSVCRT__execute_onexit_table(MSVCRT__onexit_table_t *table)
+{
+ MSVCRT__onexit_t *func;
+ MSVCRT__onexit_table_t copy;
+
+ if (!table)
+ return -1;
+
+ EnterCriticalSection(&MSVCRT_onexit_cs);
+ if (!table->_first || table->_first >= table->_last)
+ {
+ LeaveCriticalSection(&MSVCRT_onexit_cs);
+ return 0;
+ }
+ copy._first = table->_first;
+ copy._last = table->_last;
+ copy._end = table->_end;
+ memset(table, 0, sizeof(*table));
+ __MSVCRT__initialize_onexit_table(table);
+ LeaveCriticalSection(&MSVCRT_onexit_cs);
+
+ for (func = copy._last - 1; func >= copy._first; func--)
+ {
+ if (*func)
+ (*func)();
+ }
+
+ MSVCRT_free(copy._first);
+ return 0;
+}
+
/* INTERNAL: call atexit functions */
static void __MSVCRT__call_atexit(void)
{
/* Note: should only be called with the exit lock held */
- TRACE("%d atext functions to call\n", MSVCRT_atexit_registered);
if (tls_atexit_callback) tls_atexit_callback(NULL, DLL_PROCESS_DETACH, NULL);
- /* Last registered gets executed first */
- while (MSVCRT_atexit_registered > 0)
- {
- MSVCRT_atexit_registered--;
- TRACE("next is %p\n",MSVCRT_atexit_table[MSVCRT_atexit_registered]);
- if (MSVCRT_atexit_table[MSVCRT_atexit_registered])
- (*MSVCRT_atexit_table[MSVCRT_atexit_registered])();
- TRACE("returned\n");
- }
+ __MSVCRT__execute_onexit_table(&MSVCRT_atexit_table);
}
/*********************************************************************
@@ -292,25 +367,9 @@ MSVCRT__onexit_t CDECL MSVCRT__onexit(MSVCRT__onexit_t func)
return NULL;
LOCK_EXIT;
- if (MSVCRT_atexit_registered > MSVCRT_atexit_table_size - 1)
- {
- MSVCRT__onexit_t *newtable;
- TRACE("expanding table\n");
- newtable = MSVCRT_calloc(MSVCRT_atexit_table_size + 32, sizeof(void *));
- if (!newtable)
- {
- TRACE("failed!\n");
- UNLOCK_EXIT;
- return NULL;
- }
- memcpy (newtable, MSVCRT_atexit_table, MSVCRT_atexit_table_size*sizeof(void *));
- MSVCRT_atexit_table_size += 32;
- MSVCRT_free (MSVCRT_atexit_table);
- MSVCRT_atexit_table = newtable;
- }
- MSVCRT_atexit_table[MSVCRT_atexit_registered] = func;
- MSVCRT_atexit_registered++;
+ __MSVCRT__register_onexit_function(&MSVCRT_atexit_table, func);
UNLOCK_EXIT;
+
return func;
}
@@ -359,7 +418,6 @@ int CDECL MSVCRT__crt_atexit(void (*func)(void))
return MSVCRT__onexit((MSVCRT__onexit_t)func) == (MSVCRT__onexit_t)func ? 0 : -1;
}
-
/*********************************************************************
* _initialize_onexit_table (UCRTBASE.@)
*/
@@ -367,12 +425,7 @@ int CDECL MSVCRT__initialize_onexit_table(MSVCRT__onexit_table_t *table)
{
TRACE("(%p)\n", table);
- if (!table)
- return -1;
-
- if (table->_first == table->_end)
- table->_last = table->_end = table->_first = NULL;
- return 0;
+ return __MSVCRT__initialize_onexit_table(table);
}
/*********************************************************************
@@ -382,43 +435,7 @@ int CDECL MSVCRT__register_onexit_function(MSVCRT__onexit_table_t *table, MSVCRT
{
TRACE("(%p %p)\n", table, func);
- if (!table)
- return -1;
-
- EnterCriticalSection(&MSVCRT_onexit_cs);
- if (!table->_first)
- {
- table->_first = MSVCRT_calloc(32, sizeof(void *));
- if (!table->_first)
- {
- WARN("failed to allocate initial table.\n");
- LeaveCriticalSection(&MSVCRT_onexit_cs);
- return -1;
- }
- table->_last = table->_first;
- table->_end = table->_first + 32;
- }
-
- /* grow if full */
- if (table->_last == table->_end)
- {
- int len = table->_end - table->_first;
- MSVCRT__onexit_t *tmp = MSVCRT_realloc(table->_first, 2 * len * sizeof(void *));
- if (!tmp)
- {
- WARN("failed to grow table.\n");
- LeaveCriticalSection(&MSVCRT_onexit_cs);
- return -1;
- }
- table->_first = tmp;
- table->_end = table->_first + 2 * len;
- table->_last = table->_first + len;
- }
-
- *table->_last = func;
- table->_last++;
- LeaveCriticalSection(&MSVCRT_onexit_cs);
- return 0;
+ return __MSVCRT__register_onexit_function(table, func);
}
/*********************************************************************
@@ -426,35 +443,9 @@ int CDECL MSVCRT__register_onexit_function(MSVCRT__onexit_table_t *table, MSVCRT
*/
int CDECL MSVCRT__execute_onexit_table(MSVCRT__onexit_table_t *table)
{
- MSVCRT__onexit_t *func;
- MSVCRT__onexit_table_t copy;
-
TRACE("(%p)\n", table);
- if (!table)
- return -1;
-
- EnterCriticalSection(&MSVCRT_onexit_cs);
- if (!table->_first || table->_first >= table->_last)
- {
- LeaveCriticalSection(&MSVCRT_onexit_cs);
- return 0;
- }
- copy._first = table->_first;
- copy._last = table->_last;
- copy._end = table->_end;
- memset(table, 0, sizeof(*table));
- MSVCRT__initialize_onexit_table(table);
- LeaveCriticalSection(&MSVCRT_onexit_cs);
-
- for (func = copy._last - 1; func >= copy._first; func--)
- {
- if (*func)
- (*func)();
- }
-
- MSVCRT_free(copy._first);
- return 0;
+ return __MSVCRT__execute_onexit_table(table);
}
/*********************************************************************
diff --git a/dlls/ucrtbase/tests/misc.c b/dlls/ucrtbase/tests/misc.c
index 354fab1e940..ed5bb0589c8 100644
--- a/dlls/ucrtbase/tests/misc.c
+++ b/dlls/ucrtbase/tests/misc.c
@@ -125,6 +125,8 @@ static int (CDECL *p_fesetround)(int);
static void (CDECL *p___setusermatherr)(MSVCRT_matherr_func);
static int* (CDECL *p_errno)(void);
static char* (CDECL *p_asctime)(const struct tm *);
+static void (CDECL *p_exit)(int);
+static int (CDECL *p__crt_atexit)(void (CDECL*)(void));
static void test__initialize_onexit_table(void)
{
@@ -429,6 +431,8 @@ static BOOL init(void)
p___setusermatherr = (void*)GetProcAddress(module, "__setusermatherr");
p_errno = (void*)GetProcAddress(module, "_errno");
p_asctime = (void*)GetProcAddress(module, "asctime");
+ p__crt_atexit = (void*)GetProcAddress(module, "_crt_atexit");
+ p_exit = (void*)GetProcAddress(module, "exit");
return TRUE;
}
@@ -765,6 +769,70 @@ static void test_asctime(void)
ok(!strcmp(ret, "Thu Jan 1 00:00:00 1970\n"), "asctime returned %s\n", ret);
}
+static void test_exit(const char *argv0)
+{
+ HANDLE exit_event1, exit_event2;
+ PROCESS_INFORMATION proc;
+ STARTUPINFOA startup = {0};
+ char path[MAX_PATH];
+ DWORD ret;
+
+ exit_event1 = CreateEventA(NULL, FALSE, FALSE, "exit_event1");
+ exit_event2 = CreateEventA(NULL, FALSE, FALSE, "exit_event2");
+
+ sprintf(path, "%s misc exit", argv0);
+ startup.cb = sizeof(startup);
+ CreateProcessA(NULL, path, NULL, NULL, TRUE, 0, NULL, NULL, &startup, &proc);
+ winetest_wait_child_process(proc.hProcess);
+
+ ret = WaitForSingleObject(exit_event1, 0);
+ ok(ret == WAIT_OBJECT_0, "exit_event1 was not set (%x)\n", ret);
+
+ CloseHandle(exit_event1);
+ CloseHandle(exit_event2);
+}
+
+static void CDECL at_exit_func1(void)
+{
+ HANDLE exit_event1 = CreateEventA(NULL, FALSE, FALSE, "exit_event1");
+ HANDLE exit_event2 = CreateEventA(NULL, FALSE, FALSE, "exit_event2");
+ DWORD ret;
+
+ ok(exit_event1 != NULL, "CreateEvent failed: %d\n", GetLastError());
+ ok(exit_event2 != NULL, "CreateEvent failed: %d\n", GetLastError());
+
+ ret = WaitForSingleObject(exit_event2, 0);
+ ok(ret == WAIT_OBJECT_0, "exit_event2 was not set (%x)\n", ret);
+
+ SetEvent(exit_event1);
+ CloseHandle(exit_event1);
+ CloseHandle(exit_event2);
+}
+
+static void CDECL at_exit_func2(void)
+{
+ HANDLE exit_event1 = CreateEventA(NULL, FALSE, FALSE, "exit_event1");
+ HANDLE exit_event2 = CreateEventA(NULL, FALSE, FALSE, "exit_event2");
+ DWORD ret;
+
+ ok(exit_event1 != NULL, "CreateEvent failed: %d\n", GetLastError());
+ ok(exit_event2 != NULL, "CreateEvent failed: %d\n", GetLastError());
+
+ ret = WaitForSingleObject(exit_event1, 0);
+ ok(ret == WAIT_TIMEOUT, "exit_event1 should not be set (%x)\n", ret);
+
+ SetEvent(exit_event2);
+ CloseHandle(exit_event1);
+ CloseHandle(exit_event2);
+}
+
+static void test_call_exit(void)
+{
+ ok(!p__crt_atexit(at_exit_func1), "_crt_atexit failed\n");
+ ok(!p__crt_atexit(at_exit_func2), "_crt_atexit failed\n");
+ p_exit(0);
+}
+
START_TEST(misc)
{
int arg_c;
@@ -775,7 +843,10 @@ START_TEST(misc)
arg_c = winetest_get_mainargs(&arg_v);
if(arg_c == 3) {
- test__get_narrow_winmain_command_line(NULL);
+ if(!strcmp(arg_v[2], "cmd"))
+ test__get_narrow_winmain_command_line(NULL);
+ else if(!strcmp(arg_v[2], "exit"))
+ test_call_exit();
return;
}
@@ -791,4 +862,5 @@ START_TEST(misc)
test_isblank();
test_math_errors();
test_asctime();
+ test_exit(arg_v[0]);
}
--
2.18.0
June 22, 2018
Re: [PATCH v2] msvcrt: Use already existent oneexit_table functions for _onexit and _c_exit
by Fabian Maurer
> It's still needed to hold the exit lock. Older versions of msvcrt
were
> doing it (I didn't test if newer versions are still using this lock).
Thanks, I'll have an updated version soon. Though I don't see a
good way to write a test for this lock.
Regards,
Fabian Maurer
June 22, 2018
Re: [PATCH] mp3dmod: Support COM aggregation.
by Zebediah Figura
On 06/22/2018 01:22 PM, Jacek Caban wrote:
> Hi Zebediah,
>
> On 06/22/2018 08:06 PM, Zebediah Figura wrote:
>> -static HRESULT create_mp3_decoder(REFIID iid, void **obj)
>> +static HRESULT create_mp3_decoder(IUnknown *outer, REFIID iid, void **obj)
>> {
>> struct mp3_decoder *This;
>> int err;
>> @@ -424,15 +457,17 @@ static HRESULT create_mp3_decoder(REFIID iid, void **obj)
>> if (!(This = heap_alloc_zero(sizeof(*This))))
>> return E_OUTOFMEMORY;
>>
>> - This->IMediaObject_iface.lpVtbl = &IMediaObject_vtbl;
>> + This->IUnknown_inner.lpVtbl = &Unknown_vtbl;
>> + This->IMediaObject_iface.lpVtbl = &MediaObject_vtbl;
>> This->ref = 0;
>> + This->outer = outer ? outer : &This->IUnknown_inner;
>>
>> mpg123_init();
>> This->mh = mpg123_new(NULL, &err);
>> mpg123_open_feed(This->mh);
>> mpg123_format_none(This->mh);
>>
>> - return IMediaObject_QueryInterface(&This->IMediaObject_iface, iid, obj);
>> + return IUnknown_QueryInterface(&This->IUnknown_inner, iid, obj);
>
>
> This leaks in non-aggregated case if QueryInterface fails.
>
>
> Jacek
>
Thanks; I've sent an updated patch.
June 22, 2018
[PATCH v2] mp3dmod: Support COM aggregation.
by Zebediah Figura
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/mp3dmod/mp3dmod.c | 80 ++++++++++++++++++++++++++++++++------------
dlls/mp3dmod/tests/mp3dmod.c | 57 +++++++++++++++++++++++++++++++
2 files changed, 116 insertions(+), 21 deletions(-)
diff --git a/dlls/mp3dmod/mp3dmod.c b/dlls/mp3dmod/mp3dmod.c
index 4949780..90bcf66 100644
--- a/dlls/mp3dmod/mp3dmod.c
+++ b/dlls/mp3dmod/mp3dmod.c
@@ -43,7 +43,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(mp3dmod);
static HINSTANCE mp3dmod_instance;
struct mp3_decoder {
+ IUnknown IUnknown_inner;
IMediaObject IMediaObject_iface;
+ IUnknown *outer;
LONG ref;
mpg123_handle *mh;
DMO_MEDIA_TYPE outtype;
@@ -51,33 +53,35 @@ struct mp3_decoder {
REFERENCE_TIME timestamp;
};
-static inline struct mp3_decoder *impl_from_IMediaObject(IMediaObject *iface)
+static inline struct mp3_decoder *impl_from_IUnknown(IUnknown *iface)
{
- return CONTAINING_RECORD(iface, struct mp3_decoder, IMediaObject_iface);
+ return CONTAINING_RECORD(iface, struct mp3_decoder, IUnknown_inner);
}
-static HRESULT WINAPI MediaObject_QueryInterface(IMediaObject *iface, REFIID iid, void **ppv)
+static HRESULT WINAPI Unknown_QueryInterface(IUnknown *iface, REFIID iid, void **obj)
{
- struct mp3_decoder *This = impl_from_IMediaObject(iface);
+ struct mp3_decoder *This = impl_from_IUnknown(iface);
- TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(iid), ppv);
+ TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(iid), obj);
- if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IMediaObject))
- *ppv = &This->IMediaObject_iface;
+ if (IsEqualGUID(iid, &IID_IUnknown))
+ *obj = &This->IUnknown_inner;
+ else if (IsEqualGUID(iid, &IID_IMediaObject))
+ *obj = &This->IMediaObject_iface;
else
{
FIXME("no interface for %s\n", debugstr_guid(iid));
- *ppv = NULL;
+ *obj = NULL;
return E_NOINTERFACE;
}
- IMediaObject_AddRef(iface);
+ IUnknown_AddRef((IUnknown *)*obj);
return S_OK;
}
-static ULONG WINAPI MediaObject_AddRef(IMediaObject *iface)
+static ULONG WINAPI Unknown_AddRef(IUnknown *iface)
{
- struct mp3_decoder *This = impl_from_IMediaObject(iface);
+ struct mp3_decoder *This = impl_from_IUnknown(iface);
ULONG refcount = InterlockedIncrement(&This->ref);
TRACE("(%p) AddRef from %d\n", This, refcount - 1);
@@ -85,9 +89,9 @@ static ULONG WINAPI MediaObject_AddRef(IMediaObject *iface)
return refcount;
}
-static ULONG WINAPI MediaObject_Release(IMediaObject *iface)
+static ULONG WINAPI Unknown_Release(IUnknown *iface)
{
- struct mp3_decoder *This = impl_from_IMediaObject(iface);
+ struct mp3_decoder *This = impl_from_IUnknown(iface);
ULONG refcount = InterlockedDecrement(&This->ref);
TRACE("(%p) Release from %d\n", This, refcount + 1);
@@ -100,6 +104,35 @@ static ULONG WINAPI MediaObject_Release(IMediaObject *iface)
return refcount;
}
+static const IUnknownVtbl Unknown_vtbl = {
+ Unknown_QueryInterface,
+ Unknown_AddRef,
+ Unknown_Release,
+};
+
+static inline struct mp3_decoder *impl_from_IMediaObject(IMediaObject *iface)
+{
+ return CONTAINING_RECORD(iface, struct mp3_decoder, IMediaObject_iface);
+}
+
+static HRESULT WINAPI MediaObject_QueryInterface(IMediaObject *iface, REFIID iid, void **obj)
+{
+ struct mp3_decoder *This = impl_from_IMediaObject(iface);
+ return IUnknown_QueryInterface(This->outer, iid, obj);
+}
+
+static ULONG WINAPI MediaObject_AddRef(IMediaObject *iface)
+{
+ struct mp3_decoder *This = impl_from_IMediaObject(iface);
+ return IUnknown_AddRef(This->outer);
+}
+
+static ULONG WINAPI MediaObject_Release(IMediaObject *iface)
+{
+ struct mp3_decoder *This = impl_from_IMediaObject(iface);
+ return IUnknown_Release(This->outer);
+}
+
static HRESULT WINAPI MediaObject_GetStreamCount(IMediaObject *iface, DWORD *input, DWORD *output)
{
FIXME("(%p)->(%p, %p) stub!\n", iface, input, output);
@@ -389,7 +422,7 @@ static HRESULT WINAPI MediaObject_Lock(IMediaObject *iface, LONG lock)
return E_NOTIMPL;
}
-static const IMediaObjectVtbl IMediaObject_vtbl = {
+static const IMediaObjectVtbl MediaObject_vtbl = {
MediaObject_QueryInterface,
MediaObject_AddRef,
MediaObject_Release,
@@ -416,23 +449,28 @@ static const IMediaObjectVtbl IMediaObject_vtbl = {
MediaObject_Lock,
};
-static HRESULT create_mp3_decoder(REFIID iid, void **obj)
+static HRESULT create_mp3_decoder(IUnknown *outer, REFIID iid, void **obj)
{
struct mp3_decoder *This;
+ HRESULT hr;
int err;
if (!(This = heap_alloc_zero(sizeof(*This))))
return E_OUTOFMEMORY;
- This->IMediaObject_iface.lpVtbl = &IMediaObject_vtbl;
- This->ref = 0;
+ This->IUnknown_inner.lpVtbl = &Unknown_vtbl;
+ This->IMediaObject_iface.lpVtbl = &MediaObject_vtbl;
+ This->ref = 1;
+ This->outer = outer ? outer : &This->IUnknown_inner;
mpg123_init();
This->mh = mpg123_new(NULL, &err);
mpg123_open_feed(This->mh);
mpg123_format_none(This->mh);
- return IMediaObject_QueryInterface(&This->IMediaObject_iface, iid, obj);
+ hr = IUnknown_QueryInterface(&This->IUnknown_inner, iid, obj);
+ IUnknown_Release(&This->IUnknown_inner);
+ return hr;
}
static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID iid, void **obj)
@@ -466,13 +504,13 @@ static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown
{
TRACE("(%p, %s, %p)\n", outer, debugstr_guid(iid), obj);
- if (outer)
+ if (outer && !IsEqualGUID(iid, &IID_IUnknown))
{
*obj = NULL;
- return CLASS_E_NOAGGREGATION;
+ return E_NOINTERFACE;
}
- return create_mp3_decoder(iid, obj);
+ return create_mp3_decoder(outer, iid, obj);
}
static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL lock)
diff --git a/dlls/mp3dmod/tests/mp3dmod.c b/dlls/mp3dmod/tests/mp3dmod.c
index 68c6b4d..75fd0e2 100644
--- a/dlls/mp3dmod/tests/mp3dmod.c
+++ b/dlls/mp3dmod/tests/mp3dmod.c
@@ -230,6 +230,62 @@ static void test_convert(void)
IMediaObject_Release(dmo);
}
+static const GUID IID_test_outer = {0xdeadbeef,0,0,{0,0,0,0,0,0,0,0x66}};
+
+static HRESULT WINAPI Outer_QueryInterface(IUnknown *iface, REFIID iid, void **obj)
+{
+ if (IsEqualGUID(iid, &IID_test_outer))
+ {
+ *obj = (IUnknown *)0xdeadbeef;
+ return S_OK;
+ }
+ ok(0, "unexpected call %s\n", wine_dbgstr_guid(iid));
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI Outer_AddRef(IUnknown *iface)
+{
+ return 2;
+}
+
+static ULONG WINAPI Outer_Release(IUnknown *iface)
+{
+ return 1;
+}
+
+static IUnknownVtbl Outer_vtbl = {
+ Outer_QueryInterface,
+ Outer_AddRef,
+ Outer_Release,
+};
+
+static IUnknown Outer = { &Outer_vtbl };
+
+static void test_aggregation(void)
+{
+ IUnknown *unk, *unk2;
+ IMediaObject *dmo;
+ HRESULT hr;
+
+ hr = CoCreateInstance(&CLSID_CMP3DecMediaObject, &Outer, CLSCTX_INPROC_SERVER,
+ &IID_IUnknown, (void **)&unk);
+ ok(hr == S_OK, "got %#x\n", hr);
+
+ hr = IUnknown_QueryInterface(unk, &IID_IMediaObject, (void **)&dmo);
+ ok(hr == S_OK, "got %#x\n", hr);
+
+ hr = IMediaObject_QueryInterface(dmo, &IID_test_outer, (void **)&unk2);
+ ok(hr == S_OK, "got %#x\n", hr);
+ ok(unk2 == (IUnknown *)0xdeadbeef, "got unk %p\n", unk2);
+
+ IUnknown_Release(dmo);
+ IUnknown_Release(unk);
+
+ hr = CoCreateInstance(&CLSID_CMP3DecMediaObject, &Outer, CLSCTX_INPROC_SERVER,
+ &IID_IMediaObject, (void **)&unk);
+ ok(hr == E_NOINTERFACE, "got %#x\n", hr);
+}
+
START_TEST(mp3dmod)
{
IMediaObject *dmo;
@@ -247,6 +303,7 @@ START_TEST(mp3dmod)
IMediaObject_Release(dmo);
test_convert();
+ test_aggregation();
CoUninitialize();
}
--
2.7.4
June 22, 2018
[PATCH v3] user32: Always release menu item in EnableMenuItem
by Fabian Maurer
The menu must be release on all code-paths,
else the underlying lock will never be released.
Fixes bug 45355.
Signed-off-by: Fabian Maurer <dark.shadow4(a)web.de>
---
dlls/user32/menu.c | 33 +++++++++++++++------------------
1 file changed, 15 insertions(+), 18 deletions(-)
diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c
index 8c541cc4f91..ab1ae9bc1bd 100644
--- a/dlls/user32/menu.c
+++ b/dlls/user32/menu.c
@@ -3741,28 +3741,25 @@ BOOL WINAPI EnableMenuItem( HMENU hMenu, UINT id, UINT wFlags )
item->fState ^= (oldflags ^ wFlags) & (MF_GRAYED | MF_DISABLED);
/* If the close item in the system menu change update the close button */
- if ((item->wID == SC_CLOSE) && (oldflags != wFlags))
+ if ((item->wID == SC_CLOSE) && (oldflags != wFlags) && menu->hSysMenuOwner)
{
- if (menu->hSysMenuOwner)
- {
- RECT rc;
- POPUPMENU* parentMenu;
- HWND hwnd;
+ RECT rc;
+ POPUPMENU* parentMenu;
+ HWND hwnd;
- /* Get the parent menu to access*/
- parentMenu = grab_menu_ptr(menu->hSysMenuOwner);
- release_menu_ptr(menu);
- if (!parentMenu)
- return (UINT)-1;
+ /* Get the parent menu to access */
+ parentMenu = grab_menu_ptr(menu->hSysMenuOwner);
+ release_menu_ptr(menu);
+ if (!parentMenu)
+ return (UINT)-1;
- hwnd = parentMenu->hWnd;
- release_menu_ptr(parentMenu);
+ hwnd = parentMenu->hWnd;
+ release_menu_ptr(parentMenu);
- /* Refresh the frame to reflect the change */
- WIN_GetRectangles( hwnd, COORDS_CLIENT, &rc, NULL );
- rc.bottom = 0;
- RedrawWindow(hwnd, &rc, 0, RDW_FRAME | RDW_INVALIDATE | RDW_NOCHILDREN);
- }
+ /* Refresh the frame to reflect the change */
+ WIN_GetRectangles(hwnd, COORDS_CLIENT, &rc, NULL);
+ rc.bottom = 0;
+ RedrawWindow(hwnd, &rc, 0, RDW_FRAME | RDW_INVALIDATE | RDW_NOCHILDREN);
}
else
release_menu_ptr(menu);
--
2.18.0
June 22, 2018