From c4d75213abe21dcd7697d2f9151a186ebb3f8c8d Mon Sep 17 00:00:00 2001 From: Alexander Dorofeyev Date: Tue, 6 May 2008 00:49:34 +0300 Subject: [PATCH] ddraw/tests: Add tests for IDirect3DDevice7_Load. --- dlls/ddraw/tests/d3d.c | 1092 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1092 insertions(+) diff --git a/dlls/ddraw/tests/d3d.c b/dlls/ddraw/tests/d3d.c index e81d8027cdb..ca0bbafca15 100644 --- a/dlls/ddraw/tests/d3d.c +++ b/dlls/ddraw/tests/d3d.c @@ -3,6 +3,7 @@ * * Copyright (C) 2005 Antoine Chavasse * Copyright (C) 2006 Stefan Dösinger for CodeWeavers + * Copyright (C) 2008 Alexander Dorofeyev * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -1616,6 +1617,1096 @@ static void D3D7_OldRenderStateTest(void) } } +#define IS_VALUE_NEAR(a, b) ( ((a) == (b)) || ((a) == (b) - 1) || ((a) == (b) + 1) ) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +static void DeviceLoadTest() +{ + DDSURFACEDESC2 ddsd; + IDirectDrawSurface7 *texture_levels[2][8]; + IDirectDrawSurface7 *cube_face_levels[2][6][8]; + DWORD flags; + HRESULT hr; + DDBLTFX ddbltfx; + RECT loadrect; + POINT loadpoint; + int i, i1, i2; + unsigned diff_count = 0, diff_count2 = 0; + unsigned x, y; + BOOL load_mip_subset_broken = FALSE; + IDirectDrawPalette *palettes[5]; + PALETTEENTRY table1[256]; + DDCOLORKEY ddckey; + + /* Test loading of texture subrectangle with a mipmap surface. */ + memset(texture_levels, 0, sizeof(texture_levels)); + memset(cube_face_levels, 0, sizeof(cube_face_levels)); + memset(palettes, 0, sizeof(palettes)); + + for (i = 0; i < 2; i++) + { + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; + ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP; + ddsd.dwWidth = 128; + ddsd.dwHeight = 128; + U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat); + U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB; + U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32; + U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000; + U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00; + U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF; + hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL); + ok(hr==DD_OK,"CreateSurface returned: %x\n",hr); + if (FAILED(hr)) goto out; + + /* Check the number of created mipmaps */ + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(ddsd); + hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd); + ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr); + ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount); + if (U2(ddsd).dwMipMapCount != 8) goto out; + + for (i1 = 1; i1 < 8; i1++) + { + hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]); + ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr); + if (FAILED(hr)) goto out; + } + } + + for (i1 = 0; i1 < 8; i1++) + { + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(ddsd); + hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL); + ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr); + if (FAILED(hr)) goto out; + + for (y = 0 ; y < ddsd.dwHeight; y++) + { + DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * ddsd.lPitch); + + for (x = 0; x < ddsd.dwWidth; x++) + { + /* x stored in green component, y in blue. */ + DWORD color = 0xff0000 | (x << 8) | y; + *textureRow++ = color; + } + } + + hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL); + ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr); + } + + for (i1 = 0; i1 < 8; i1++) + { + memset(&ddbltfx, 0, sizeof(ddbltfx)); + ddbltfx.dwSize = sizeof(ddbltfx); + U5(ddbltfx).dwFillColor = 0; + hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); + ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr); + } + + /* First test some broken coordinates. */ + loadpoint.x = loadpoint.y = 0; + loadrect.left = 0; + loadrect.top = 0; + loadrect.right = 0; + loadrect.bottom = 0; + hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0); + ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr); + + loadpoint.x = loadpoint.y = 50; + loadrect.left = 0; + loadrect.top = 0; + loadrect.right = 100; + loadrect.bottom = 100; + hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0); + ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr); + + /* Test actual loading. */ + loadpoint.x = loadpoint.y = 31; + loadrect.left = 30; + loadrect.top = 20; + loadrect.right = 93; + loadrect.bottom = 52; + + hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0); + ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr); + + for (i1 = 0; i1 < 8; i1++) + { + diff_count = 0; + diff_count2 = 0; + + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(ddsd); + hr = IDirectDrawSurface7_Lock(texture_levels[1][i1], NULL, &ddsd, DDLOCK_WAIT, NULL); + ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr); + if (FAILED(hr)) goto out; + + for (y = 0 ; y < ddsd.dwHeight; y++) + { + DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * ddsd.lPitch); + + for (x = 0; x < ddsd.dwWidth; x++) + { + DWORD color = *textureRow++; + + if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left || + y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top) + { + if (color & 0xffffff) diff_count++; + } + else + { + DWORD r = (color & 0xff0000) >> 16; + DWORD g = (color & 0xff00) >> 8; + DWORD b = (color & 0xff); + + if (r != 0xff || g != x + loadrect.left - loadpoint.x || b != y + loadrect.top - loadpoint.y) diff_count++; + } + + /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may + technically be correct as it's not precisely defined by docs. */ + if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left || + y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1) + { + if (color & 0xffffff) diff_count2++; + } + else + { + DWORD r = (color & 0xff0000) >> 16; + DWORD g = (color & 0xff00) >> 8; + DWORD b = (color & 0xff); + + if (r != 0xff || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) || + !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++; + } + } + } + + hr = IDirectDrawSurface7_Unlock(texture_levels[1][i1], NULL); + ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr); + + ok(diff_count == 0 || diff_count2 == 0, "Unexpected destination texture level pixels; %u differences at %d level\n", + MIN(diff_count, diff_count2), i1); + + loadpoint.x /= 2; + loadpoint.y /= 2; + loadrect.top /= 2; + loadrect.left /= 2; + loadrect.right = (loadrect.right + 1) / 2; + loadrect.bottom = (loadrect.bottom + 1) / 2; + } + + /* This crashes on native (tested on real windows XP / directx9 / nvidia and + * qemu Win98 / directx7 / RGB software rasterizer): + * passing non toplevel surfaces (sublevels) to Load (DX7 docs tell not to do this) + hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][1], NULL, texture_levels[0][1], NULL, 0); + */ + + /* Freed in reverse order as native seems to dislike and crash on freeing top level surface first. */ + for (i = 0; i < 2; i++) + { + for (i1 = 7; i1 >= 0; i1--) + { + if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]); + } + } + memset(texture_levels, 0, sizeof(texture_levels)); + + /* Test texture size mismatch. */ + for (i = 0; i < 2; i++) + { + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE; + ddsd.dwWidth = i ? 256 : 128; + ddsd.dwHeight = 128; + hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL); + ok(hr==DD_OK,"CreateSurface returned: %x\n",hr); + if (FAILED(hr)) goto out; + } + + hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0); + ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr); + + hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[0][0], NULL, texture_levels[1][0], NULL, 0); + ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr); + + IDirectDrawSurface7_Release(texture_levels[0][0]); + IDirectDrawSurface7_Release(texture_levels[1][0]); + memset(texture_levels, 0, sizeof(texture_levels)); + + /* Test loading mipmapped cubemap texture subrectangle from another similar texture. */ + for (i = 0; i < 2; i++) + { + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; + ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP; + ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES; + ddsd.dwWidth = 128; + ddsd.dwHeight = 128; + U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat); + U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB; + U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32; + U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000; + U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00; + U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF; + hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[i][0][0], NULL); + ok(hr==DD_OK,"CreateSurface returned: %x\n",hr); + if (FAILED(hr)) goto out; + + flags = DDSCAPS2_CUBEMAP_NEGATIVEX; + for (i1 = 1; i1 < 6; i1++, flags <<= 1) + { + ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE; + ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | flags; + hr = IDirectDrawSurface7_GetAttachedSurface(cube_face_levels[i][0][0], &ddsd.ddsCaps, &cube_face_levels[i][i1][0]); + ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr); + if (FAILED(hr)) goto out; + } + + for (i1 = 0; i1 < 6; i1++) + { + /* Check the number of created mipmaps */ + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(ddsd); + hr = IDirectDrawSurface7_GetSurfaceDesc(cube_face_levels[i][i1][0], &ddsd); + ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr); + ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount); + if (U2(ddsd).dwMipMapCount != 8) goto out; + + for (i2 = 1; i2 < 8; i2++) + { + ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP; + ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL; + hr = IDirectDrawSurface7_GetAttachedSurface(cube_face_levels[i][i1][i2 - 1], &ddsd.ddsCaps, &cube_face_levels[i][i1][i2]); + ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr); + if (FAILED(hr)) goto out; + } + } + } + + for (i = 0; i < 6; i++) + for (i1 = 0; i1 < 8; i1++) + { + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(ddsd); + hr = IDirectDrawSurface7_Lock(cube_face_levels[0][i][i1], NULL, &ddsd, DDLOCK_WAIT, NULL); + ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr); + if (FAILED(hr)) goto out; + + for (y = 0 ; y < ddsd.dwHeight; y++) + { + DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * ddsd.lPitch); + + for (x = 0; x < ddsd.dwWidth; x++) + { + /* face number in low 4 bits of red, x stored in green component, y in blue. */ + DWORD color = 0xf00000 | (i << 16) | (x << 8) | y; + *textureRow++ = color; + } + } + + hr = IDirectDrawSurface7_Unlock(cube_face_levels[0][i][i1], NULL); + ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr); + } + + for (i = 0; i < 6; i++) + for (i1 = 0; i1 < 8; i1++) + { + memset(&ddbltfx, 0, sizeof(ddbltfx)); + ddbltfx.dwSize = sizeof(ddbltfx); + U5(ddbltfx).dwFillColor = 0; + hr = IDirectDrawSurface7_Blt(cube_face_levels[1][i][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); + ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr); + } + + loadpoint.x = loadpoint.y = 10; + loadrect.left = 30; + loadrect.top = 20; + loadrect.right = 93; + loadrect.bottom = 52; + + hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], &loadpoint, cube_face_levels[0][0][0], &loadrect, + DDSCAPS2_CUBEMAP_ALLFACES); + ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr); + + for (i = 0; i < 6; i++) + { + loadpoint.x = loadpoint.y = 10; + loadrect.left = 30; + loadrect.top = 20; + loadrect.right = 93; + loadrect.bottom = 52; + + for (i1 = 0; i1 < 8; i1++) + { + diff_count = 0; + diff_count2 = 0; + + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(ddsd); + hr = IDirectDrawSurface7_Lock(cube_face_levels[1][i][i1], NULL, &ddsd, DDLOCK_WAIT, NULL); + ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr); + if (FAILED(hr)) goto out; + + for (y = 0 ; y < ddsd.dwHeight; y++) + { + DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * ddsd.lPitch); + + for (x = 0; x < ddsd.dwWidth; x++) + { + DWORD color = *textureRow++; + + if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left || + y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top) + { + if (color & 0xffffff) diff_count++; + } + else + { + DWORD r = (color & 0xff0000) >> 16; + DWORD g = (color & 0xff00) >> 8; + DWORD b = (color & 0xff); + + if (r != (0xf0 | i) || g != x + loadrect.left - loadpoint.x || + b != y + loadrect.top - loadpoint.y) diff_count++; + } + + /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may + technically be correct as it's not precisely defined by docs. */ + if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left || + y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1) + { + if (color & 0xffffff) diff_count2++; + } + else + { + DWORD r = (color & 0xff0000) >> 16; + DWORD g = (color & 0xff00) >> 8; + DWORD b = (color & 0xff); + + if (r != (0xf0 | i) || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) || + !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++; + } + } + } + + hr = IDirectDrawSurface7_Unlock(cube_face_levels[1][i][i1], NULL); + ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr); + + ok(diff_count == 0 || diff_count2 == 0, + "Unexpected destination texture level pixels; %u differences at face %x level %d\n", + MIN(diff_count, diff_count2), i, i1); + + loadpoint.x /= 2; + loadpoint.y /= 2; + loadrect.top /= 2; + loadrect.left /= 2; + loadrect.right = (loadrect.right + 1) / 2; + loadrect.bottom = (loadrect.bottom + 1) / 2; + } + } + + for (i = 0; i < 2; i++) + for (i1 = 5; i1 >= 0; i1--) + for (i2 = 7; i2 >= 0; i2--) + { + if (cube_face_levels[i][i1][i2]) IDirectDrawSurface7_Release(cube_face_levels[i][i1][i2]); + } + memset(cube_face_levels, 0, sizeof(cube_face_levels)); + + /* Test cubemap loading from regular texture. */ + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX; + ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES; + ddsd.dwWidth = 128; + ddsd.dwHeight = 128; + hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[0][0][0], NULL); + ok(hr==DD_OK,"CreateSurface returned: %x\n",hr); + if (FAILED(hr)) goto out; + + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE; + ddsd.dwWidth = 128; + ddsd.dwHeight = 128; + hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[0][0], NULL); + ok(hr==DD_OK,"CreateSurface returned: %x\n",hr); + if (FAILED(hr)) goto out; + + hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, texture_levels[0][0], NULL, + DDSCAPS2_CUBEMAP_ALLFACES); + ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr); + + IDirectDrawSurface7_Release(cube_face_levels[0][0][0]); + memset(cube_face_levels, 0, sizeof(cube_face_levels)); + IDirectDrawSurface7_Release(texture_levels[0][0]); + memset(texture_levels, 0, sizeof(texture_levels)); + + /* Test cubemap loading from cubemap with different number of faces. */ + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX; + ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX; + ddsd.dwWidth = 128; + ddsd.dwHeight = 128; + hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[0][0][0], NULL); + ok(hr==DD_OK,"CreateSurface returned: %x\n",hr); + if (FAILED(hr)) goto out; + + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX; + ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP_POSITIVEY; + ddsd.dwWidth = 128; + ddsd.dwHeight = 128; + hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[1][0][0], NULL); + ok(hr==DD_OK,"CreateSurface returned: %x\n",hr); + if (FAILED(hr)) goto out; + + /* INVALIDPARAMS tests currently would fail because wine doesn't support partial cube faces + (the above created cubemaps will have all faces. */ + hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL, + DDSCAPS2_CUBEMAP_ALLFACES); + todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr); + + hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL, + DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP_POSITIVEY); + todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr); + + hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL, + DDSCAPS2_CUBEMAP_POSITIVEX); + todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr); + + hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL, + DDSCAPS2_CUBEMAP_ALLFACES); + ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr); + + hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL, + DDSCAPS2_CUBEMAP_POSITIVEX); + ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr); + + hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL, + DDSCAPS2_CUBEMAP_POSITIVEZ); + ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr); + + IDirectDrawSurface7_Release(cube_face_levels[0][0][0]); + IDirectDrawSurface7_Release(cube_face_levels[1][0][0]); + memset(cube_face_levels, 0, sizeof(cube_face_levels)); + + /* Test texture loading with different mip level count (larger levels match, smaller levels missing in destination. */ + for (i = 0; i < 2; i++) + { + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_MIPMAPCOUNT; + ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP; + ddsd.dwWidth = 128; + ddsd.dwHeight = 128; + ddsd.dwMipMapCount = i ? 4 : 8; + U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat); + U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB; + U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32; + U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000; + U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00; + U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF; + hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL); + ok(hr==DD_OK,"CreateSurface returned: %x\n",hr); + if (FAILED(hr)) goto out; + + /* Check the number of created mipmaps */ + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(ddsd); + hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd); + ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr); + ok(U2(ddsd).dwMipMapCount == (i ? 4 : 8), "unexpected mip count %u\n", U2(ddsd).dwMipMapCount); + if (U2(ddsd).dwMipMapCount != (i ? 4 : 8)) goto out; + + for (i1 = 1; i1 < (i ? 4 : 8); i1++) + { + hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]); + ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr); + if (FAILED(hr)) goto out; + } + } + + for (i1 = 0; i1 < 8; i1++) + { + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(ddsd); + hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL); + ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr); + if (FAILED(hr)) goto out; + + for (y = 0 ; y < ddsd.dwHeight; y++) + { + DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * ddsd.lPitch); + + for (x = 0; x < ddsd.dwWidth; x++) + { + /* x stored in green component, y in blue. */ + DWORD color = 0xf00000 | (i1 << 16) | (x << 8) | y; + *textureRow++ = color; + } + } + + hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL); + ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr); + } + + for (i1 = 0; i1 < 4; i1++) + { + memset(&ddbltfx, 0, sizeof(ddbltfx)); + ddbltfx.dwSize = sizeof(ddbltfx); + U5(ddbltfx).dwFillColor = 0; + hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); + ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr); + } + + loadpoint.x = loadpoint.y = 31; + loadrect.left = 30; + loadrect.top = 20; + loadrect.right = 93; + loadrect.bottom = 52; + + /* Destination mip levels are a subset of source mip levels. */ + hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0); + ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr); + + for (i1 = 0; i1 < 4; i1++) + { + diff_count = 0; + diff_count2 = 0; + + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(ddsd); + hr = IDirectDrawSurface7_Lock(texture_levels[1][i1], NULL, &ddsd, DDLOCK_WAIT, NULL); + ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr); + if (FAILED(hr)) goto out; + + for (y = 0 ; y < ddsd.dwHeight; y++) + { + DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * ddsd.lPitch); + + for (x = 0; x < ddsd.dwWidth; x++) + { + DWORD color = *textureRow++; + + if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left || + y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top) + { + if (color & 0xffffff) diff_count++; + } + else + { + DWORD r = (color & 0xff0000) >> 16; + DWORD g = (color & 0xff00) >> 8; + DWORD b = (color & 0xff); + + if (r != (0xf0 | i1) || g != x + loadrect.left - loadpoint.x || + b != y + loadrect.top - loadpoint.y) diff_count++; + } + + /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may + technically be correct as it's not precisely defined by docs. */ + if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left || + y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1) + { + if (color & 0xffffff) diff_count2++; + } + else + { + DWORD r = (color & 0xff0000) >> 16; + DWORD g = (color & 0xff00) >> 8; + DWORD b = (color & 0xff); + + if (r != (0xf0 | i1) || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) || + !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++; + } + } + } + + hr = IDirectDrawSurface7_Unlock(texture_levels[1][i1], NULL); + ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr); + + ok(diff_count == 0 || diff_count2 == 0, "Unexpected destination texture level pixels; %u differences at %d level\n", + MIN(diff_count, diff_count2), i1); + + loadpoint.x /= 2; + loadpoint.y /= 2; + loadrect.top /= 2; + loadrect.left /= 2; + loadrect.right = (loadrect.right + 1) / 2; + loadrect.bottom = (loadrect.bottom + 1) / 2; + } + + /* Destination mip levels are a superset of source mip levels (should fail). */ + hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[0][0], &loadpoint, texture_levels[1][0], &loadrect, 0); + ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr); + + for (i = 0; i < 2; i++) + { + for (i1 = 7; i1 >= 0; i1--) + { + if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]); + } + } + memset(texture_levels, 0, sizeof(texture_levels)); + + /* Test loading from mipmap texture to a regular texture that matches one sublevel in size. */ + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; + ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP; + ddsd.dwWidth = 128; + ddsd.dwHeight = 128; + U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat); + U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB; + U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32; + U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000; + U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00; + U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF; + hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[0][0], NULL); + ok(hr==DD_OK,"CreateSurface returned: %x\n",hr); + if (FAILED(hr)) goto out; + + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; + ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE; + ddsd.dwWidth = 32; + ddsd.dwHeight = 32; + U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat); + U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB; + U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32; + U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000; + U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00; + U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF; + hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[1][0], NULL); + ok(hr==DD_OK,"CreateSurface returned: %x\n",hr); + if (FAILED(hr)) goto out; + + for (i1 = 1; i1 < 8; i1++) + { + hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[0][i1 - 1], &ddsd.ddsCaps, &texture_levels[0][i1]); + ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr); + if (FAILED(hr)) goto out; + } + + for (i1 = 0; i1 < 8; i1++) + { + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(ddsd); + hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL); + ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr); + if (FAILED(hr)) goto out; + + for (y = 0 ; y < ddsd.dwHeight; y++) + { + DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * ddsd.lPitch); + + for (x = 0; x < ddsd.dwWidth; x++) + { + /* x stored in green component, y in blue. */ + DWORD color = 0xf00000 | (i1 << 16) | (x << 8) | y; + *textureRow++ = color; + } + } + + hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL); + ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr); + } + + memset(&ddbltfx, 0, sizeof(ddbltfx)); + ddbltfx.dwSize = sizeof(ddbltfx); + U5(ddbltfx).dwFillColor = 0; + hr = IDirectDrawSurface7_Blt(texture_levels[1][0], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); + ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr); + + loadpoint.x = loadpoint.y = 32; + loadrect.left = 32; + loadrect.top = 32; + loadrect.right = 96; + loadrect.bottom = 96; + + hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0); + ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr); + + loadpoint.x /= 4; + loadpoint.y /= 4; + loadrect.top /= 4; + loadrect.left /= 4; + loadrect.right = (loadrect.right + 3) / 4; + loadrect.bottom = (loadrect.bottom + 3) / 4; + + /* NOTE: something in either nvidia driver or directx9 on WinXP appears to be broken: + * this kind of Load calls (to subset with smaller surface(s)) produces wrong results with + * copied subrectangles divided more than needed, without apparent logic. But it works + * as expected on qemu / Win98 / directx7 / RGB device. Some things are broken on XP, e.g. + * some games don't work that worked in Win98, so it is assumed here XP results are wrong. + * The following code attempts to detect broken results, actual tests will then be skipped + */ + load_mip_subset_broken = TRUE; + diff_count = 0; + + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(ddsd); + hr = IDirectDrawSurface7_Lock(texture_levels[1][0], NULL, &ddsd, DDLOCK_WAIT, NULL); + ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr); + if (FAILED(hr)) goto out; + + for (y = 0 ; y < ddsd.dwHeight; y++) + { + DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * ddsd.lPitch); + + for (x = 0; x < ddsd.dwWidth; x++) + { + DWORD color = *textureRow++; + + if (x < 2 || x >= 2 + 4 || + y < 2 || y >= 2 + 4) + { + if (color & 0xffffff) diff_count++; + } + else + { + DWORD r = (color & 0xff0000) >> 16; + + if ((r & (0xf0)) != 0xf0) diff_count++; + } + } + } + + if (diff_count) load_mip_subset_broken = FALSE; + + if (load_mip_subset_broken) { + skip("IDirect3DDevice7_Load is broken (happens on some modern Windows installations like XP). Skipping affected tests.\n"); + } else { + diff_count = 0; + + for (y = 0 ; y < ddsd.dwHeight; y++) + { + DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * ddsd.lPitch); + + for (x = 0; x < ddsd.dwWidth; x++) + { + DWORD color = *textureRow++; + + if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left || + y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top) + { + if (color & 0xffffff) diff_count++; + } + else + { + DWORD r = (color & 0xff0000) >> 16; + DWORD g = (color & 0xff00) >> 8; + DWORD b = (color & 0xff); + + if (r != (0xf0 | 2) || g != x + loadrect.left - loadpoint.x || + b != y + loadrect.top - loadpoint.y) diff_count++; + } + } + } + } + + hr = IDirectDrawSurface7_Unlock(texture_levels[1][0], NULL); + ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr); + + ok(diff_count == 0, "Unexpected destination texture level pixels; %u differences\n", diff_count); + + for (i = 0; i < 2; i++) + { + for (i1 = 7; i1 >= 0; i1--) + { + if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]); + } + } + memset(texture_levels, 0, sizeof(texture_levels)); + + if (!load_mip_subset_broken) + { + /* Test loading when destination mip levels are a subset of source mip levels and start from smaller + * surface (than first source mip level) + */ + for (i = 0; i < 2; i++) + { + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; + if (i) ddsd.dwFlags |= DDSD_MIPMAPCOUNT; + ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP; + ddsd.dwWidth = i ? 32 : 128; + ddsd.dwHeight = i ? 32 : 128; + if (i) ddsd.dwMipMapCount = 4; + U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat); + U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB; + U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32; + U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000; + U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00; + U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF; + hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL); + ok(hr==DD_OK,"CreateSurface returned: %x\n",hr); + if (FAILED(hr)) goto out; + + /* Check the number of created mipmaps */ + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(ddsd); + hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd); + ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr); + ok(U2(ddsd).dwMipMapCount == (i ? 4 : 8), "unexpected mip count %u\n", U2(ddsd).dwMipMapCount); + if (U2(ddsd).dwMipMapCount != (i ? 4 : 8)) goto out; + + for (i1 = 1; i1 < (i ? 4 : 8); i1++) + { + hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]); + ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr); + if (FAILED(hr)) goto out; + } + } + + for (i1 = 0; i1 < 8; i1++) + { + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(ddsd); + hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL); + ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr); + if (FAILED(hr)) goto out; + + for (y = 0 ; y < ddsd.dwHeight; y++) + { + DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * ddsd.lPitch); + + for (x = 0; x < ddsd.dwWidth; x++) + { + /* x stored in green component, y in blue. */ + DWORD color = 0xf00000 | (i1 << 16) | (x << 8) | y; + *textureRow++ = color; + } + } + + hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL); + ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr); + } + + for (i1 = 0; i1 < 4; i1++) + { + memset(&ddbltfx, 0, sizeof(ddbltfx)); + ddbltfx.dwSize = sizeof(ddbltfx); + U5(ddbltfx).dwFillColor = 0; + hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); + ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr); + } + + loadpoint.x = loadpoint.y = 0; + loadrect.left = 0; + loadrect.top = 0; + loadrect.right = 64; + loadrect.bottom = 64; + + hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0); + ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr); + + i = 0; + for (i1 = 0; i1 < 8 && i < 4; i1++) + { + DDSURFACEDESC2 ddsd2; + + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(ddsd); + hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[0][i1], &ddsd); + + memset(&ddsd2, 0, sizeof(DDSURFACEDESC2)); + ddsd2.dwSize = sizeof(ddsd2); + hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[1][i], &ddsd2); + + if (ddsd.dwWidth == ddsd2.dwWidth && ddsd.dwHeight == ddsd2.dwHeight) + { + diff_count = 0; + + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(ddsd); + hr = IDirectDrawSurface7_Lock(texture_levels[1][i], NULL, &ddsd, DDLOCK_WAIT, NULL); + ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr); + if (FAILED(hr)) goto out; + + for (y = 0 ; y < ddsd.dwHeight; y++) + { + DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * ddsd.lPitch); + + for (x = 0; x < ddsd.dwWidth; x++) + { + DWORD color = *textureRow++; + + if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left || + y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top) + { + if (color & 0xffffff) diff_count++; + } + else + { + DWORD r = (color & 0xff0000) >> 16; + DWORD g = (color & 0xff00) >> 8; + DWORD b = (color & 0xff); + + if (r != (0xf0 | i1) || g != x + loadrect.left - loadpoint.x || + b != y + loadrect.top - loadpoint.y) diff_count++; + } + } + } + + hr = IDirectDrawSurface7_Unlock(texture_levels[1][i], NULL); + ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr); + + ok(diff_count == 0, "Unexpected destination texture level pixels; %u differences at %d level\n", diff_count, i1); + + i++; + } + + loadpoint.x /= 2; + loadpoint.y /= 2; + loadrect.top /= 2; + loadrect.left /= 2; + loadrect.right = (loadrect.right + 1) / 2; + loadrect.bottom = (loadrect.bottom + 1) / 2; + } + + for (i = 0; i < 2; i++) + { + for (i1 = 7; i1 >= 0; i1--) + { + if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]); + } + } + memset(texture_levels, 0, sizeof(texture_levels)); + } + + /* Test palette copying. */ + for (i = 0; i < 2; i++) + { + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; + ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP; + ddsd.dwWidth = 128; + ddsd.dwHeight = 128; + U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat); + U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8; + U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 8; + hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL); + ok(hr==DD_OK,"CreateSurface returned: %x\n",hr); + if (FAILED(hr)) goto out; + + /* Check the number of created mipmaps */ + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(ddsd); + hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd); + ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr); + ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount); + if (U2(ddsd).dwMipMapCount != 8) goto out; + + for (i1 = 1; i1 < 8; i1++) + { + hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]); + ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr); + if (FAILED(hr)) goto out; + } + } + + memset(table1, 0, sizeof(table1)); + for (i = 0; i < 3; i++) + { + table1[0].peBlue = i + 1; + hr = IDirectDraw7_CreatePalette(lpDD, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &palettes[i], NULL); + ok(hr == DD_OK, "CreatePalette returned %08x\n", hr); + if (FAILED(hr)) + { + skip("IDirectDraw7_CreatePalette failed; skipping further tests\n"); + goto out; + } + } + + hr = IDirectDrawSurface7_SetPalette(texture_levels[0][0], palettes[0]); + ok(hr==DD_OK, "IDirectDrawSurface7_SetPalette returned: %x\n", hr); + + hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0); + ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr); + + hr = IDirectDrawSurface7_GetPalette(texture_levels[1][0], &palettes[4]); + ok(hr==DDERR_NOPALETTEATTACHED, "IDirectDrawSurface7_GetPalette returned: %x\n", hr); + + hr = IDirectDrawSurface7_SetPalette(texture_levels[0][1], palettes[1]); + todo_wine ok(hr==DDERR_NOTONMIPMAPSUBLEVEL, "IDirectDrawSurface7_SetPalette returned: %x\n", hr); + hr = IDirectDrawSurface7_SetPalette(texture_levels[1][0], palettes[2]); + ok(hr==DD_OK, "IDirectDrawSurface7_SetPalette returned: %x\n", hr); + + hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0); + ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr); + + memset(table1, 0, sizeof(table1)); + hr = IDirectDrawSurface7_GetPalette(texture_levels[1][0], &palettes[4]); + ok(hr==DD_OK, "IDirectDrawSurface7_GetPalette returned: %x\n", hr); + if (SUCCEEDED(hr)) + { + hr = IDirectDrawPalette_GetEntries(palettes[4], 0, 0, 256, table1); + ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr); + ok(table1[0].peBlue == 1, "Unexpected palette color after load: %u\n", (unsigned)table1[0].peBlue); + } + + /* Test colorkey copying. */ + ddckey.dwColorSpaceLowValue = ddckey.dwColorSpaceHighValue = 64; + hr = IDirectDrawSurface7_SetColorKey(texture_levels[0][0], DDCKEY_SRCBLT, &ddckey); + ok(hr==DD_OK, "IDirectDrawSurface7_SetColorKey returned: %x\n", hr); + hr = IDirectDrawSurface7_SetColorKey(texture_levels[0][1], DDCKEY_SRCBLT, &ddckey); + todo_wine ok(hr==DDERR_NOTONMIPMAPSUBLEVEL, "IDirectDrawSurface7_SetColorKey returned: %x\n", hr); + + hr = IDirectDrawSurface7_GetColorKey(texture_levels[1][0], DDCKEY_SRCBLT, &ddckey); + ok(hr==DDERR_NOCOLORKEY, "IDirectDrawSurface7_GetColorKey returned: %x\n", hr); + + hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0); + ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr); + + hr = IDirectDrawSurface7_GetColorKey(texture_levels[1][0], DDCKEY_SRCBLT, &ddckey); + ok(hr==DD_OK, "IDirectDrawSurface7_GetColorKey returned: %x\n", hr); + ok(ddckey.dwColorSpaceLowValue == ddckey.dwColorSpaceHighValue && ddckey.dwColorSpaceLowValue == 64, + "Unexpected color key values: %u - %u\n", ddckey.dwColorSpaceLowValue, ddckey.dwColorSpaceHighValue); + + out: + + for (i = 0; i < 5; i++) + { + if (palettes[i]) IDirectDrawPalette_Release(palettes[i]); + } + + for (i = 0; i < 2; i++) + { + for (i1 = 7; i1 >= 0; i1--) + { + if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]); + } + } + + for (i = 0; i < 2; i++) + for (i1 = 5; i1 >= 0; i1--) + for (i2 = 7; i2 >= 0; i2--) + { + if (cube_face_levels[i][i1][i2]) IDirectDrawSurface7_Release(cube_face_levels[i][i1][i2]); + } +} START_TEST(d3d) { @@ -1637,6 +2728,7 @@ START_TEST(d3d) CapsTest(); VertexBufferDescTest(); D3D7_OldRenderStateTest(); + DeviceLoadTest(); ReleaseDirect3D(); } -- 2.11.4.GIT