[2/2] d3d9: Add a LockRect test for DXTn formats

H. Verbeet hverbeet at gmail.com
Thu Mar 15 17:27:58 CDT 2007


http://www.winehq.org/pipermail/wine-patches/2007-March/037047.html
hasn't been applied (yet?), so adding this as todo_wine.

We currently calculate the wrong offset when locking DXTn textures.
DXTn textures are based on compressed blocks of 4x4 pixels, each
16bytes large (8 bytes in case of DXT1). Because of that Pitch has
slightly different meaning compared to regular textures. For DXTn
textures Pitch is the size of a row of blocks, 4 high and "width"
long. The x offset is calculated differently as well, since moving 4
pixels to the right actually moves an entire 4x4 block to right, ie
16/8 bytes. That's also the reason why DXTn textures can only be
locked at coordinates that are multiples of 4.

Changelog:
  - Add a LockRect test for DXTn formats
-------------- next part --------------
---

 dlls/d3d9/tests/surface.c |   58 ++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 57 insertions(+), 1 deletions(-)

diff --git a/dlls/d3d9/tests/surface.c b/dlls/d3d9/tests/surface.c
index 42ebf2d..7063a2a 100644
--- a/dlls/d3d9/tests/surface.c
+++ b/dlls/d3d9/tests/surface.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 Henri Verbeet
+ * Copyright 2006-2007 Henri Verbeet
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -172,6 +172,61 @@ static void test_surface_alignment(IDirect3DDevice9 *device_ptr)
     }
 }
 
+/* Since the DXT formats are based on 4x4 blocks, locking works slightly
+ * different than with regular formats. This patch verifies we return the
+ * correct memory offsets */
+static void test_lockrect_offset(IDirect3DDevice9 *device)
+{
+    IDirect3DSurface9 *surface = 0;
+    const RECT rect = {60, 60, 68, 68};
+    D3DLOCKED_RECT locked_rect;
+    unsigned int expected_offset;
+    unsigned int offset;
+    unsigned int i;
+    BYTE *base;
+    HRESULT hr;
+
+    const struct {
+        D3DFORMAT fmt;
+        const char *name;
+        unsigned int block_width;
+        unsigned int block_height;
+        unsigned int block_size;
+    } dxt_formats[] = {
+        {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, 8},
+        {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, 16},
+        {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, 16},
+        {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, 16},
+        {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 16},
+    };
+
+    for (i = 0; i < (sizeof(dxt_formats) / sizeof(*dxt_formats)); ++i) {
+        hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128, dxt_formats[i].fmt, D3DPOOL_SCRATCH, &surface, 0);
+        ok(SUCCEEDED(hr), "CreateOffscreenPlainSurface failed (%08x)\n", hr);
+
+        hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
+        ok(SUCCEEDED(hr), "LockRect failed (%08x)\n", hr);
+
+        base = locked_rect.pBits;
+
+        hr = IDirect3DSurface9_UnlockRect(surface);
+        ok(SUCCEEDED(hr), "UnlockRect failed (%08x)\n", hr);
+
+        hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
+        ok(SUCCEEDED(hr), "LockRect failed (%08x)\n", hr);
+
+        offset = (BYTE *)locked_rect.pBits - base;
+        expected_offset = (rect.top / dxt_formats[i].block_height) * locked_rect.Pitch
+                        + (rect.left / dxt_formats[i].block_width) * dxt_formats[i].block_size;
+        todo_wine ok(offset == expected_offset, "Got offset %u, expected offset %u for format %s\n", offset, expected_offset, dxt_formats[i].name);
+
+        hr = IDirect3DSurface9_UnlockRect(surface);
+        ok(SUCCEEDED(hr), "UnlockRect failed (%08x)\n", hr);
+
+        IDirect3DSurface9_Release(surface);
+    }
+}
+
 START_TEST(surface)
 {
     HMODULE d3d9_handle;
@@ -189,4 +244,5 @@ START_TEST(surface)
 
     test_surface_get_container(device_ptr);
     test_surface_alignment(device_ptr);
+    test_lockrect_offset(device_ptr);
 }


More information about the wine-patches mailing list