mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-02 16:43:38 +00:00
ddraw/tests: Add some tests for creating surfaces with user memory.
This commit is contained in:
parent
9e86596714
commit
c81d05064f
|
@ -20,6 +20,7 @@
|
|||
|
||||
#define COBJMACROS
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "wine/test.h"
|
||||
#include "wine/heap.h"
|
||||
#include <limits.h>
|
||||
|
@ -50,6 +51,15 @@ struct vec4
|
|||
float x, y, z, w;
|
||||
};
|
||||
|
||||
struct ddraw_test_context
|
||||
{
|
||||
HWND window;
|
||||
IDirectDraw7 *ddraw;
|
||||
IDirect3D7 *d3d;
|
||||
IDirect3DDevice7 *device;
|
||||
IDirectDrawSurface7 *backbuffer;
|
||||
};
|
||||
|
||||
struct create_window_thread_param
|
||||
{
|
||||
HWND window;
|
||||
|
@ -112,6 +122,16 @@ static BOOL compare_mode_rect(const DEVMODEW *mode1, const DEVMODEW *mode2)
|
|||
&& mode1->dmPelsHeight == mode2->dmPelsHeight;
|
||||
}
|
||||
|
||||
static void init_format_b8g8r8x8(DDPIXELFORMAT *format)
|
||||
{
|
||||
format->dwSize = sizeof(*format);
|
||||
format->dwFlags = DDPF_RGB;
|
||||
U1(*format).dwRGBBitCount = 32;
|
||||
U2(*format).dwRBitMask = 0x00ff0000;
|
||||
U3(*format).dwGBitMask = 0x0000ff00;
|
||||
U4(*format).dwBBitMask = 0x000000ff;
|
||||
}
|
||||
|
||||
static ULONG get_refcount(IUnknown *iface)
|
||||
{
|
||||
IUnknown_AddRef(iface);
|
||||
|
@ -602,6 +622,53 @@ static IDirect3DDevice7 *create_device(HWND window, DWORD coop_level)
|
|||
return create_device_ex(window, coop_level, device_guid);
|
||||
}
|
||||
|
||||
static bool init_3d_test_context_guid(struct ddraw_test_context *context, const GUID *device_guid)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
memset(context, 0, sizeof(*context));
|
||||
|
||||
context->window = create_window();
|
||||
if (!(context->device = create_device_ex(context->window, DDSCL_NORMAL, device_guid)))
|
||||
{
|
||||
skip("Failed to create a D3D device.\n");
|
||||
DestroyWindow(context->window);
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = IDirect3DDevice7_GetDirect3D(context->device, &context->d3d);
|
||||
ok(hr == S_OK, "Got hr %#lx.\n", hr);
|
||||
hr = IDirect3D7_QueryInterface(context->d3d, &IID_IDirectDraw7, (void **)&context->ddraw);
|
||||
ok(hr == S_OK, "Got hr %#lx.\n", hr);
|
||||
hr = IDirect3DDevice7_GetRenderTarget(context->device, &context->backbuffer);
|
||||
ok(hr == S_OK, "Got hr %#lx.\n", hr);
|
||||
return true;
|
||||
}
|
||||
|
||||
#define release_test_context(a) release_test_context_(__LINE__, a)
|
||||
static void release_test_context_(unsigned int line, struct ddraw_test_context *context)
|
||||
{
|
||||
ULONG refcount;
|
||||
|
||||
IDirectDrawSurface7_Release(context->backbuffer);
|
||||
refcount = IDirect3DDevice7_Release(context->device);
|
||||
ok_(__FILE__, line)(!refcount, "Device has %lu references left.\n", refcount);
|
||||
IDirect3D7_Release(context->d3d);
|
||||
refcount = IDirectDraw7_Release(context->ddraw);
|
||||
ok_(__FILE__, line)(!refcount, "D3D object has %lu references left.\n", refcount);
|
||||
DestroyWindow(context->window);
|
||||
}
|
||||
|
||||
static void clear_surface(IDirectDrawSurface7 *surface, unsigned int colour)
|
||||
{
|
||||
DDBLTFX fx = {.dwSize = sizeof(fx)};
|
||||
HRESULT hr;
|
||||
|
||||
U5(fx).dwFillColor = colour;
|
||||
hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
|
||||
ok(hr == S_OK, "Got hr %#lx.\n", hr);
|
||||
}
|
||||
|
||||
struct message
|
||||
{
|
||||
UINT message;
|
||||
|
@ -19561,10 +19628,245 @@ static void test_enum_devices(void)
|
|||
ok(!refcount, "Device has %lu references left.\n", refcount);
|
||||
}
|
||||
|
||||
static void test_user_memory(const GUID *device_guid)
|
||||
{
|
||||
IDirectDrawSurface7 *surfaces[6], *dst_surface;
|
||||
struct ddraw_test_context context;
|
||||
unsigned int i, color;
|
||||
DDSURFACEDESC2 desc;
|
||||
HRESULT hr;
|
||||
void *mem;
|
||||
RECT rect;
|
||||
|
||||
static const struct
|
||||
{
|
||||
DWORD flags;
|
||||
DWORD caps;
|
||||
DWORD caps2;
|
||||
HRESULT hr;
|
||||
}
|
||||
create_tests[] =
|
||||
{
|
||||
{0, DDSCAPS_MIPMAP, 0, S_OK},
|
||||
{0, DDSCAPS_MIPMAP | DDSCAPS_COMPLEX, 0, DDERR_INVALIDCAPS},
|
||||
{DDSD_MIPMAPCOUNT, DDSCAPS_MIPMAP | DDSCAPS_COMPLEX, 0, DDERR_INVALIDCAPS},
|
||||
{0, DDSCAPS_COMPLEX, DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES, DDERR_INVALIDCAPS},
|
||||
};
|
||||
|
||||
if (!init_3d_test_context_guid(&context, device_guid))
|
||||
{
|
||||
winetest_pop_context();
|
||||
return;
|
||||
}
|
||||
|
||||
mem = malloc(16 * 16 * 5 * 4);
|
||||
|
||||
reset_ddsd(&desc);
|
||||
desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
|
||||
desc.dwWidth = 16;
|
||||
desc.dwHeight = 16;
|
||||
desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
|
||||
init_format_b8g8r8x8(&U4(desc).ddpfPixelFormat);
|
||||
hr = IDirectDraw7_CreateSurface(context.ddraw, &desc, &dst_surface, NULL);
|
||||
ok(hr == S_OK, "Got hr %#lx.\n", hr);
|
||||
|
||||
/* Test creating and using a normal user memory surface. */
|
||||
|
||||
reset_ddsd(&desc);
|
||||
desc.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LPSURFACE;
|
||||
desc.dwWidth = 16;
|
||||
U1(desc).lPitch = 16 * 4;
|
||||
desc.dwHeight = 16;
|
||||
desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
|
||||
init_format_b8g8r8x8(&U4(desc).ddpfPixelFormat);
|
||||
desc.lpSurface = mem;
|
||||
hr = IDirectDraw7_CreateSurface(context.ddraw, &desc, &surfaces[0], NULL);
|
||||
ok(hr == S_OK, "Got hr %#lx.\n", hr);
|
||||
|
||||
reset_ddsd(&desc);
|
||||
hr = IDirectDrawSurface7_Lock(surfaces[0], NULL, &desc, DDLOCK_WAIT, NULL);
|
||||
ok(hr == S_OK, "Got hr %#lx.\n", hr);
|
||||
ok(desc.lpSurface == mem, "Surface pointers didn't match.\n");
|
||||
memset(desc.lpSurface, 0x55, desc.dwHeight * U1(desc).lPitch);
|
||||
hr = IDirectDrawSurface7_Unlock(surfaces[0], NULL);
|
||||
ok(hr == S_OK, "Got hr %#lx.\n", hr);
|
||||
|
||||
/* Drawing from the user memory surface doesn't seem to work.
|
||||
* Windows 10 WARP succeeds, but Windows 10 on real NVidia hardware fails in
|
||||
* EndScene() with an undocumented error code 0x887602fb. */
|
||||
|
||||
clear_surface(dst_surface, 0x00999999);
|
||||
SetRect(&rect, 0, 0, 16, 16);
|
||||
hr = IDirectDrawSurface7_Blt(dst_surface, &rect, surfaces[0], &rect, DDBLT_WAIT, NULL);
|
||||
ok(hr == S_OK, "Got hr %#lx.\n", hr);
|
||||
color = get_surface_color(dst_surface, 1, 1);
|
||||
ok(color == 0x00555555, "Got unexpected color 0x%08x.\n", color);
|
||||
|
||||
IDirectDrawSurface7_Release(surfaces[0]);
|
||||
|
||||
/* Creating a texture with DDSCAPS_MIPMAP and DDSD_LPSURFACE is legal, but
|
||||
* such a texture isn't really mipmapped and only has one level.
|
||||
* Trying to create a mipmapped texture with DDSD_COMPLEX, or a
|
||||
* cubemap texture, fails if user memory is specified, even with a mipmap
|
||||
* count of 1. */
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(create_tests); ++i)
|
||||
{
|
||||
reset_ddsd(&desc);
|
||||
desc.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_HEIGHT | DDSD_CAPS
|
||||
| DDSD_PIXELFORMAT | DDSD_LPSURFACE | create_tests[i].flags;
|
||||
desc.dwWidth = 16;
|
||||
U1(desc).lPitch = 16 * 4;
|
||||
desc.dwHeight = 16;
|
||||
desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | create_tests[i].caps;
|
||||
desc.ddsCaps.dwCaps2 = create_tests[i].caps2;
|
||||
init_format_b8g8r8x8(&U4(desc).ddpfPixelFormat);
|
||||
U2(desc).dwMipMapCount = 1;
|
||||
desc.lpSurface = mem;
|
||||
hr = IDirectDraw7_CreateSurface(context.ddraw, &desc, &surfaces[0], NULL);
|
||||
todo_wine_if (create_tests[i].caps & DDSCAPS_COMPLEX)
|
||||
ok(hr == create_tests[i].hr, "Flags %#lx, caps %#lx: got hr %#lx.\n",
|
||||
create_tests[i].flags, create_tests[i].caps, hr);
|
||||
|
||||
if (hr == S_OK)
|
||||
IDirectDrawSurface7_Release(surfaces[0]);
|
||||
}
|
||||
|
||||
/* Mipmap surfaces. */
|
||||
|
||||
reset_ddsd(&desc);
|
||||
desc.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_MIPMAPCOUNT;
|
||||
desc.dwWidth = 16;
|
||||
U1(desc).lPitch = 16 * 4;
|
||||
desc.dwHeight = 16;
|
||||
desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_MIPMAP | DDSCAPS_COMPLEX;
|
||||
init_format_b8g8r8x8(&U4(desc).ddpfPixelFormat);
|
||||
U2(desc).dwMipMapCount = 5;
|
||||
hr = IDirectDraw7_CreateSurface(context.ddraw, &desc, &surfaces[0], NULL);
|
||||
ok(hr == S_OK, "Got hr %#lx.\n", hr);
|
||||
|
||||
for (i = 0; i < 4; ++i)
|
||||
{
|
||||
DDSCAPS2 mip_caps = {.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL};
|
||||
|
||||
hr = IDirectDrawSurface7_GetAttachedSurface(surfaces[i], &mip_caps, &surfaces[i + 1]);
|
||||
ok(hr == S_OK, "Got hr %#lx.\n", hr);
|
||||
}
|
||||
|
||||
reset_ddsd(&desc);
|
||||
desc.dwFlags = DDSD_LPSURFACE;
|
||||
desc.lpSurface = mem;
|
||||
hr = IDirectDrawSurface7_SetSurfaceDesc(surfaces[2], &desc, 0);
|
||||
ok(hr == S_OK, "Got hr %#lx.\n", hr);
|
||||
|
||||
for (i = 0; i < 5; ++i)
|
||||
{
|
||||
reset_ddsd(&desc);
|
||||
hr = IDirectDrawSurface7_GetSurfaceDesc(surfaces[i], &desc);
|
||||
ok(hr == S_OK, "Got hr %#lx.\n", hr);
|
||||
ok(desc.dwWidth == (16u >> i), "Got width %lu.\n", desc.dwWidth);
|
||||
|
||||
reset_ddsd(&desc);
|
||||
hr = IDirectDrawSurface7_Lock(surfaces[i], NULL, &desc, DDLOCK_WAIT, NULL);
|
||||
ok(hr == S_OK, "Got hr %#lx.\n", hr);
|
||||
if (i == 2)
|
||||
ok(desc.lpSurface == mem, "Got surface pointer %p.\n", desc.lpSurface);
|
||||
memset(desc.lpSurface, 0x11 * (i + 1), desc.dwHeight * U1(desc).lPitch);
|
||||
hr = IDirectDrawSurface7_Unlock(surfaces[i], NULL);
|
||||
ok(hr == S_OK, "Got hr %#lx.\n", hr);
|
||||
}
|
||||
|
||||
for (i = 0; i < 5; ++i)
|
||||
{
|
||||
winetest_push_context("level %u", i);
|
||||
|
||||
clear_surface(dst_surface, 0x00999999);
|
||||
SetRect(&rect, 0, 0, (16u >> i), (16u >> i));
|
||||
hr = IDirectDrawSurface7_Blt(dst_surface, &rect, surfaces[i], &rect, DDBLT_WAIT, NULL);
|
||||
ok(hr == S_OK, "Got hr %#lx.\n", hr);
|
||||
color = get_surface_color(dst_surface, 0, 0);
|
||||
ok(color == 0x00111111 * (i + 1), "Got unexpected color 0x%08x.\n", color);
|
||||
|
||||
winetest_pop_context();
|
||||
}
|
||||
|
||||
for (i = 0; i < 5; ++i)
|
||||
IDirectDrawSurface7_Release(surfaces[4 - i]);
|
||||
|
||||
/* Cube maps. */
|
||||
|
||||
reset_ddsd(&desc);
|
||||
desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
|
||||
desc.dwWidth = 16;
|
||||
U1(desc).lPitch = 16 * 4;
|
||||
desc.dwHeight = 16;
|
||||
desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX;
|
||||
desc.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
|
||||
init_format_b8g8r8x8(&U4(desc).ddpfPixelFormat);
|
||||
hr = IDirectDraw7_CreateSurface(context.ddraw, &desc, &surfaces[0], NULL);
|
||||
ok(hr == S_OK, "Got hr %#lx.\n", hr);
|
||||
|
||||
for (i = 0; i < 5; ++i)
|
||||
{
|
||||
DDSCAPS2 face_caps = {.dwCaps2 = DDSCAPS2_CUBEMAP | (DDSCAPS2_CUBEMAP_POSITIVEX << (i + 1))};
|
||||
|
||||
hr = IDirectDrawSurface7_GetAttachedSurface(surfaces[0], &face_caps, &surfaces[i + 1]);
|
||||
ok(hr == S_OK, "Got hr %#lx.\n", hr);
|
||||
}
|
||||
|
||||
reset_ddsd(&desc);
|
||||
desc.dwFlags = DDSD_LPSURFACE;
|
||||
desc.lpSurface = mem;
|
||||
hr = IDirectDrawSurface7_SetSurfaceDesc(surfaces[2], &desc, 0);
|
||||
ok(hr == S_OK, "Got hr %#lx.\n", hr);
|
||||
|
||||
for (i = 0; i < 6; ++i)
|
||||
{
|
||||
reset_ddsd(&desc);
|
||||
hr = IDirectDrawSurface7_GetSurfaceDesc(surfaces[i], &desc);
|
||||
ok(hr == S_OK, "Got hr %#lx.\n", hr);
|
||||
|
||||
reset_ddsd(&desc);
|
||||
hr = IDirectDrawSurface7_Lock(surfaces[i], NULL, &desc, DDLOCK_WAIT, NULL);
|
||||
ok(hr == S_OK, "Got hr %#lx.\n", hr);
|
||||
if (i == 2)
|
||||
ok(desc.lpSurface == mem, "Got surface pointer %p.\n", desc.lpSurface);
|
||||
memset(desc.lpSurface, 0x11 * (i + 1), desc.dwHeight * U1(desc).lPitch);
|
||||
hr = IDirectDrawSurface7_Unlock(surfaces[i], NULL);
|
||||
ok(hr == S_OK, "Got hr %#lx.\n", hr);
|
||||
}
|
||||
|
||||
for (i = 0; i < 6; ++i)
|
||||
{
|
||||
winetest_push_context("face %u", i);
|
||||
|
||||
clear_surface(dst_surface, 0x00999999);
|
||||
SetRect(&rect, 0, 0, 16, 16);
|
||||
hr = IDirectDrawSurface7_Blt(dst_surface, &rect, surfaces[i], &rect, DDBLT_WAIT, NULL);
|
||||
ok(hr == S_OK, "Got hr %#lx.\n", hr);
|
||||
color = get_surface_color(dst_surface, 0, 0);
|
||||
ok(color == 0x00111111 * (i + 1), "Got unexpected color 0x%08x.\n", color);
|
||||
|
||||
winetest_pop_context();
|
||||
}
|
||||
|
||||
for (i = 0; i < 6; ++i)
|
||||
IDirectDrawSurface7_Release(surfaces[5 - i]);
|
||||
|
||||
free(mem);
|
||||
|
||||
IDirectDrawSurface7_Release(dst_surface);
|
||||
release_test_context(&context);
|
||||
}
|
||||
|
||||
static void run_for_each_device_type(void (*test_func)(const GUID *))
|
||||
{
|
||||
winetest_push_context("Hardware device");
|
||||
test_func(hw_device_guid);
|
||||
winetest_pop_context();
|
||||
winetest_push_context("Software device");
|
||||
test_func(&IID_IDirect3DRGBDevice);
|
||||
winetest_pop_context();
|
||||
}
|
||||
|
||||
START_TEST(ddraw7)
|
||||
|
@ -19740,4 +20042,5 @@ START_TEST(ddraw7)
|
|||
run_for_each_device_type(test_texture_wrong_caps);
|
||||
test_filling_convention();
|
||||
test_enum_devices();
|
||||
run_for_each_device_type(test_user_memory);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue