Wine-devel
Threads by month
- ----- 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
April 2018
- 75 participants
- 538 discussions
[PATCH 2/2] dinput/tests: Add some tests for DIK_ codes using different keyboard layouts. (v2)
by Dmitry Timoshkov 16 Apr '18
by Dmitry Timoshkov 16 Apr '18
16 Apr '18
v2: fixed test failures under testbot VMs, failures never happen on real
hardware but testbot VMs seem to have timing issues.
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
dlls/dinput/keyboard.c | 3 +-
dlls/dinput/tests/keyboard.c | 193 ++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 193 insertions(+), 3 deletions(-)
diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c
index e1ba15edd1..8a59ce01bc 100644
--- a/dlls/dinput/keyboard.c
+++ b/dlls/dinput/keyboard.c
@@ -86,7 +86,8 @@ static int KeyboardCallback( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM
wparam != WM_SYSKEYDOWN && wparam != WM_SYSKEYUP)
return 0;
- TRACE("(%p) %ld,%ld\n", iface, wparam, lparam);
+ TRACE("(%p) wp %08lx, lp %08lx, vk %02x, scan %02x\n",
+ iface, wparam, lparam, hook->vkCode, hook->scanCode);
switch (hook->vkCode)
{
diff --git a/dlls/dinput/tests/keyboard.c b/dlls/dinput/tests/keyboard.c
index e51e332535..576a94cc7d 100644
--- a/dlls/dinput/tests/keyboard.c
+++ b/dlls/dinput/tests/keyboard.c
@@ -30,6 +30,53 @@
#include "wingdi.h"
#include "dinput.h"
+/* to make things easier with PSDK without a dinput.lib */
+static HRESULT (WINAPI *pDirectInputCreateA)(HINSTANCE,DWORD,IDirectInputA **,IUnknown *);
+
+static void pump_messages(void)
+{
+ MSG msg;
+
+ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
+ {
+ TranslateMessage(&msg);
+ DispatchMessageA(&msg);
+ }
+}
+
+static HKL activate_keyboard_layout(LANGID langid, HKL *hkl_orig)
+{
+ HKL hkl, hkl_current;
+ char hkl_name[64];
+
+ sprintf(hkl_name, "%08x", langid);
+ trace("Loading keyboard layout %s\n", hkl_name);
+ hkl = LoadKeyboardLayoutA(hkl_name, 0);
+ if (!hkl)
+ {
+ win_skip("Unable to load keyboard layout %s\n", hkl_name);
+ return 0;
+ }
+ *hkl_orig = ActivateKeyboardLayout(hkl, 0);
+ ok(*hkl_orig != 0, "Unable to activate keyboard layout %s\n", hkl_name);
+ if (!*hkl_orig) return 0;
+
+ hkl_current = GetKeyboardLayout(0);
+ if (LOWORD(hkl_current) != langid)
+ {
+ /* FIXME: Wine can't activate different keyboard layouts.
+ * for testing purposes use this workaround:
+ * setxkbmap us && LANG=en_US.UTF-8 make test
+ * setxkbmap fr && LANG=fr_FR.UTF-8 make test
+ * setxkbmap de && LANG=de_DE.UTF-8 make test
+ */
+ skip("current %08x != langid %08x\n", LOWORD(hkl_current), langid);
+ return 0;
+ }
+
+ return hkl;
+}
+
static void acquire_tests(IDirectInputA *pDI, HWND hwnd)
{
HRESULT hr;
@@ -44,8 +91,12 @@ static void acquire_tests(IDirectInputA *pDI, HWND hwnd)
{ &GUID_Key, sizeof(LONG) * 2, DIDFT_MAKEINSTANCE(DIK_E)|DIDFT_BUTTON, 0 },
{ &GUID_Key, sizeof(LONG) * 4, DIDFT_MAKEINSTANCE(DIK_R)|DIDFT_BUTTON, 0 },
};
-
DIDATAFORMAT df;
+ HKL hkl, hkl_orig;
+
+ hkl = activate_keyboard_layout(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), &hkl_orig);
+ if (!hkl) return;
+
df.dwSize = sizeof( df );
df.dwObjSize = sizeof( DIOBJECTDATAFORMAT );
df.dwFlags = DIDF_RELAXIS;
@@ -93,6 +144,8 @@ static void acquire_tests(IDirectInputA *pDI, HWND hwnd)
/* simulate some keyboard input */
SetFocus(hwnd);
+ pump_messages();
+
keybd_event('Q', 0, 0, 0);
hr = IDirectInputDevice_GetDeviceState(pKeyboard, sizeof(custom_state), custom_state);
ok(SUCCEEDED(hr), "IDirectInputDevice_GetDeviceState() failed: %08x\n", hr);
@@ -113,6 +166,9 @@ static void acquire_tests(IDirectInputA *pDI, HWND hwnd)
keybd_event('Q', 0, KEYEVENTF_KEYUP, 0);
if (pKeyboard) IUnknown_Release(pKeyboard);
+
+ ActivateKeyboardLayout(hkl_orig, 0);
+ UnloadKeyboardLayout(hkl);
}
static const HRESULT SetCoop_null_window[16] = {
@@ -225,6 +281,130 @@ static void test_capabilities(IDirectInputA *pDI, HWND hwnd)
IUnknown_Release(pKeyboard);
}
+static void test_dik_codes(IDirectInputA *dI, HWND hwnd, LANGID langid)
+{
+ static const struct key2dik
+ {
+ BYTE key, dik;
+ } key2dik_en[] =
+ {
+ {'Q',DIK_Q}, {'W',DIK_W}, {'E',DIK_E}, {'R',DIK_R}, {'T',DIK_T}, {'Y',DIK_Y}
+ },
+ key2dik_fr[] =
+ {
+ {'A',DIK_Q}, {'Z',DIK_W}, {'E',DIK_E}, {'R',DIK_R}, {'T',DIK_T}, {'Y',DIK_Y}
+ },
+ key2dik_de[] =
+ {
+ {'Q',DIK_Q}, {'W',DIK_W}, {'E',DIK_E}, {'R',DIK_R}, {'T',DIK_T}, {'Z',DIK_Y}
+ };
+ static const struct
+ {
+ LANGID langid;
+ const struct key2dik *map;
+ } expected[] =
+ {
+ { MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), key2dik_en },
+ { MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH), key2dik_fr },
+ { MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN), key2dik_de },
+ { MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN), key2dik_en }
+ };
+ const struct key2dik *map = NULL;
+ UINT i;
+ HRESULT hr;
+ IDirectInputDeviceA *device;
+ HKL hkl, hkl_orig;
+ MSG msg;
+
+ for (i = 0; i < sizeof(expected)/sizeof(expected[0]); i++)
+ {
+ if (expected[i].langid == langid)
+ {
+ map = expected[i].map;
+ break;
+ }
+ }
+ ok(map != NULL, "can't find mapping for langid %04x\n", langid);
+ if (!map) return;
+
+ hr = IDirectInput_CreateDevice(dI, &GUID_SysKeyboard, &device, NULL);
+ ok(hr == S_OK, "CreateDevice() failed: %08x\n", hr);
+ hr = IDirectInputDevice_SetDataFormat(device, &c_dfDIKeyboard);
+ ok(hr == S_OK, "SetDataFormat() failed: %08x\n", hr);
+ hr = IDirectInputDevice_Acquire(device);
+ ok(hr == S_OK, "Acquire() failed: %08x\n", hr);
+
+ hkl = activate_keyboard_layout(langid, &hkl_orig);
+ if (!hkl) goto fail;
+
+ SetFocus(hwnd);
+ pump_messages();
+
+ for (i = 0; i < sizeof(key2dik_en)/sizeof(key2dik_en[0]); i++)
+ {
+ BYTE kbd_state[256];
+ UINT n;
+ INPUT in;
+
+ n = MapVirtualKeyA(map[i].key, MAPVK_VK_TO_CHAR);
+ ok(n == map[i].key, "%u: expected %c, got %c\n", i, map[i].key, n);
+ n = MapVirtualKeyA(map[i].key, MAPVK_VK_TO_VSC);
+ ok(n == map[i].dik, "%u: expected %02x, got %02x\n", i, map[i].dik, n);
+
+ in.type = INPUT_KEYBOARD;
+ U(in).ki.wVk = map[i].key;
+ U(in).ki.wScan = map[i].dik; /* scan codes match the DIK_ codes */
+ U(in).ki.dwFlags = 0;
+ U(in).ki.dwExtraInfo = 0;
+ U(in).ki.time = 0;
+ n = SendInput(1, &in, sizeof(in));
+ ok(n == 1, "got %u\n", n);
+
+ if (!PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
+ {
+ win_skip("failed to queue keyboard event\n");
+ break;
+ }
+ ok(msg.message == WM_KEYDOWN || broken(msg.message != WM_KEYDOWN), "expected WM_KEYDOWN, got %04x\n", msg.message);
+ /* this never happens on real hardware but tesbot VMs seem to have timing issues */
+ if (msg.message != WM_KEYDOWN)
+ {
+ win_skip("failed to queue keyboard event\n");
+ break;
+ }
+ DispatchMessageA(&msg);
+
+ trace("keydown wParam: %#lx (%c) lParam: %#lx, MapVirtualKey(MAPVK_VK_TO_CHAR) = %c\n",
+ msg.wParam, LOWORD(msg.wParam), msg.lParam, MapVirtualKeyA(msg.wParam, MAPVK_VK_TO_CHAR));
+
+ pump_messages();
+
+ hr = IDirectInputDevice_GetDeviceState(device, sizeof(kbd_state), kbd_state);
+ ok(hr == S_OK, "GetDeviceState() failed: %08x\n", hr);
+
+ /* this never happens on real hardware but tesbot VMs seem to have timing issues */
+ if (i == 0 && kbd_state[map[0].dik] != 0x80)
+ {
+ win_skip("dinput failed to handle keyboard event\n");
+ break;
+ }
+
+ ok(kbd_state[map[i].dik] == 0x80, "DI key %#x has state %#x\n", map[i].dik, kbd_state[map[i].dik]);
+
+ U(in).ki.dwFlags = KEYEVENTF_KEYUP;
+ n = SendInput(1, &in, sizeof(in));
+ ok(n == 1, "got %u\n", n);
+
+ pump_messages();
+ }
+
+ ActivateKeyboardLayout(hkl_orig, 0);
+ UnloadKeyboardLayout(hkl);
+fail:
+ IDirectInputDevice_Unacquire(device);
+ IUnknown_Release(device);
+}
+
static void keyboard_tests(DWORD version)
{
HRESULT hr;
@@ -233,7 +413,7 @@ static void keyboard_tests(DWORD version)
HWND hwnd;
ULONG ref = 0;
- hr = DirectInputCreateA(hInstance, version, &pDI, NULL);
+ hr = pDirectInputCreateA(hInstance, version, &pDI, NULL);
if (hr == DIERR_OLDDIRECTINPUTVERSION)
{
skip("Tests require a newer dinput version\n");
@@ -248,10 +428,17 @@ static void keyboard_tests(DWORD version)
if (hwnd)
{
+ pump_messages();
+
acquire_tests(pDI, hwnd);
test_set_coop(pDI, hwnd);
test_get_prop(pDI, hwnd);
test_capabilities(pDI, hwnd);
+
+ test_dik_codes(pDI, hwnd, MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT));
+ test_dik_codes(pDI, hwnd, MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH));
+ test_dik_codes(pDI, hwnd, MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN));
+ test_dik_codes(pDI, hwnd, MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN));
}
DestroyWindow(hwnd);
@@ -261,6 +448,8 @@ static void keyboard_tests(DWORD version)
START_TEST(keyboard)
{
+ pDirectInputCreateA = (void *)GetProcAddress(LoadLibraryA("dinput.dll"), "DirectInputCreateA");
+
CoInitialize(NULL);
keyboard_tests(0x0700);
--
2.16.3
1
0
16 Apr '18
This patch reverts commit 304ff3c7280a53b7cbadfa83eaeda458ff5959d1,
and fixes multiple regressions caused by this change for non-US keyboards.
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
dlls/dinput/keyboard.c | 24 ++++--------------------
1 file changed, 4 insertions(+), 20 deletions(-)
diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c
index 4c3c38e7fc..e1ba15edd1 100644
--- a/dlls/dinput/keyboard.c
+++ b/dlls/dinput/keyboard.c
@@ -69,26 +69,10 @@ static inline IDirectInputDevice8W *IDirectInputDevice8W_from_impl(SysKeyboardIm
static BYTE map_dik_code(DWORD scanCode, DWORD vkCode)
{
- static const BYTE asciiCodes[] =
- {/*32*/ DIK_SPACE,0,0,0,0,0,0,DIK_APOSTROPHE,
- /*40*/ 0,0,0,0,DIK_COMMA,DIK_MINUS,DIK_PERIOD,DIK_SLASH,
- /*48*/ DIK_0,DIK_1,DIK_2,DIK_3,DIK_4,DIK_5,DIK_6,DIK_7,
- /*56*/ DIK_8,DIK_9,DIK_COLON,DIK_SEMICOLON,0,DIK_EQUALS,0,0,
- /*64*/ DIK_AT,DIK_A,DIK_B,DIK_C,DIK_D,DIK_E,DIK_F,DIK_G,
- /*72*/ DIK_H,DIK_I,DIK_J,DIK_K,DIK_L,DIK_M,DIK_N,DIK_O,
- /*80*/ DIK_P,DIK_Q,DIK_R,DIK_S,DIK_T,DIK_U,DIK_V,DIK_W,
- /*88*/ DIK_X,DIK_Y,DIK_Z,DIK_LBRACKET,0,DIK_RBRACKET,DIK_CIRCUMFLEX,DIK_UNDERLINE} /*95*/ ;
-
- BYTE out_code = 0;
- WCHAR c = MapVirtualKeyW(vkCode,MAPVK_VK_TO_CHAR);
-
- if (c > 31 && c < 96)
- out_code = asciiCodes[c - 32];
-
- if (out_code == 0)
- out_code = scanCode;
-
- return out_code;
+ if (!scanCode)
+ scanCode = MapVirtualKeyW(vkCode, MAPVK_VK_TO_VSC);
+
+ return scanCode;
}
static int KeyboardCallback( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM lparam )
--
2.16.3
1
0
[PATCH 5/5] wined3d: Get rid of the "numberedArraysLoaded" field in struct wined3d_context.
by Henri Verbeet 16 Apr '18
by Henri Verbeet 16 Apr '18
16 Apr '18
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
dlls/wined3d/state.c | 4 +---
dlls/wined3d/wined3d_private.h | 9 +++++----
2 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index 5a37fadabdc..5bcd244d930 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -4346,10 +4346,9 @@ static void streamsrc(struct wined3d_context *context, const struct wined3d_stat
&& !use_vs(state) && !context->use_immediate_mode_draw;
if (isStateDirty(context, STATE_VDECL)) return;
- if (context->numberedArraysLoaded && !load_numbered)
+ if (context->numbered_array_mask && !load_numbered)
{
unload_numbered_arrays(context);
- context->numberedArraysLoaded = FALSE;
context->numbered_array_mask = 0;
}
else if (context->namedArraysLoaded)
@@ -4362,7 +4361,6 @@ static void streamsrc(struct wined3d_context *context, const struct wined3d_stat
{
TRACE("Loading numbered arrays\n");
load_numbered_arrays(context, &context->stream_info, state);
- context->numberedArraysLoaded = TRUE;
}
else if (load_named)
{
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 24d923265e3..7e6a87fe2fa 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1883,7 +1883,7 @@ struct wined3d_context
DWORD last_was_vshader : 1;
DWORD last_was_normal : 1;
DWORD namedArraysLoaded : 1;
- DWORD numberedArraysLoaded : 1;
+ DWORD last_was_ffp_blit : 1;
DWORD last_was_blit : 1;
DWORD last_was_ckey : 1;
DWORD fog_coord : 1;
@@ -1892,6 +1892,7 @@ struct wined3d_context
DWORD current : 1;
DWORD destroyed : 1;
DWORD valid : 1;
+
DWORD texShaderBumpMap : 8; /* MAX_TEXTURES, 8 */
DWORD lastWasPow2Texture : 8; /* MAX_TEXTURES, 8 */
DWORD fixed_function_usage_map : 8; /* MAX_TEXTURES, 8 */
@@ -1900,6 +1901,7 @@ struct wined3d_context
DWORD rebind_fbo : 1;
DWORD needs_set : 1;
DWORD hdc_is_private : 1;
+
DWORD hdc_has_format : 1; /* only meaningful if hdc_is_private */
DWORD update_shader_resource_bindings : 1;
DWORD update_compute_shader_resource_bindings : 1;
@@ -1911,11 +1913,10 @@ struct wined3d_context
DWORD transform_feedback_paused : 1;
DWORD shader_update_mask : 6; /* WINED3D_SHADER_TYPE_COUNT, 6 */
DWORD clip_distance_mask : 8; /* MAX_CLIP_DISTANCES, 8 */
- DWORD last_was_ffp_blit : 1;
- DWORD padding : 8;
+ DWORD padding : 9;
DWORD constant_update_mask;
- DWORD numbered_array_mask;
+ DWORD numbered_array_mask;
GLenum tracking_parm; /* Which source is tracking current colour */
GLenum untracked_materials[2];
UINT blit_w, blit_h;
--
2.11.0
1
0
[PATCH 4/5] wined3d: Use staging resources to blit from CPU resources in the ARBfp blitter.
by Henri Verbeet 16 Apr '18
by Henri Verbeet 16 Apr '18
16 Apr '18
From: Matteo Bruni <mbruni(a)codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
dlls/wined3d/arb_program_shader.c | 49 +++++++++++++++++++++++++++++++++++----
1 file changed, 44 insertions(+), 5 deletions(-)
diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index ea07c3b2e35..7d3f547405a 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -7789,9 +7789,11 @@ static DWORD arbfp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bl
const struct wined3d_color_key *color_key, enum wined3d_texture_filter_type filter)
{
struct wined3d_device *device = dst_texture->resource.device;
+ struct wined3d_texture *staging_texture = NULL;
struct wined3d_arbfp_blitter *arbfp_blitter;
struct wined3d_color_key alpha_test_key;
struct wined3d_blitter *next;
+ unsigned int src_level;
RECT s, d;
TRACE("blitter %p, op %#x, context %p, src_texture %p, src_sub_resource_idx %u, src_location %s, src_rect %s, "
@@ -7816,14 +7818,45 @@ static DWORD arbfp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bl
arbfp_blitter = CONTAINING_RECORD(blitter, struct wined3d_arbfp_blitter, blitter);
- /* Now load the surface */
- if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
+ if (!(src_texture->resource.access & WINED3D_RESOURCE_ACCESS_GPU))
+ {
+ struct wined3d_resource_desc desc;
+ struct wined3d_box upload_box;
+ HRESULT hr;
+
+ TRACE("Source texture is not GPU accessible, creating a staging texture.\n");
+
+ src_level = src_sub_resource_idx % src_texture->level_count;
+ desc.resource_type = WINED3D_RTYPE_TEXTURE_2D;
+ desc.format = src_texture->resource.format->id;
+ desc.multisample_type = src_texture->resource.multisample_type;
+ desc.multisample_quality = src_texture->resource.multisample_quality;
+ desc.usage = WINED3DUSAGE_PRIVATE;
+ desc.access = WINED3D_RESOURCE_ACCESS_GPU;
+ desc.width = wined3d_texture_get_level_width(src_texture, src_level);
+ desc.height = wined3d_texture_get_level_height(src_texture, src_level);
+ desc.depth = 1;
+ desc.size = 0;
+
+ if (FAILED(hr = wined3d_texture_create(device, &desc, 1, 1, 0,
+ NULL, NULL, &wined3d_null_parent_ops, &staging_texture)))
+ {
+ ERR("Failed to create staging texture, hr %#x.\n", hr);
+ return dst_location;
+ }
+
+ wined3d_box_set(&upload_box, 0, 0, desc.width, desc.height, 0, desc.depth);
+ wined3d_texture_upload_from_texture(staging_texture, 0, 0, 0, 0,
+ src_texture, src_sub_resource_idx, &upload_box);
+
+ src_texture = staging_texture;
+ src_sub_resource_idx = 0;
+ }
+ else if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
&& (src_texture->sub_resources[src_sub_resource_idx].locations
- & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_DRAWABLE))
- == WINED3D_LOCATION_DRAWABLE
+ & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_DRAWABLE)) == WINED3D_LOCATION_DRAWABLE
&& !wined3d_resource_is_offscreen(&src_texture->resource))
{
- unsigned int src_level = src_sub_resource_idx % src_texture->level_count;
/* Without FBO blits transferring from the drawable to the texture is
* expensive, because we have to flip the data in sysmem. Since we can
@@ -7833,12 +7866,15 @@ static DWORD arbfp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bl
texture2d_load_fb_texture(src_texture, src_sub_resource_idx, FALSE, context);
s = *src_rect;
+ src_level = src_sub_resource_idx % src_texture->level_count;
s.top = wined3d_texture_get_level_height(src_texture, src_level) - s.top;
s.bottom = wined3d_texture_get_level_height(src_texture, src_level) - s.bottom;
src_rect = &s;
}
else
+ {
wined3d_texture_load(src_texture, context, FALSE);
+ }
context_apply_ffp_blit_state(context, device);
@@ -7889,6 +7925,9 @@ static DWORD arbfp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bl
if (dst_texture->swapchain && (dst_texture->swapchain->front_buffer == dst_texture))
context->gl_info->gl_ops.gl.p_glFlush();
+ if (staging_texture)
+ wined3d_texture_decref(staging_texture);
+
return dst_location;
}
--
2.11.0
1
0
[PATCH 3/5] wined3d: Use staging resources to blit from CPU resources in the GLSL blitter.
by Henri Verbeet 16 Apr '18
by Henri Verbeet 16 Apr '18
16 Apr '18
From: Matteo Bruni <mbruni(a)codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
dlls/wined3d/glsl_shader.c | 49 ++++++++++++++++++++++++++++----
dlls/wined3d/surface.c | 64 ++++++------------------------------------
dlls/wined3d/texture.c | 46 ++++++++++++++++++++++++++++++
dlls/wined3d/wined3d_private.h | 3 ++
4 files changed, 100 insertions(+), 62 deletions(-)
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index e839369f11c..7f1e66bc877 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -12428,11 +12428,9 @@ static BOOL glsl_blitter_supported(enum wined3d_blit_op blit_op, const struct wi
return FALSE;
}
- /* FIXME: We never want to blit from resources without
+ /* We don't necessarily want to blit from resources without
* WINED3D_RESOURCE_ACCESS_GPU, but that may be the only way to decompress
- * compressed textures. We should probably create an explicit staging
- * texture for this purpose instead of loading the resource into an
- * invalid location. */
+ * compressed textures. */
decompress = src_format && (src_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_COMPRESSED)
&& !(dst_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_COMPRESSED);
if (!decompress && !(src_resource->access & dst_resource->access & WINED3D_RESOURCE_ACCESS_GPU))
@@ -12465,8 +12463,10 @@ static DWORD glsl_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bli
{
struct wined3d_device *device = dst_texture->resource.device;
const struct wined3d_gl_info *gl_info = context->gl_info;
+ struct wined3d_texture *staging_texture = NULL;
struct wined3d_glsl_blitter *glsl_blitter;
struct wined3d_blitter *next;
+ unsigned int src_level;
GLuint program_id;
RECT s, d;
@@ -12491,12 +12491,45 @@ static DWORD glsl_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bli
glsl_blitter = CONTAINING_RECORD(blitter, struct wined3d_glsl_blitter, blitter);
- if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
+ if (!(src_texture->resource.access & WINED3D_RESOURCE_ACCESS_GPU))
+ {
+ struct wined3d_resource_desc desc;
+ struct wined3d_box upload_box;
+ HRESULT hr;
+
+ TRACE("Source texture is not GPU accessible, creating a staging texture.\n");
+
+ src_level = src_sub_resource_idx % src_texture->level_count;
+ desc.resource_type = WINED3D_RTYPE_TEXTURE_2D;
+ desc.format = src_texture->resource.format->id;
+ desc.multisample_type = src_texture->resource.multisample_type;
+ desc.multisample_quality = src_texture->resource.multisample_quality;
+ desc.usage = WINED3DUSAGE_PRIVATE;
+ desc.access = WINED3D_RESOURCE_ACCESS_GPU;
+ desc.width = wined3d_texture_get_level_width(src_texture, src_level);
+ desc.height = wined3d_texture_get_level_height(src_texture, src_level);
+ desc.depth = 1;
+ desc.size = 0;
+
+ if (FAILED(hr = wined3d_texture_create(device, &desc, 1, 1, 0,
+ NULL, NULL, &wined3d_null_parent_ops, &staging_texture)))
+ {
+ ERR("Failed to create staging texture, hr %#x.\n", hr);
+ return dst_location;
+ }
+
+ wined3d_box_set(&upload_box, 0, 0, desc.width, desc.height, 0, desc.depth);
+ wined3d_texture_upload_from_texture(staging_texture, 0, 0, 0, 0,
+ src_texture, src_sub_resource_idx, &upload_box);
+
+ src_texture = staging_texture;
+ src_sub_resource_idx = 0;
+ }
+ else if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
&& (src_texture->sub_resources[src_sub_resource_idx].locations
& (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_DRAWABLE)) == WINED3D_LOCATION_DRAWABLE
&& !wined3d_resource_is_offscreen(&src_texture->resource))
{
- unsigned int src_level = src_sub_resource_idx % src_texture->level_count;
/* Without FBO blits transferring from the drawable to the texture is
* expensive, because we have to flip the data in sysmem. Since we can
@@ -12506,6 +12539,7 @@ static DWORD glsl_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bli
texture2d_load_fb_texture(src_texture, src_sub_resource_idx, FALSE, context);
s = *src_rect;
+ src_level = src_sub_resource_idx % src_texture->level_count;
s.top = wined3d_texture_get_level_height(src_texture, src_level) - s.top;
s.bottom = wined3d_texture_get_level_height(src_texture, src_level) - s.bottom;
src_rect = &s;
@@ -12557,6 +12591,9 @@ static DWORD glsl_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bli
if (dst_texture->swapchain && (dst_texture->swapchain->front_buffer == dst_texture))
gl_info->gl_ops.gl.p_glFlush();
+ if (staging_texture)
+ wined3d_texture_decref(staging_texture);
+
return dst_location;
}
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index ad4ed1c33a8..7a13b5883be 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -566,52 +566,6 @@ static void texture2d_download_data(struct wined3d_texture *texture, unsigned in
heap_free(temporary_mem);
}
-static HRESULT texture2d_upload_from_surface(struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx,
- unsigned int dst_x, unsigned int dst_y, struct wined3d_texture *src_texture,
- unsigned int src_sub_resource_idx, const struct wined3d_box *src_box)
-{
- unsigned int src_row_pitch, src_slice_pitch;
- unsigned int src_level, dst_level;
- struct wined3d_context *context;
- struct wined3d_bo_address data;
- UINT update_w, update_h;
-
- TRACE("dst_texture %p, dst_sub_resource_idx %u, dst_x %u, dst_y %u, "
- "src_texture %p, src_sub_resource_idx %u, src_box %s.\n",
- dst_texture, dst_sub_resource_idx, dst_x, dst_y,
- src_texture, src_sub_resource_idx, debug_box(src_box));
-
- context = context_acquire(dst_texture->resource.device, NULL, 0);
-
- /* Only load the sub-resource for partial updates. For newly allocated
- * textures the texture wouldn't be the current location, and we'd upload
- * zeroes just to overwrite them again. */
- update_w = src_box->right - src_box->left;
- update_h = src_box->bottom - src_box->top;
- dst_level = dst_sub_resource_idx % dst_texture->level_count;
- if (update_w == wined3d_texture_get_level_width(dst_texture, dst_level)
- && update_h == wined3d_texture_get_level_height(dst_texture, dst_level))
- wined3d_texture_prepare_texture(dst_texture, context, FALSE);
- else
- wined3d_texture_load_location(dst_texture, dst_sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB);
- wined3d_texture_bind_and_dirtify(dst_texture, context, FALSE);
-
- src_level = src_sub_resource_idx % src_texture->level_count;
- wined3d_texture_get_memory(src_texture, src_sub_resource_idx, &data,
- src_texture->sub_resources[src_sub_resource_idx].locations);
- wined3d_texture_get_pitch(src_texture, src_level, &src_row_pitch, &src_slice_pitch);
-
- wined3d_texture_upload_data(dst_texture, dst_sub_resource_idx, context, src_texture->resource.format,
- src_box, wined3d_const_bo_address(&data), src_row_pitch, src_slice_pitch, dst_x, dst_y, 0, FALSE);
-
- context_release(context);
-
- wined3d_texture_validate_location(dst_texture, dst_sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB);
- wined3d_texture_invalidate_location(dst_texture, dst_sub_resource_idx, ~WINED3D_LOCATION_TEXTURE_RGB);
-
- return WINED3D_OK;
-}
-
/* See also float_16_to_32() in wined3d_private.h */
static inline unsigned short float_32_to_16(const float *in)
{
@@ -3459,18 +3413,16 @@ HRESULT texture2d_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_
TRACE("Not doing upload because the destination format needs conversion.\n");
else
{
- if (SUCCEEDED(texture2d_upload_from_surface(dst_texture, dst_sub_resource_idx,
- dst_box->left, dst_box->top, src_texture, src_sub_resource_idx, src_box)))
+ wined3d_texture_upload_from_texture(dst_texture, dst_sub_resource_idx, dst_box->left,
+ dst_box->top, dst_box->front, src_texture, src_sub_resource_idx, src_box);
+ if (!wined3d_resource_is_offscreen(&dst_texture->resource))
{
- if (!wined3d_resource_is_offscreen(&dst_texture->resource))
- {
- context = context_acquire(device, dst_texture, dst_sub_resource_idx);
- wined3d_texture_load_location(dst_texture, dst_sub_resource_idx,
- context, dst_texture->resource.draw_binding);
- context_release(context);
- }
- return WINED3D_OK;
+ context = context_acquire(device, dst_texture, dst_sub_resource_idx);
+ wined3d_texture_load_location(dst_texture, dst_sub_resource_idx,
+ context, dst_texture->resource.draw_binding);
+ context_release(context);
}
+ return WINED3D_OK;
}
}
else if (dst_swapchain && dst_swapchain->back_buffers
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index 427ed4f3570..dadcd0323a0 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -3488,3 +3488,49 @@ HRESULT CDECL wined3d_texture_release_dc(struct wined3d_texture *texture, unsign
return WINED3D_OK;
}
+
+void wined3d_texture_upload_from_texture(struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx,
+ unsigned int dst_x, unsigned int dst_y, unsigned int dst_z, struct wined3d_texture *src_texture,
+ unsigned int src_sub_resource_idx, const struct wined3d_box *src_box)
+{
+ unsigned int src_row_pitch, src_slice_pitch;
+ unsigned int update_w, update_h, update_d;
+ unsigned int src_level, dst_level;
+ struct wined3d_context *context;
+ struct wined3d_bo_address data;
+
+ TRACE("dst_texture %p, dst_sub_resource_idx %u, dst_x %u, dst_y %u, dst_z %u, "
+ "src_texture %p, src_sub_resource_idx %u, src_box %s.\n",
+ dst_texture, dst_sub_resource_idx, dst_x, dst_y, dst_z,
+ src_texture, src_sub_resource_idx, debug_box(src_box));
+
+ context = context_acquire(dst_texture->resource.device, NULL, 0);
+
+ /* Only load the sub-resource for partial updates. For newly allocated
+ * textures the texture wouldn't be the current location, and we'd upload
+ * zeroes just to overwrite them again. */
+ update_w = src_box->right - src_box->left;
+ update_h = src_box->bottom - src_box->top;
+ update_d = src_box->back - src_box->front;
+ dst_level = dst_sub_resource_idx % dst_texture->level_count;
+ if (update_w == wined3d_texture_get_level_width(dst_texture, dst_level)
+ && update_h == wined3d_texture_get_level_height(dst_texture, dst_level)
+ && update_d == wined3d_texture_get_level_depth(dst_texture, dst_level))
+ wined3d_texture_prepare_texture(dst_texture, context, FALSE);
+ else
+ wined3d_texture_load_location(dst_texture, dst_sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB);
+ wined3d_texture_bind_and_dirtify(dst_texture, context, FALSE);
+
+ src_level = src_sub_resource_idx % src_texture->level_count;
+ wined3d_texture_get_memory(src_texture, src_sub_resource_idx, &data,
+ src_texture->sub_resources[src_sub_resource_idx].locations);
+ wined3d_texture_get_pitch(src_texture, src_level, &src_row_pitch, &src_slice_pitch);
+
+ wined3d_texture_upload_data(dst_texture, dst_sub_resource_idx, context, src_texture->resource.format,
+ src_box, wined3d_const_bo_address(&data), src_row_pitch, src_slice_pitch, dst_x, dst_y, dst_z, FALSE);
+
+ context_release(context);
+
+ wined3d_texture_validate_location(dst_texture, dst_sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB);
+ wined3d_texture_invalidate_location(dst_texture, dst_sub_resource_idx, ~WINED3D_LOCATION_TEXTURE_RGB);
+}
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index e5a61e7af0e..24d923265e3 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -3305,6 +3305,9 @@ void wined3d_texture_upload_data(struct wined3d_texture *texture, unsigned int s
struct wined3d_context *context, const struct wined3d_format *format, const struct wined3d_box *src_box,
const struct wined3d_const_bo_address *data, unsigned int row_pitch, unsigned int slice_pitch,
unsigned int dst_x, unsigned int dst_y, unsigned int dst_z, BOOL srgb) DECLSPEC_HIDDEN;
+void wined3d_texture_upload_from_texture(struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx,
+ unsigned int dst_x, unsigned int dst_y, unsigned int dst_z, struct wined3d_texture *src_texture,
+ unsigned int src_sub_resource_idx, const struct wined3d_box *src_box) DECLSPEC_HIDDEN;
void wined3d_texture_validate_location(struct wined3d_texture *texture,
unsigned int sub_resource_idx, DWORD location) DECLSPEC_HIDDEN;
--
2.11.0
1
0
16 Apr '18
From: Matteo Bruni <mbruni(a)codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
dlls/wined3d/glsl_shader.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index e27b0ff0603..e839369f11c 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -12270,8 +12270,8 @@ static GLuint glsl_blitter_generate_program(struct wined3d_glsl_blitter *blitter
"\n"
"void main()\n"
"{\n";
+ struct wined3d_string_buffer *buffer, *string;
GLuint program, vshader_id, fshader_id;
- struct wined3d_string_buffer *buffer;
const char *tex_type, *swizzle, *ptr;
unsigned int i;
@@ -12314,9 +12314,14 @@ static GLuint glsl_blitter_generate_program(struct wined3d_glsl_blitter *blitter
declare_in_varying(gl_info, buffer, FALSE, "vec3 out_texcoord;\n");
if (!needs_legacy_glsl_syntax(gl_info))
shader_addline(buffer, "out vec4 ps_out[1];\n");
+
shader_addline(buffer, fshader_header);
- shader_addline(buffer, " %s[0] = texture%s(sampler, out_texcoord.%s);\n",
- get_fragment_output(gl_info), needs_legacy_glsl_syntax(gl_info) ? tex_type : "", swizzle);
+ string = string_buffer_get(&blitter->string_buffers);
+ string_buffer_sprintf(string, "%s[0]", get_fragment_output(gl_info));
+ shader_addline(buffer, " %s = texture%s(sampler, out_texcoord.%s);\n",
+ string->buffer, needs_legacy_glsl_syntax(gl_info) ? tex_type : "", swizzle);
+ shader_glsl_color_correction_ext(buffer, string->buffer, WINED3DSP_WRITEMASK_ALL, args->fixup);
+ string_buffer_release(&blitter->string_buffers, string);
shader_addline(buffer, "}\n");
ptr = buffer->buffer;
@@ -12436,9 +12441,9 @@ static BOOL glsl_blitter_supported(enum wined3d_blit_op blit_op, const struct wi
return FALSE;
}
- if (!is_identity_fixup(src_format->color_fixup))
+ if (is_complex_fixup(src_format->color_fixup))
{
- TRACE("Source fixups are not supported.\n");
+ TRACE("Complex source fixups are not supported.\n");
return FALSE;
}
--
2.11.0
1
0
[PATCH 1/5] wined3d: Remove unused return values from the YUV shader generation helpers in the ARBfp blitter.
by Henri Verbeet 16 Apr '18
by Henri Verbeet 16 Apr '18
16 Apr '18
From: Matteo Bruni <mbruni(a)codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
dlls/wined3d/arb_program_shader.c | 52 ++++++++++++---------------------------
1 file changed, 16 insertions(+), 36 deletions(-)
diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index 2b796cd21bc..ea07c3b2e35 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -6936,8 +6936,8 @@ static void arbfp_blitter_destroy(struct wined3d_blitter *blitter, struct wined3
heap_free(arbfp_blitter);
}
-static BOOL gen_planar_yuv_read(struct wined3d_string_buffer *buffer, const struct arbfp_blit_type *type,
- char *luminance)
+static void gen_planar_yuv_read(struct wined3d_string_buffer *buffer,
+ const struct arbfp_blit_type *type, char *luminance)
{
char chroma;
const char *tex, *texinstr = "TXP";
@@ -6985,13 +6985,12 @@ static BOOL gen_planar_yuv_read(struct wined3d_string_buffer *buffer, const stru
shader_addline(buffer, "FLR texcrd.x, texcrd.x;\n");
shader_addline(buffer, "ADD texcrd.x, texcrd.x, coef.y;\n");
- /* Divide the x coordinate by 0.5 and get the fraction. This gives 0.25 and 0.75 for the
- * even and odd pixels respectively
- */
+ /* Multiply the x coordinate by 0.5 and get the fraction. This gives 0.25
+ * and 0.75 for the even and odd pixels respectively. */
shader_addline(buffer, "MUL texcrd2, texcrd, coef.y;\n");
shader_addline(buffer, "FRC texcrd2, texcrd2;\n");
- /* Sample Pixel 1 */
+ /* Sample Pixel 1. */
shader_addline(buffer, "%s luminance, texcrd, texture[0], %s;\n", texinstr, tex);
/* Put the value into either of the chroma values */
@@ -7020,12 +7019,10 @@ static BOOL gen_planar_yuv_read(struct wined3d_string_buffer *buffer, const stru
/* This gives the correctly filtered luminance value */
shader_addline(buffer, "TEX luminance, fragment.texcoord[0], texture[0], %s;\n", tex);
-
- return TRUE;
}
-static BOOL gen_yv12_read(struct wined3d_string_buffer *buffer, const struct arbfp_blit_type *type,
- char *luminance)
+static void gen_yv12_read(struct wined3d_string_buffer *buffer,
+ const struct arbfp_blit_type *type, char *luminance)
{
const char *tex;
static const float yv12_coef[]
@@ -7087,7 +7084,6 @@ static BOOL gen_yv12_read(struct wined3d_string_buffer *buffer, const struct arb
*/
if (type->res_type == WINED3D_GL_RES_TYPE_TEX_2D)
{
-
shader_addline(buffer, "RCP chroma.w, size.y;\n");
shader_addline(buffer, "MUL texcrd2.y, texcrd.y, size.y;\n");
@@ -7095,7 +7091,7 @@ static BOOL gen_yv12_read(struct wined3d_string_buffer *buffer, const struct arb
shader_addline(buffer, "FLR texcrd2.y, texcrd2.y;\n");
shader_addline(buffer, "MAD texcrd.y, texcrd.y, yv12_coef.y, yv12_coef.x;\n");
- /* Read odd lines from the right side(add size * 0.5 to the x coordinate */
+ /* Read odd lines from the right side (add size * 0.5 to the x coordinate). */
shader_addline(buffer, "ADD texcrd2.x, texcrd2.y, yv12_coef.y;\n"); /* To avoid 0.5 == 0.5 comparisons */
shader_addline(buffer, "FRC texcrd2.x, texcrd2.x;\n");
shader_addline(buffer, "SGE texcrd2.x, texcrd2.x, coef.y;\n");
@@ -7109,11 +7105,11 @@ static BOOL gen_yv12_read(struct wined3d_string_buffer *buffer, const struct arb
}
else
{
- /* Read from [size - size+size/4] */
+ /* The y coordinate for V is in the range [size, size + size / 4). */
shader_addline(buffer, "FLR texcrd.y, texcrd.y;\n");
shader_addline(buffer, "MAD texcrd.y, texcrd.y, coef.w, size.y;\n");
- /* Read odd lines from the right side(add size * 0.5 to the x coordinate */
+ /* Read odd lines from the right side (add size * 0.5 to the x coordinate). */
shader_addline(buffer, "ADD texcrd2.x, texcrd.y, yv12_coef.y;\n"); /* To avoid 0.5 == 0.5 comparisons */
shader_addline(buffer, "FRC texcrd2.x, texcrd2.x;\n");
shader_addline(buffer, "SGE texcrd2.x, texcrd2.x, coef.y;\n");
@@ -7169,12 +7165,10 @@ static BOOL gen_yv12_read(struct wined3d_string_buffer *buffer, const struct arb
shader_addline(buffer, "TEX luminance, texcrd, texture[0], %s;\n", tex);
}
*luminance = 'a';
-
- return TRUE;
}
-static BOOL gen_nv12_read(struct wined3d_string_buffer *buffer, const struct arbfp_blit_type *type,
- char *luminance)
+static void gen_nv12_read(struct wined3d_string_buffer *buffer,
+ const struct arbfp_blit_type *type, char *luminance)
{
const char *tex;
static const float nv12_coef[]
@@ -7250,7 +7244,7 @@ static BOOL gen_nv12_read(struct wined3d_string_buffer *buffer, const struct arb
}
else
{
- /* Read from [size - size+size/2] */
+ /* The y coordinate for chroma is in the range [size, size + size / 2). */
shader_addline(buffer, "MAD texcrd.y, texcrd.y, coef.y, size.y;\n");
shader_addline(buffer, "FLR texcrd.x, texcrd.x;\n");
@@ -7305,8 +7299,6 @@ static BOOL gen_nv12_read(struct wined3d_string_buffer *buffer, const struct arb
shader_addline(buffer, "TEX luminance, texcrd, texture[0], %s;\n", tex);
}
*luminance = 'a';
-
- return TRUE;
}
/* Context activation is done by the caller. */
@@ -7472,27 +7464,15 @@ static GLuint gen_yuv_shader(const struct wined3d_gl_info *gl_info, const struct
{
case COMPLEX_FIXUP_UYVY:
case COMPLEX_FIXUP_YUY2:
- if (!gen_planar_yuv_read(&buffer, type, &luminance_component))
- {
- string_buffer_free(&buffer);
- return 0;
- }
+ gen_planar_yuv_read(&buffer, type, &luminance_component);
break;
case COMPLEX_FIXUP_YV12:
- if (!gen_yv12_read(&buffer, type, &luminance_component))
- {
- string_buffer_free(&buffer);
- return 0;
- }
+ gen_yv12_read(&buffer, type, &luminance_component);
break;
case COMPLEX_FIXUP_NV12:
- if (!gen_nv12_read(&buffer, type, &luminance_component))
- {
- string_buffer_free(&buffer);
- return 0;
- }
+ gen_nv12_read(&buffer, type, &luminance_component);
break;
default:
--
2.11.0
1
0
16 Apr '18
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
v3: fixed ddraw test failure
dlls/d3d11/device.c | 4 +-
dlls/d3d8/device.c | 2 +-
dlls/d3d9/device.c | 2 +-
dlls/ddraw/device.c | 2 +-
dlls/wined3d/arb_program_shader.c | 2 +-
dlls/wined3d/cs.c | 35 +++++++-----
dlls/wined3d/device.c | 52 ++++++++++-------
dlls/wined3d/glsl_shader.c | 44 +++++++++++----
dlls/wined3d/state.c | 92 +++++++++++++++++++++++--------
dlls/wined3d/stateblock.c | 12 ++--
dlls/wined3d/utils.c | 17 +++---
dlls/wined3d/wined3d.spec | 2 +-
dlls/wined3d/wined3d_private.h | 29 ++++++----
include/wine/wined3d.h | 5 +-
14 files changed, 202 insertions(+), 98 deletions(-)
diff --git a/dlls/d3d11/device.c b/dlls/d3d11/device.c
index 1fe62975d5..659b33c101 100644
--- a/dlls/d3d11/device.c
+++ b/dlls/d3d11/device.c
@@ -979,7 +979,7 @@ static void STDMETHODCALLTYPE d3d11_immediate_context_RSSetViewports(ID3D11Devic
wined3d_vp.max_z = viewports[0].MaxDepth;
wined3d_mutex_lock();
- wined3d_device_set_viewport(device->wined3d_device, &wined3d_vp);
+ wined3d_device_set_viewports(device->wined3d_device, 1, &wined3d_vp);
wined3d_mutex_unlock();
}
@@ -4167,7 +4167,7 @@ static void STDMETHODCALLTYPE d3d10_device_RSSetViewports(ID3D10Device1 *iface,
wined3d_vp.max_z = viewports[0].MaxDepth;
wined3d_mutex_lock();
- wined3d_device_set_viewport(device->wined3d_device, &wined3d_vp);
+ wined3d_device_set_viewports(device->wined3d_device, 1, &wined3d_vp);
wined3d_mutex_unlock();
}
diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c
index 65480876d3..3bdb278ec5 100644
--- a/dlls/d3d8/device.c
+++ b/dlls/d3d8/device.c
@@ -1650,7 +1650,7 @@ static HRESULT WINAPI d3d8_device_SetViewport(IDirect3DDevice8 *iface, const D3D
vp.min_z = viewport->MinZ;
vp.max_z = viewport->MaxZ;
- wined3d_device_set_viewport(device->wined3d_device, &vp);
+ wined3d_device_set_viewports(device->wined3d_device, 1, &vp);
wined3d_mutex_unlock();
return D3D_OK;
diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c
index d533afb9b3..5c0d6779c5 100644
--- a/dlls/d3d9/device.c
+++ b/dlls/d3d9/device.c
@@ -2068,7 +2068,7 @@ static HRESULT WINAPI d3d9_device_SetViewport(IDirect3DDevice9Ex *iface, const D
vp.max_z = viewport->MaxZ;
wined3d_mutex_lock();
- wined3d_device_set_viewport(device->wined3d_device, &vp);
+ wined3d_device_set_viewports(device->wined3d_device, 1, &vp);
wined3d_mutex_unlock();
return D3D_OK;
diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c
index 35995625e4..23c61c5d80 100644
--- a/dlls/ddraw/device.c
+++ b/dlls/ddraw/device.c
@@ -5333,7 +5333,7 @@ static HRESULT d3d_device7_SetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *vi
vp.min_z = viewport->dvMinZ;
vp.max_z = viewport->dvMaxZ;
- wined3d_device_set_viewport(device->wined3d_device, &vp);
+ wined3d_device_set_viewports(device->wined3d_device, 1, &vp);
wined3d_mutex_unlock();
return D3D_OK;
diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index 9339c1362e..2b796cd21b 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -611,7 +611,7 @@ static void shader_arb_vs_local_constants(const struct arb_vs_compiled_shader *g
unsigned char i;
/* Upload the position fixup */
- shader_get_position_fixup(context, state, position_fixup);
+ shader_get_position_fixup(context, state, 1, position_fixup);
GL_EXTCALL(glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, gl_shader->pos_fixup, position_fixup));
if (!gl_shader->num_int_consts) return;
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index 2f0c4ed52e..221e51eb94 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -33,7 +33,7 @@ enum wined3d_cs_op
WINED3D_CS_OP_DRAW,
WINED3D_CS_OP_FLUSH,
WINED3D_CS_OP_SET_PREDICATION,
- WINED3D_CS_OP_SET_VIEWPORT,
+ WINED3D_CS_OP_SET_VIEWPORTS,
WINED3D_CS_OP_SET_SCISSOR_RECT,
WINED3D_CS_OP_SET_RENDERTARGET_VIEW,
WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW,
@@ -138,10 +138,11 @@ struct wined3d_cs_set_predication
BOOL value;
};
-struct wined3d_cs_set_viewport
+struct wined3d_cs_set_viewports
{
enum wined3d_cs_op opcode;
- struct wined3d_viewport viewport;
+ unsigned int viewport_count;
+ struct wined3d_viewport viewports[1];
};
struct wined3d_cs_set_scissor_rect
@@ -530,7 +531,7 @@ void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT *
{
unsigned int rt_count = cs->device->adapter->gl_info.limits.buffers;
const struct wined3d_state *state = &cs->device->state;
- const struct wined3d_viewport *vp = &state->viewport;
+ const struct wined3d_viewport *vp = &state->viewports[0];
struct wined3d_rendertarget_view *view;
struct wined3d_cs_clear *op;
RECT view_rect;
@@ -961,21 +962,29 @@ void wined3d_cs_emit_set_predication(struct wined3d_cs *cs, struct wined3d_query
cs->ops->submit(cs, WINED3D_CS_QUEUE_DEFAULT);
}
-static void wined3d_cs_exec_set_viewport(struct wined3d_cs *cs, const void *data)
+static void wined3d_cs_exec_set_viewports(struct wined3d_cs *cs, const void *data)
{
- const struct wined3d_cs_set_viewport *op = data;
+ const struct wined3d_cs_set_viewports *op = data;
- cs->state.viewport = op->viewport;
+ if (op->viewport_count)
+ memcpy(cs->state.viewports, op->viewports, op->viewport_count * sizeof(*op->viewports));
+ else
+ memset(cs->state.viewports, 0, sizeof(*cs->state.viewports));
+ cs->state.viewport_count = op->viewport_count;
device_invalidate_state(cs->device, STATE_VIEWPORT);
}
-void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport *viewport)
+void wined3d_cs_emit_set_viewports(struct wined3d_cs *cs, unsigned int viewport_count,
+ const struct wined3d_viewport *viewports)
{
- struct wined3d_cs_set_viewport *op;
+ struct wined3d_cs_set_viewports *op;
- op = cs->ops->require_space(cs, sizeof(*op), WINED3D_CS_QUEUE_DEFAULT);
- op->opcode = WINED3D_CS_OP_SET_VIEWPORT;
- op->viewport = *viewport;
+ op = cs->ops->require_space(cs, FIELD_OFFSET(struct wined3d_cs_set_viewports, viewports[viewport_count]),
+ WINED3D_CS_QUEUE_DEFAULT);
+ op->opcode = WINED3D_CS_OP_SET_VIEWPORTS;
+ if (viewport_count)
+ memcpy(op->viewports, viewports, viewport_count * sizeof(*viewports));
+ op->viewport_count = viewport_count;
cs->ops->submit(cs, WINED3D_CS_QUEUE_DEFAULT);
}
@@ -2401,7 +2410,7 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void
/* WINED3D_CS_OP_DRAW */ wined3d_cs_exec_draw,
/* WINED3D_CS_OP_FLUSH */ wined3d_cs_exec_flush,
/* WINED3D_CS_OP_SET_PREDICATION */ wined3d_cs_exec_set_predication,
- /* WINED3D_CS_OP_SET_VIEWPORT */ wined3d_cs_exec_set_viewport,
+ /* WINED3D_CS_OP_SET_VIEWPORTS */ wined3d_cs_exec_set_viewports,
/* WINED3D_CS_OP_SET_SCISSOR_RECT */ wined3d_cs_exec_set_scissor_rect,
/* WINED3D_CS_OP_SET_RENDERTARGET_VIEW */ wined3d_cs_exec_set_rendertarget_view,
/* WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW */ wined3d_cs_exec_set_depth_stencil_view,
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 4ff1f06c87..4ee948019b 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -1910,13 +1910,24 @@ INT CDECL wined3d_device_get_base_vertex_index(const struct wined3d_device *devi
return device->state.base_vertex_index;
}
-void CDECL wined3d_device_set_viewport(struct wined3d_device *device, const struct wined3d_viewport *viewport)
+void CDECL wined3d_device_set_viewports(struct wined3d_device *device, unsigned int viewport_count,
+ const struct wined3d_viewport *viewports)
{
- TRACE("device %p, viewport %p.\n", device, viewport);
- TRACE("x %.8e, y %.8e, w %.8e, h %.8e, min_z %.8e, max_z %.8e.\n",
- viewport->x, viewport->y, viewport->width, viewport->height, viewport->min_z, viewport->max_z);
+ unsigned int i;
+
+ TRACE("device %p, viewport_count %u, viewports %p.\n", device, viewport_count, viewports);
+
+ for (i = 0; i < viewport_count; ++i)
+ {
+ TRACE("%u: x %.8e, y %.8e, w %.8e, h %.8e, min_z %.8e, max_z %.8e.\n", i, viewports[i].x, viewports[i].y,
+ viewports[i].width, viewports[i].height, viewports[i].min_z, viewports[i].max_z);
+ }
- device->update_state->viewport = *viewport;
+ if (viewport_count)
+ memcpy(device->update_state->viewports, viewports, viewport_count * sizeof(*viewports));
+ else
+ memset(device->update_state->viewports, 0, sizeof(device->update_state->viewports));
+ device->update_state->viewport_count = viewport_count;
/* Handle recording of state blocks */
if (device->recording)
@@ -1926,14 +1937,14 @@ void CDECL wined3d_device_set_viewport(struct wined3d_device *device, const stru
return;
}
- wined3d_cs_emit_set_viewport(device->cs, viewport);
+ wined3d_cs_emit_set_viewports(device->cs, viewport_count, viewports);
}
void CDECL wined3d_device_get_viewport(const struct wined3d_device *device, struct wined3d_viewport *viewport)
{
TRACE("device %p, viewport %p.\n", device, viewport);
- *viewport = device->state.viewport;
+ *viewport = device->state.viewports[0];
}
static void resolve_depth_buffer(struct wined3d_device *device)
@@ -4449,19 +4460,19 @@ HRESULT CDECL wined3d_device_set_rendertarget_view(struct wined3d_device *device
{
struct wined3d_state *state = &device->state;
- state->viewport.x = 0;
- state->viewport.y = 0;
- state->viewport.width = view->width;
- state->viewport.height = view->height;
- state->viewport.min_z = 0.0f;
- state->viewport.max_z = 1.0f;
- wined3d_cs_emit_set_viewport(device->cs, &state->viewport);
+ state->viewports[0].x = 0;
+ state->viewports[0].y = 0;
+ state->viewports[0].width = view->width;
+ state->viewports[0].height = view->height;
+ state->viewports[0].min_z = 0.0f;
+ state->viewports[0].max_z = 1.0f;
+ state->viewport_count = 1;
+ wined3d_cs_emit_set_viewports(device->cs, 1, state->viewports);
SetRect(&state->scissor_rect, 0, 0, view->width, view->height);
wined3d_cs_emit_set_scissor_rect(device->cs, &state->scissor_rect);
}
-
prev = device->fb.render_targets[view_idx];
if (view == prev)
return WINED3D_OK;
@@ -4961,11 +4972,12 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
wined3d_device_set_rendertarget_view(device, 0, view, FALSE);
/* Note the min_z / max_z is not reset. */
- state->viewport.x = 0;
- state->viewport.y = 0;
- state->viewport.width = view->width;
- state->viewport.height = view->height;
- wined3d_cs_emit_set_viewport(device->cs, &state->viewport);
+ state->viewports[0].x = 0;
+ state->viewports[0].y = 0;
+ state->viewports[0].width = view->width;
+ state->viewports[0].height = view->height;
+ state->viewport_count = 1;
+ wined3d_cs_emit_set_viewports(device->cs, 1, state->viewports);
SetRect(&state->scissor_rect, 0, 0, view->width, view->height);
wined3d_cs_emit_set_scissor_rect(device->cs, &state->scissor_rect);
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 583c014e14..e27b0ff060 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -1756,7 +1756,7 @@ static void shader_glsl_load_constants(void *shader_priv, struct wined3d_context
const struct wined3d_shader *pshader = state->shader[WINED3D_SHADER_TYPE_PIXEL];
const struct wined3d_gl_info *gl_info = context->gl_info;
struct shader_glsl_priv *priv = shader_priv;
- float position_fixup[4];
+ float position_fixup[4 * WINED3D_MAX_VIEWPORTS];
DWORD update_mask;
struct glsl_shader_prog_link *prog = ctx_data->glsl_program;
@@ -1793,9 +1793,11 @@ static void shader_glsl_load_constants(void *shader_priv, struct wined3d_context
if (update_mask & WINED3D_SHADER_CONST_POS_FIXUP)
{
- shader_get_position_fixup(context, state, position_fixup);
+ unsigned int fixup_count = state->shader[WINED3D_SHADER_TYPE_GEOMETRY] ?
+ max(state->viewport_count, 1) : 1;
+ shader_get_position_fixup(context, state, fixup_count, position_fixup);
if (state->shader[WINED3D_SHADER_TYPE_GEOMETRY])
- GL_EXTCALL(glUniform4fv(prog->gs.pos_fixup_location, 1, position_fixup));
+ GL_EXTCALL(glUniform4fv(prog->gs.pos_fixup_location, fixup_count, position_fixup));
else if (state->shader[WINED3D_SHADER_TYPE_DOMAIN])
GL_EXTCALL(glUniform4fv(prog->ds.pos_fixup_location, 1, position_fixup));
else
@@ -3806,7 +3808,7 @@ static void PRINTF_ATTR(9, 10) shader_glsl_gen_sample_code(const struct wined3d_
shader_glsl_color_correction(ins, fixup);
}
-static void shader_glsl_fixup_position(struct wined3d_string_buffer *buffer)
+static void shader_glsl_fixup_position(struct wined3d_string_buffer *buffer, BOOL use_viewport_index)
{
/* Write the final position.
*
@@ -3815,8 +3817,16 @@ static void shader_glsl_fixup_position(struct wined3d_string_buffer *buffer)
* pos_fixup. pos_fixup.y contains 1.0 or -1.0 to turn the rendering
* upside down for offscreen rendering. pos_fixup.x contains 1.0 to allow
* a MAD. */
- shader_addline(buffer, "gl_Position.y = gl_Position.y * pos_fixup.y;\n");
- shader_addline(buffer, "gl_Position.xy += pos_fixup.zw * gl_Position.ww;\n");
+ if (use_viewport_index)
+ {
+ shader_addline(buffer, "gl_Position.y = gl_Position.y * pos_fixup[gl_ViewportIndex].y;\n");
+ shader_addline(buffer, "gl_Position.xy += pos_fixup[gl_ViewportIndex].zw * gl_Position.ww;\n");
+ }
+ else
+ {
+ shader_addline(buffer, "gl_Position.y = gl_Position.y * pos_fixup.y;\n");
+ shader_addline(buffer, "gl_Position.xy += pos_fixup.zw * gl_Position.ww;\n");
+ }
/* Z coord [0;1]->[-1;1] mapping, see comment in get_projection_matrix()
* in utils.c
@@ -5143,9 +5153,10 @@ static void shader_glsl_emit(const struct wined3d_shader_instruction *ins)
{
unsigned int stream = ins->handler_idx == WINED3DSIH_EMIT ? 0 : ins->src[0].reg.idx[0].offset;
+ shader_addline(ins->ctx->buffer, "gl_ViewportIndex = 0;\n");
shader_addline(ins->ctx->buffer, "setup_gs_output(gs_out);\n");
if (!ins->ctx->gl_info->supported[ARB_CLIP_CONTROL])
- shader_glsl_fixup_position(ins->ctx->buffer);
+ shader_glsl_fixup_position(ins->ctx->buffer, TRUE);
if (!stream)
shader_addline(ins->ctx->buffer, "EmitVertex();\n");
@@ -6766,6 +6777,14 @@ static void shader_glsl_input_pack(const struct wined3d_shader *shader, struct w
else
FIXME("ARB_fragment_layer_viewport is not supported.\n");
}
+ else if (input->sysval_semantic == WINED3D_SV_VIEWPORT_ARRAY_INDEX && !semantic_idx)
+ {
+ if (gl_info->supported[ARB_VIEWPORT_ARRAY])
+ shader_addline(buffer, "ps_in[%u]%s = intBitsToFloat(gl_ViewportIndex);\n",
+ input->register_idx, reg_mask);
+ else
+ FIXME("ARB_viewport_array is not supported.\n");
+ }
else
{
if (input->sysval_semantic)
@@ -7057,6 +7076,11 @@ static void shader_glsl_setup_sm3_rasterizer_input(struct shader_glsl_priv *priv
shader_addline(buffer, "gl_Layer = floatBitsToInt(outputs[%u])%s;\n",
output->register_idx, reg_mask);
}
+ else if (output->sysval_semantic == WINED3D_SV_VIEWPORT_ARRAY_INDEX && !semantic_idx)
+ {
+ shader_addline(buffer, "gl_ViewportIndex = floatBitsToInt(outputs[%u])%s;\n",
+ output->register_idx, reg_mask);
+ }
else if (output->sysval_semantic == WINED3D_SV_CLIP_DISTANCE)
{
shader_glsl_generate_clip_or_cull_distances(buffer, output, reg_maps_out->clip_distance_mask);
@@ -7830,7 +7854,7 @@ static void shader_glsl_generate_vs_epilogue(const struct wined3d_gl_info *gl_in
shader_addline(buffer, "gl_PointSize = clamp(ffp_point.size, ffp_point.size_min, ffp_point.size_max);\n");
if (args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL && !gl_info->supported[ARB_CLIP_CONTROL])
- shader_glsl_fixup_position(buffer);
+ shader_glsl_fixup_position(buffer, FALSE);
}
/* Context activation is done by the caller. */
@@ -8068,7 +8092,7 @@ static void shader_glsl_generate_ds_epilogue(const struct wined3d_gl_info *gl_in
shader_addline(buffer, "setup_ds_output(ds_out);\n");
if (args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL && !gl_info->supported[ARB_CLIP_CONTROL])
- shader_glsl_fixup_position(buffer);
+ shader_glsl_fixup_position(buffer, FALSE);
}
static GLuint shader_glsl_generate_domain_shader(const struct wined3d_context *context,
@@ -8193,7 +8217,7 @@ static GLuint shader_glsl_generate_geometry_shader(const struct wined3d_context
shader_addline(buffer, "in shader_in_out { vec4 reg[%u]; } shader_in[];\n", shader->limits->packed_input);
if (!gl_info->supported[ARB_CLIP_CONTROL])
- shader_addline(buffer, "uniform vec4 pos_fixup;\n");
+ shader_addline(buffer, "uniform vec4 pos_fixup[%u];\n", WINED3D_MAX_VIEWPORTS);
if (is_rasterization_disabled(shader))
{
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index 83cc484be8..5a37fadabd 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -4514,21 +4514,24 @@ static void vertexdeclaration(struct wined3d_context *context, const struct wine
}
}
-static void get_viewport(struct wined3d_context *context, const struct wined3d_state *state,
- struct wined3d_viewport *viewport)
+static void get_viewports(struct wined3d_context *context, const struct wined3d_state *state,
+ unsigned int viewport_count, struct wined3d_viewport *viewports)
{
const struct wined3d_rendertarget_view *depth_stencil = state->fb->depth_stencil;
const struct wined3d_rendertarget_view *target = state->fb->render_targets[0];
- unsigned int width, height;
+ unsigned int width, height, i;
- *viewport = state->viewport;
-
- if (target)
+ for (i = 0; i < viewport_count; ++i)
{
- if (viewport->width > target->width)
- viewport->width = target->width;
- if (viewport->height > target->height)
- viewport->height = target->height;
+ viewports[i] = state->viewports[i];
+
+ if (target)
+ {
+ if (viewports[i].width > target->width)
+ viewports[i].width = target->width;
+ if (viewports[i].height > target->height)
+ viewports[i].height = target->height;
+ }
}
/*
@@ -4552,22 +4555,45 @@ static void get_viewport(struct wined3d_context *context, const struct wined3d_s
return;
}
- viewport->y = height - (viewport->y + viewport->height);
+ for (i = 0; i < viewport_count; ++i)
+ viewports[i].y = height - (viewports[i].y + viewports[i].height);
}
static void viewport_miscpart(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
{
const struct wined3d_gl_info *gl_info = context->gl_info;
- struct wined3d_viewport vp;
+ struct wined3d_viewport vp[WINED3D_MAX_VIEWPORTS];
+
+ if (gl_info->supported[ARB_VIEWPORT_ARRAY])
+ {
+ unsigned int i, reset_count = 0;
- get_viewport(context, state, &vp);
+ get_viewports(context, state, state->viewport_count, vp);
+ for (i = 0; i < state->viewport_count; ++i)
+ {
+ GL_EXTCALL(glDepthRangeIndexed(i, vp[i].min_z, vp[i].max_z));
+ GL_EXTCALL(glViewportIndexedf(i, vp[i].x, vp[i].y, vp[i].width, vp[i].height));
+ }
- gl_info->gl_ops.gl.p_glDepthRange(vp.min_z, vp.max_z);
+ if (context->viewport_count > state->viewport_count)
+ reset_count = context->viewport_count - state->viewport_count;
- if (gl_info->supported[ARB_VIEWPORT_ARRAY])
- GL_EXTCALL(glViewportIndexedf(0, vp.x, vp.y, vp.width, vp.height));
+ if (reset_count)
+ {
+ static const GLfloat reset[4 * WINED3D_MAX_VIEWPORTS];
+ static const GLdouble resetd[2 * WINED3D_MAX_VIEWPORTS];
+
+ GL_EXTCALL(glDepthRangeArrayv(state->viewport_count, reset_count, resetd));
+ GL_EXTCALL(glViewportArrayv(state->viewport_count, reset_count, reset));
+ }
+ context->viewport_count = state->viewport_count;
+ }
else
- gl_info->gl_ops.gl.p_glViewport(vp.x, vp.y, vp.width, vp.height);
+ {
+ get_viewports(context, state, 1, vp);
+ gl_info->gl_ops.gl.p_glDepthRange(vp[0].min_z, vp[0].max_z);
+ gl_info->gl_ops.gl.p_glViewport(vp[0].x, vp[0].y, vp[0].width, vp[0].height);
+ }
checkGLcall("setting clip space and viewport");
}
@@ -4578,16 +4604,34 @@ static void viewport_miscpart_cc(struct wined3d_context *context,
float pixel_center_offset = context->d3d_info->wined3d_creation_flags
& WINED3D_PIXEL_CENTER_INTEGER ? 63.0f / 128.0f : -1.0f / 128.0f;
const struct wined3d_gl_info *gl_info = context->gl_info;
- struct wined3d_viewport vp;
-
- get_viewport(context, state, &vp);
- vp.x += pixel_center_offset;
- vp.y += pixel_center_offset;
+ struct wined3d_viewport vp[WINED3D_MAX_VIEWPORTS];
+ unsigned int i, reset_count = 0;
- gl_info->gl_ops.gl.p_glDepthRange(vp.min_z, vp.max_z);
+ get_viewports(context, state, state->viewport_count, vp);
GL_EXTCALL(glClipControl(context->render_offscreen ? GL_UPPER_LEFT : GL_LOWER_LEFT, GL_ZERO_TO_ONE));
- GL_EXTCALL(glViewportIndexedf(0, vp.x, vp.y, vp.width, vp.height));
+
+ for (i = 0; i < state->viewport_count; ++i)
+ {
+ vp[i].x += pixel_center_offset;
+ vp[i].y += pixel_center_offset;
+ GL_EXTCALL(glDepthRangeIndexed(i, vp[i].min_z, vp[i].max_z));
+ GL_EXTCALL(glViewportIndexedf(i, vp[i].x, vp[i].y, vp[i].width, vp[i].height));
+ }
+
+ if (context->viewport_count > state->viewport_count)
+ reset_count = context->viewport_count - state->viewport_count;
+
+ if (reset_count)
+ {
+ static const GLfloat reset[4 * WINED3D_MAX_VIEWPORTS];
+ static const GLdouble resetd[2 * WINED3D_MAX_VIEWPORTS];
+
+ GL_EXTCALL(glDepthRangeArrayv(state->viewport_count, reset_count, resetd));
+ GL_EXTCALL(glViewportArrayv(state->viewport_count, reset_count, reset));
+ }
+ context->viewport_count = state->viewport_count;
+
checkGLcall("setting clip space and viewport");
}
diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c
index 4c28eb55e8..23a615fc08 100644
--- a/dlls/wined3d/stateblock.c
+++ b/dlls/wined3d/stateblock.c
@@ -811,11 +811,15 @@ void CDECL wined3d_stateblock_capture(struct wined3d_stateblock *stateblock)
}
if (stateblock->changed.viewport
- && memcmp(&src_state->viewport, &stateblock->state.viewport, sizeof(stateblock->state.viewport)))
+ && (src_state->viewport_count != stateblock->state.viewport_count
+ || memcmp(src_state->viewports, stateblock->state.viewports, src_state->viewport_count * sizeof(stateblock->state.viewports))))
{
- TRACE("Updating viewport.\n");
+ TRACE("Updating viewports.\n");
- stateblock->state.viewport = src_state->viewport;
+ if ((stateblock->state.viewport_count = src_state->viewport_count))
+ memcpy(stateblock->state.viewports, src_state->viewports, sizeof(src_state->viewports));
+ else
+ memset(stateblock->state.viewports, 0, sizeof(*stateblock->state.viewports));
}
if (stateblock->changed.scissorRect && memcmp(&src_state->scissor_rect,
@@ -1055,7 +1059,7 @@ void CDECL wined3d_stateblock_apply(const struct wined3d_stateblock *stateblock)
wined3d_device_set_material(device, &stateblock->state.material);
if (stateblock->changed.viewport)
- wined3d_device_set_viewport(device, &stateblock->state.viewport);
+ wined3d_device_set_viewports(device, stateblock->state.viewport_count, stateblock->state.viewports);
if (stateblock->changed.scissorRect)
wined3d_device_set_scissor_rect(device, &stateblock->state.scissor_rect);
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index 0775f53b7a..c0bb4f17ab 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -4865,10 +4865,10 @@ void get_projection_matrix(const struct wined3d_context *context, const struct w
if (context->last_was_rhw)
{
/* Transform D3D RHW coordinates to OpenGL clip coordinates. */
- float x = state->viewport.x;
- float y = state->viewport.y;
- float w = state->viewport.width;
- float h = state->viewport.height;
+ float x = state->viewports[0].x;
+ float y = state->viewports[0].y;
+ float w = state->viewports[0].width;
+ float h = state->viewports[0].height;
float x_scale = 2.0f / w;
float x_offset = (center_offset - (2.0f * x) - w) / w;
float y_scale = flip ? 2.0f / h : 2.0f / -h;
@@ -4892,10 +4892,10 @@ void get_projection_matrix(const struct wined3d_context *context, const struct w
else
{
float y_scale = flip ? -1.0f : 1.0f;
- float x_offset = center_offset / state->viewport.width;
+ float x_offset = center_offset / state->viewports[0].width;
float y_offset = flip
- ? center_offset / state->viewport.height
- : -center_offset / state->viewport.height;
+ ? center_offset / state->viewports[0].height
+ : -center_offset / state->viewports[0].height;
float z_scale = clip_control ? 1.0f : 2.0f;
float z_offset = clip_control ? 0.0f : -1.0f;
const struct wined3d_matrix projection =
@@ -5095,9 +5095,10 @@ void get_pointsize(const struct wined3d_context *context, const struct wined3d_s
b.d = state->render_states[WINED3D_RS_POINTSCALE_B];
c.d = state->render_states[WINED3D_RS_POINTSCALE_C];
+ /* Always use first viewport, this path does not apply to d3d10/11 multiple viewports case. */
if (state->render_states[WINED3D_RS_POINTSCALEENABLE])
{
- float scale_factor = state->viewport.height * state->viewport.height;
+ float scale_factor = state->viewports[0].height * state->viewports[0].height;
out_att[0] = a.f / scale_factor;
out_att[1] = b.f / scale_factor;
diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec
index 16d22f5263..b4c41cc59a 100644
--- a/dlls/wined3d/wined3d.spec
+++ b/dlls/wined3d/wined3d.spec
@@ -187,7 +187,7 @@
@ cdecl wined3d_device_set_unordered_access_view(ptr long ptr long)
@ cdecl wined3d_device_set_vertex_declaration(ptr ptr)
@ cdecl wined3d_device_set_vertex_shader(ptr ptr)
-@ cdecl wined3d_device_set_viewport(ptr ptr)
+@ cdecl wined3d_device_set_viewports(ptr long ptr)
@ cdecl wined3d_device_set_vs_cb(ptr long ptr)
@ cdecl wined3d_device_set_vs_consts_b(ptr long long ptr)
@ cdecl wined3d_device_set_vs_consts_f(ptr long long ptr)
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 4a27b08e72..e5a61e7af0 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1990,6 +1990,8 @@ struct wined3d_context
GLfloat fog_coord_value;
GLfloat color[4], fogstart, fogend, fogcolor[4];
GLuint dummy_arbfp_prog;
+
+ unsigned int viewport_count;
};
struct wined3d_fb_state
@@ -2851,7 +2853,8 @@ struct wined3d_state
struct wined3d_matrix transforms[HIGHEST_TRANSFORMSTATE + 1];
struct wined3d_vec4 clip_planes[MAX_CLIP_DISTANCES];
struct wined3d_material material;
- struct wined3d_viewport viewport;
+ struct wined3d_viewport viewports[WINED3D_MAX_VIEWPORTS];
+ unsigned int viewport_count;
RECT scissor_rect;
/* Light hashmap. Collisions are handled using linked lists. */
@@ -3604,7 +3607,7 @@ void wined3d_cs_emit_set_unordered_access_view(struct wined3d_cs *cs, enum wined
unsigned int initial_count) DECLSPEC_HIDDEN;
void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs,
struct wined3d_vertex_declaration *declaration) DECLSPEC_HIDDEN;
-void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport *viewport) DECLSPEC_HIDDEN;
+void wined3d_cs_emit_set_viewports(struct wined3d_cs *cs, unsigned int viewport_count, const struct wined3d_viewport *viewports) DECLSPEC_HIDDEN;
void wined3d_cs_emit_unload_resource(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN;
void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_resource *resource,
unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch,
@@ -4107,24 +4110,28 @@ static inline BOOL shader_is_scalar(const struct wined3d_shader_register *reg)
}
static inline void shader_get_position_fixup(const struct wined3d_context *context,
- const struct wined3d_state *state, float *position_fixup)
+ const struct wined3d_state *state, unsigned int fixup_count, float *position_fixup)
{
float center_offset;
+ unsigned int i;
if (context->d3d_info->wined3d_creation_flags & WINED3D_PIXEL_CENTER_INTEGER)
center_offset = 63.0f / 64.0f;
else
center_offset = -1.0f / 64.0f;
- position_fixup[0] = 1.0f;
- position_fixup[1] = 1.0f;
- position_fixup[2] = center_offset / state->viewport.width;
- position_fixup[3] = -center_offset / state->viewport.height;
-
- if (context->render_offscreen)
+ for (i = 0; i < fixup_count; ++i)
{
- position_fixup[1] *= -1.0f;
- position_fixup[3] *= -1.0f;
+ position_fixup[4 * i ] = 1.0f;
+ position_fixup[4 * i + 1] = 1.0f;
+ position_fixup[4 * i + 2] = center_offset / state->viewports[i].width;
+ position_fixup[4 * i + 3] = -center_offset / state->viewports[i].height;
+
+ if (context->render_offscreen)
+ {
+ position_fixup[4 * i + 1] *= -1.0f;
+ position_fixup[4 * i + 3] *= -1.0f;
+ }
}
}
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h
index 446e98b96f..3539b4eb06 100644
--- a/include/wine/wined3d.h
+++ b/include/wine/wined3d.h
@@ -1561,6 +1561,8 @@ enum wined3d_shader_byte_code_format
#define WINED3D_VIEW_TEXTURE_CUBE 0x00000008
#define WINED3D_VIEW_TEXTURE_ARRAY 0x00000010
+#define WINED3D_MAX_VIEWPORTS 16
+
struct wined3d_display_mode
{
UINT width;
@@ -2440,7 +2442,8 @@ void __cdecl wined3d_device_set_unordered_access_view(struct wined3d_device *dev
void __cdecl wined3d_device_set_vertex_declaration(struct wined3d_device *device,
struct wined3d_vertex_declaration *declaration);
void __cdecl wined3d_device_set_vertex_shader(struct wined3d_device *device, struct wined3d_shader *shader);
-void __cdecl wined3d_device_set_viewport(struct wined3d_device *device, const struct wined3d_viewport *viewport);
+void __cdecl wined3d_device_set_viewports(struct wined3d_device *device, unsigned int viewport_count,
+ const struct wined3d_viewport *viewports);
void __cdecl wined3d_device_set_vs_cb(struct wined3d_device *device, UINT idx, struct wined3d_buffer *buffer);
HRESULT __cdecl wined3d_device_set_vs_consts_b(struct wined3d_device *device,
unsigned int start_idx, unsigned int count, const BOOL *constants);
--
2.17.0
2
1
[PATCH vkd3d 1/3] libs/vkd3d: Mark device as removed when command list in recording state is executed.
by Józef Kucia 16 Apr '18
by Józef Kucia 16 Apr '18
16 Apr '18
From: Józef Kucia <jkucia(a)codeweavers.com>
Fixes a GPU hang in test_device_removed_reason() on RADV.
Signed-off-by: Józef Kucia <jkucia(a)codeweavers.com>
---
include/private/vkd3d_debug.h | 3 +++
libs/vkd3d-common/debug.c | 17 ++++++++++++-----
libs/vkd3d/command.c | 13 ++++++++++++-
libs/vkd3d/device.c | 21 +++++++++++++++++++--
libs/vkd3d/vkd3d_private.h | 4 ++++
tests/d3d12.c | 4 ++--
6 files changed, 52 insertions(+), 10 deletions(-)
diff --git a/include/private/vkd3d_debug.h b/include/private/vkd3d_debug.h
index b9d4bcde0a92..e5e938dbb3f3 100644
--- a/include/private/vkd3d_debug.h
+++ b/include/private/vkd3d_debug.h
@@ -21,6 +21,8 @@
#include "vkd3d_common.h"
+#include <stdarg.h>
+
enum vkd3d_dbg_level
{
VKD3D_DBG_LEVEL_NONE,
@@ -36,6 +38,7 @@ void vkd3d_dbg_printf(enum vkd3d_dbg_level level, const char *function,
const char *fmt, ...) VKD3D_PRINTF_FUNC(3, 4) DECLSPEC_HIDDEN;
const char *vkd3d_dbg_sprintf(const char *fmt, ...) VKD3D_PRINTF_FUNC(1, 2) DECLSPEC_HIDDEN;
+const char *vkd3d_dbg_vsprintf(const char *fmt, va_list args) DECLSPEC_HIDDEN;
const char *debugstr_a(const char *str) DECLSPEC_HIDDEN;
const char *debugstr_w(const WCHAR *wstr, size_t wchar_size) DECLSPEC_HIDDEN;
diff --git a/libs/vkd3d-common/debug.c b/libs/vkd3d-common/debug.c
index 9cdf2a98e851..b8380457058d 100644
--- a/libs/vkd3d-common/debug.c
+++ b/libs/vkd3d-common/debug.c
@@ -20,7 +20,6 @@
#include <assert.h>
#include <ctype.h>
-#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -89,19 +88,27 @@ static char *get_buffer(void)
return buffers[current_index];
}
-const char *vkd3d_dbg_sprintf(const char *fmt, ...)
+const char *vkd3d_dbg_vsprintf(const char *fmt, va_list args)
{
char *buffer;
- va_list args;
buffer = get_buffer();
- va_start(args, fmt);
vsnprintf(buffer, VKD3D_DEBUG_BUFFER_SIZE, fmt, args);
- va_end(args);
buffer[VKD3D_DEBUG_BUFFER_SIZE - 1] = '\0';
return buffer;
}
+const char *vkd3d_dbg_sprintf(const char *fmt, ...)
+{
+ const char *buffer;
+ va_list args;
+
+ va_start(args, fmt);
+ buffer = vkd3d_dbg_vsprintf(fmt, args);
+ va_end(args);
+ return buffer;
+}
+
const char *debugstr_a(const char *str)
{
char *buffer, *ptr;
diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c
index b7b774b284de..82a99fda2511 100644
--- a/libs/vkd3d/command.c
+++ b/libs/vkd3d/command.c
@@ -4191,6 +4191,7 @@ static void STDMETHODCALLTYPE d3d12_command_queue_ExecuteCommandLists(ID3D12Comm
{
struct d3d12_command_queue *command_queue = impl_from_ID3D12CommandQueue(iface);
const struct vkd3d_vk_device_procs *vk_procs;
+ struct d3d12_command_list *cmd_list;
struct VkSubmitInfo submit_desc;
VkCommandBuffer *buffers;
VkQueue vk_queue;
@@ -4210,7 +4211,17 @@ static void STDMETHODCALLTYPE d3d12_command_queue_ExecuteCommandLists(ID3D12Comm
for (i = 0; i < command_list_count; ++i)
{
- buffers[i] = unsafe_impl_from_ID3D12CommandList(command_lists[i])->vk_command_buffer;
+ cmd_list = unsafe_impl_from_ID3D12CommandList(command_lists[i]);
+
+ if (cmd_list->is_recording)
+ {
+ d3d12_device_mark_as_removed(command_queue->device, DXGI_ERROR_INVALID_CALL,
+ "Command list %p is in recording state.\n", command_lists[i]);
+ vkd3d_free(buffers);
+ return;
+ }
+
+ buffers[i] = cmd_list->vk_command_buffer;
}
submit_desc.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c
index 805d477f89b0..48ad7c506c34 100644
--- a/libs/vkd3d/device.c
+++ b/libs/vkd3d/device.c
@@ -1943,9 +1943,11 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateFence(ID3D12Device *iface,
static HRESULT STDMETHODCALLTYPE d3d12_device_GetDeviceRemovedReason(ID3D12Device *iface)
{
- FIXME("iface %p stub!\n", iface);
+ struct d3d12_device *device = impl_from_ID3D12Device(iface);
- return S_OK;
+ TRACE("iface %p.\n", iface);
+
+ return device->removed_reason;
}
static void STDMETHODCALLTYPE d3d12_device_GetCopyableFootprints(ID3D12Device *iface,
@@ -2245,6 +2247,8 @@ static HRESULT d3d12_device_init(struct d3d12_device *device,
if ((device->parent = create_info->parent))
IUnknown_AddRef(device->parent);
+ device->removed_reason = S_OK;
+
return S_OK;
}
@@ -2270,6 +2274,19 @@ HRESULT d3d12_device_create(struct vkd3d_instance *instance,
return S_OK;
}
+void d3d12_device_mark_as_removed(struct d3d12_device *device, HRESULT reason,
+ const char *message, ...)
+{
+ va_list args;
+
+ va_start(args, message);
+ WARN("Device %p is lost (reason %#x, message \"%s\").\n",
+ device, reason, vkd3d_dbg_vsprintf(message, args));
+ va_end(args);
+
+ device->removed_reason = reason;
+}
+
IUnknown *vkd3d_get_device_parent(ID3D12Device *device)
{
struct d3d12_device *d3d12_device = impl_from_ID3D12Device(device);
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h
index 246c42bed937..4a359dbf7632 100644
--- a/libs/vkd3d/vkd3d_private.h
+++ b/libs/vkd3d/vkd3d_private.h
@@ -683,10 +683,14 @@ struct d3d12_device
IUnknown *parent;
LUID adapter_luid;
+
+ HRESULT removed_reason;
};
HRESULT d3d12_device_create(struct vkd3d_instance *instance,
const struct vkd3d_device_create_info *create_info, struct d3d12_device **device) DECLSPEC_HIDDEN;
+void d3d12_device_mark_as_removed(struct d3d12_device *device, HRESULT reason,
+ const char *message, ...) VKD3D_PRINTF_FUNC(3, 4) DECLSPEC_HIDDEN;
struct d3d12_device *unsafe_impl_from_ID3D12Device(ID3D12Device *iface) DECLSPEC_HIDDEN;
HRESULT vkd3d_create_buffer(struct d3d12_device *device,
diff --git a/tests/d3d12.c b/tests/d3d12.c
index 7dfee875ab0b..ea7d24da57be 100644
--- a/tests/d3d12.c
+++ b/tests/d3d12.c
@@ -4598,7 +4598,7 @@ static void test_device_removed_reason(void)
exec_command_list(queue, command_list);
hr = ID3D12Device_GetDeviceRemovedReason(device);
- todo(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
+ ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
hr = ID3D12Device_CreateCommandQueue(device, &command_queue_desc,
&IID_ID3D12CommandQueue, (void **)&tmp_queue);
@@ -4607,7 +4607,7 @@ static void test_device_removed_reason(void)
ID3D12CommandQueue_Release(tmp_queue);
hr = ID3D12Device_GetDeviceRemovedReason(device);
- todo(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
+ ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
ID3D12GraphicsCommandList_Release(command_list);
ID3D12CommandAllocator_Release(command_allocator);
--
2.16.1
2
5
[PATCH 2/2] dinput/tests: Add some tests for DIK_ codes using different keyboard layouts.
by Dmitry Timoshkov 16 Apr '18
by Dmitry Timoshkov 16 Apr '18
16 Apr '18
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
dlls/dinput/keyboard.c | 3 +-
dlls/dinput/tests/keyboard.c | 178 ++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 178 insertions(+), 3 deletions(-)
diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c
index e1ba15edd1..8a59ce01bc 100644
--- a/dlls/dinput/keyboard.c
+++ b/dlls/dinput/keyboard.c
@@ -86,7 +86,8 @@ static int KeyboardCallback( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM
wparam != WM_SYSKEYDOWN && wparam != WM_SYSKEYUP)
return 0;
- TRACE("(%p) %ld,%ld\n", iface, wparam, lparam);
+ TRACE("(%p) wp %08lx, lp %08lx, vk %02x, scan %02x\n",
+ iface, wparam, lparam, hook->vkCode, hook->scanCode);
switch (hook->vkCode)
{
diff --git a/dlls/dinput/tests/keyboard.c b/dlls/dinput/tests/keyboard.c
index e51e332535..c5d890ab52 100644
--- a/dlls/dinput/tests/keyboard.c
+++ b/dlls/dinput/tests/keyboard.c
@@ -30,6 +30,53 @@
#include "wingdi.h"
#include "dinput.h"
+/* to make things easier with PSDK without a dinput.lib */
+static HRESULT (WINAPI *pDirectInputCreateA)(HINSTANCE,DWORD,IDirectInputA **,IUnknown *);
+
+static void pump_messages(void)
+{
+ MSG msg;
+
+ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
+ {
+ TranslateMessage(&msg);
+ DispatchMessageA(&msg);
+ }
+}
+
+static HKL activate_keyboard_layout(LANGID langid, HKL *hkl_orig)
+{
+ HKL hkl, hkl_current;
+ char hkl_name[64];
+
+ sprintf(hkl_name, "%08x", langid);
+ trace("Loading keyboard layout %s\n", hkl_name);
+ hkl = LoadKeyboardLayoutA(hkl_name, 0);
+ if (!hkl)
+ {
+ win_skip("Unable to load keyboard layout %s\n", hkl_name);
+ return 0;
+ }
+ *hkl_orig = ActivateKeyboardLayout(hkl, 0);
+ ok(*hkl_orig != 0, "Unable to activate keyboard layout %s\n", hkl_name);
+ if (!*hkl_orig) return 0;
+
+ hkl_current = GetKeyboardLayout(0);
+ if (LOWORD(hkl_current) != langid)
+ {
+ /* FIXME: Wine can't activate different keyboard layouts.
+ * for testing purposes use this workaround:
+ * setxkbmap us && LANG=en_US.UTF-8 make test
+ * setxkbmap fr && LANG=fr_FR.UTF-8 make test
+ * setxkbmap de && LANG=de_DE.UTF-8 make test
+ */
+ skip("current %08x != langid %08x\n", LOWORD(hkl_current), langid);
+ return 0;
+ }
+
+ return hkl;
+}
+
static void acquire_tests(IDirectInputA *pDI, HWND hwnd)
{
HRESULT hr;
@@ -44,8 +91,12 @@ static void acquire_tests(IDirectInputA *pDI, HWND hwnd)
{ &GUID_Key, sizeof(LONG) * 2, DIDFT_MAKEINSTANCE(DIK_E)|DIDFT_BUTTON, 0 },
{ &GUID_Key, sizeof(LONG) * 4, DIDFT_MAKEINSTANCE(DIK_R)|DIDFT_BUTTON, 0 },
};
-
DIDATAFORMAT df;
+ HKL hkl, hkl_orig;
+
+ hkl = activate_keyboard_layout(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), &hkl_orig);
+ if (!hkl) return;
+
df.dwSize = sizeof( df );
df.dwObjSize = sizeof( DIOBJECTDATAFORMAT );
df.dwFlags = DIDF_RELAXIS;
@@ -93,6 +144,8 @@ static void acquire_tests(IDirectInputA *pDI, HWND hwnd)
/* simulate some keyboard input */
SetFocus(hwnd);
+ pump_messages();
+
keybd_event('Q', 0, 0, 0);
hr = IDirectInputDevice_GetDeviceState(pKeyboard, sizeof(custom_state), custom_state);
ok(SUCCEEDED(hr), "IDirectInputDevice_GetDeviceState() failed: %08x\n", hr);
@@ -113,6 +166,9 @@ static void acquire_tests(IDirectInputA *pDI, HWND hwnd)
keybd_event('Q', 0, KEYEVENTF_KEYUP, 0);
if (pKeyboard) IUnknown_Release(pKeyboard);
+
+ ActivateKeyboardLayout(hkl_orig, 0);
+ UnloadKeyboardLayout(hkl);
}
static const HRESULT SetCoop_null_window[16] = {
@@ -225,6 +281,115 @@ static void test_capabilities(IDirectInputA *pDI, HWND hwnd)
IUnknown_Release(pKeyboard);
}
+static void test_dik_codes(IDirectInputA *dI, HWND hwnd, LANGID langid)
+{
+ static const struct key2dik
+ {
+ BYTE key, dik;
+ } key2dik_en[] =
+ {
+ {'Q',DIK_Q}, {'W',DIK_W}, {'E',DIK_E}, {'R', DIK_R}, {'T', DIK_T}, {'Y', DIK_Y}
+ },
+ key2dik_fr[] =
+ {
+ {'A',DIK_Q}, {'Z',DIK_W}, {'E',DIK_E}, {'R', DIK_R}, {'T', DIK_T}, {'Y', DIK_Y}
+ },
+ key2dik_de[] =
+ {
+ {'Q',DIK_Q}, {'W',DIK_W}, {'E',DIK_E}, {'R', DIK_R}, {'T', DIK_T}, {'Z', DIK_Y}
+ };
+ static const struct
+ {
+ LANGID langid;
+ const struct key2dik *map;
+ } expected[] =
+ {
+ { MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), key2dik_en },
+ { MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH), key2dik_fr },
+ { MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN), key2dik_de },
+ { MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN), key2dik_en }
+ };
+ const struct key2dik *map = NULL;
+ UINT i;
+ HRESULT hr;
+ IDirectInputDeviceA *device;
+ HKL hkl, hkl_orig;
+ MSG msg;
+
+ for (i = 0; i < sizeof(expected)/sizeof(expected[0]); i++)
+ {
+ if (expected[i].langid == langid)
+ {
+ map = expected[i].map;
+ break;
+ }
+ }
+ ok(map != NULL, "can't find mapping for langid %04x\n", langid);
+ if (!map) return;
+
+ hr = IDirectInput_CreateDevice(dI, &GUID_SysKeyboard, &device, NULL);
+ ok(hr == S_OK, "CreateDevice() failed: %08x\n", hr);
+ hr = IDirectInputDevice_SetDataFormat(device, &c_dfDIKeyboard);
+ ok(hr == S_OK, "SetDataFormat() failed: %08x\n", hr);
+ hr = IDirectInputDevice_Acquire(device);
+ ok(hr == S_OK, "Acquire() failed: %08x\n", hr);
+
+ hkl = activate_keyboard_layout(langid, &hkl_orig);
+ if (!hkl) goto fail;
+
+ SetFocus(hwnd);
+ pump_messages();
+
+ for (i = 0; i < sizeof(key2dik_en)/sizeof(key2dik_en[0]); i++)
+ {
+ BYTE kbd_state[256];
+ UINT n;
+ INPUT in;
+
+ n = MapVirtualKeyA(map[i].key, MAPVK_VK_TO_CHAR);
+ ok(n == map[i].key, "%u: expected %c, got %c\n", i, map[i].key, n);
+ n = MapVirtualKeyA(map[i].key, MAPVK_VK_TO_VSC);
+ ok(n == map[i].dik, "%u: expected %02x, got %02x\n", i, map[i].dik, n);
+
+ in.type = INPUT_KEYBOARD;
+ U(in).ki.wVk = map[i].key;
+ U(in).ki.wScan = map[i].dik; /* scan codes match the DIK_ codes */
+ U(in).ki.dwFlags = 0;
+ U(in).ki.dwExtraInfo = 0;
+ U(in).ki.time = 0;
+ n = SendInput(1, &in, sizeof(in));
+ ok(n == 1, "got %u\n", n);
+
+ if (!PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
+ {
+ win_skip("failed to queue keyboard event\n");
+ break;
+ }
+ ok(msg.message == WM_KEYDOWN, "expected WM_KEYDOWN, got %04x\n", msg.message);
+ DispatchMessageA(&msg);
+
+ trace("keydown wParam: %#lx (%c) lParam: %#lx, MapVirtualKey(MAPVK_VK_TO_CHAR) = %c\n",
+ msg.wParam, LOWORD(msg.wParam), msg.lParam, MapVirtualKeyA(msg.wParam, MAPVK_VK_TO_CHAR));
+
+ hr = IDirectInputDevice_GetDeviceState(device, sizeof(kbd_state), kbd_state);
+ ok(hr == S_OK, "GetDeviceState() failed: %08x\n", hr);
+
+ ok(kbd_state[map[i].dik] == 0x80, "DI key %#x has state %#x\n", map[i].dik, kbd_state[map[i].dik]);
+
+ U(in).ki.dwFlags = KEYEVENTF_KEYUP;
+ n = SendInput(1, &in, sizeof(in));
+ ok(n == 1, "got %u\n", n);
+
+ pump_messages();
+ }
+
+ ActivateKeyboardLayout(hkl_orig, 0);
+ UnloadKeyboardLayout(hkl);
+fail:
+ IDirectInputDevice_Unacquire(device);
+ IUnknown_Release(device);
+}
+
static void keyboard_tests(DWORD version)
{
HRESULT hr;
@@ -233,7 +398,7 @@ static void keyboard_tests(DWORD version)
HWND hwnd;
ULONG ref = 0;
- hr = DirectInputCreateA(hInstance, version, &pDI, NULL);
+ hr = pDirectInputCreateA(hInstance, version, &pDI, NULL);
if (hr == DIERR_OLDDIRECTINPUTVERSION)
{
skip("Tests require a newer dinput version\n");
@@ -248,10 +413,17 @@ static void keyboard_tests(DWORD version)
if (hwnd)
{
+ pump_messages();
+
acquire_tests(pDI, hwnd);
test_set_coop(pDI, hwnd);
test_get_prop(pDI, hwnd);
test_capabilities(pDI, hwnd);
+
+ test_dik_codes(pDI, hwnd, MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT));
+ test_dik_codes(pDI, hwnd, MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH));
+ test_dik_codes(pDI, hwnd, MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN));
+ test_dik_codes(pDI, hwnd, MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN));
}
DestroyWindow(hwnd);
@@ -261,6 +433,8 @@ static void keyboard_tests(DWORD version)
START_TEST(keyboard)
{
+ pDirectInputCreateA = (void *)GetProcAddress(LoadLibraryA("dinput.dll"), "DirectInputCreateA");
+
CoInitialize(NULL);
keyboard_tests(0x0700);
--
2.16.3
2
1