Wine-Devel
Threads by month
- ----- 2026 -----
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
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 April 16, 2018
by Dmitry Timoshkov April 16, 2018
April 16, 2018
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
[PATCH 1/2] dinput: The DIK_ key code should match the scan code.
by Dmitry Timoshkov April 16, 2018
by Dmitry Timoshkov April 16, 2018
April 16, 2018
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 April 16, 2018
by Henri Verbeet April 16, 2018
April 16, 2018
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 April 16, 2018
by Henri Verbeet April 16, 2018
April 16, 2018
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 April 16, 2018
by Henri Verbeet April 16, 2018
April 16, 2018
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
April 16, 2018
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 April 16, 2018
by Henri Verbeet April 16, 2018
April 16, 2018
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
April 16, 2018
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 April 16, 2018
by Józef Kucia April 16, 2018
April 16, 2018
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 April 16, 2018
by Dmitry Timoshkov April 16, 2018
April 16, 2018
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