=?UTF-8?Q?Stefan=20D=C3=B6singer=20?=: wined3d: Implement locking of block-based volume textures.

Alexandre Julliard julliard at winehq.org
Wed Sep 18 15:49:59 CDT 2013


Module: wine
Branch: master
Commit: ac37f7a2ac09c77f7bd9db39c3180307696fdc6c
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=ac37f7a2ac09c77f7bd9db39c3180307696fdc6c

Author: Stefan Dösinger <stefan at codeweavers.com>
Date:   Wed Sep 18 12:24:56 2013 +0200

wined3d: Implement locking of block-based volume textures.

---

 dlls/wined3d/volume.c |   95 +++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 88 insertions(+), 7 deletions(-)

diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c
index 508b1df..fcab45b 100644
--- a/dlls/wined3d/volume.c
+++ b/dlls/wined3d/volume.c
@@ -71,6 +71,31 @@ static void wined3d_volume_allocate_texture(const struct wined3d_volume *volume,
     checkGLcall("glTexImage3D");
 }
 
+static void wined3d_volume_get_pitch(const struct wined3d_volume *volume, UINT *row_pitch,
+        UINT *slice_pitch)
+{
+    const struct wined3d_format *format = volume->resource.format;
+
+    if (format->flags & WINED3DFMT_FLAG_BLOCKS)
+    {
+        /* Since compressed formats are block based, pitch means the amount of
+         * bytes to the next row of block rather than the next row of pixels. */
+        UINT row_block_count = (volume->resource.width + format->block_width - 1) / format->block_width;
+        UINT slice_block_count = (volume->resource.height + format->block_height - 1) / format->block_height;
+        *row_pitch = row_block_count * format->block_byte_count;
+        *slice_pitch = *row_pitch * slice_block_count;
+    }
+    else
+    {
+        unsigned char alignment = volume->resource.device->surface_alignment;
+        *row_pitch = format->byte_count * volume->resource.width;  /* Bytes / row */
+        *row_pitch = (*row_pitch + alignment - 1) & ~(alignment - 1);
+        *slice_pitch = *row_pitch * volume->resource.height;
+    }
+
+    TRACE("Returning row pitch %u, slice pitch %u.\n", *row_pitch, *slice_pitch);
+}
+
 /* Context activation is done by the caller. */
 void wined3d_volume_upload_data(struct wined3d_volume *volume, const struct wined3d_context *context,
         const struct wined3d_bo_address *data)
@@ -513,6 +538,34 @@ struct wined3d_resource * CDECL wined3d_volume_get_resource(struct wined3d_volum
     return &volume->resource;
 }
 
+static BOOL volume_check_block_align(const struct wined3d_volume *volume,
+        const struct wined3d_box *box)
+{
+    UINT width_mask, height_mask;
+    const struct wined3d_format *format = volume->resource.format;
+
+    if (!box)
+        return TRUE;
+
+    /* This assumes power of two block sizes, but NPOT block sizes would be
+     * silly anyway.
+     *
+     * This also assumes that the format's block depth is 1. */
+    width_mask = format->block_width - 1;
+    height_mask = format->block_height - 1;
+
+    if (box->left & width_mask)
+        return FALSE;
+    if (box->top & height_mask)
+        return FALSE;
+    if (box->right & width_mask && box->right != volume->resource.width)
+        return FALSE;
+    if (box->bottom & height_mask && box->bottom != volume->resource.height)
+        return FALSE;
+
+    return TRUE;
+}
+
 HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume,
         struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags)
 {
@@ -520,6 +573,7 @@ HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume,
     struct wined3d_context *context;
     const struct wined3d_gl_info *gl_info;
     BYTE *base_memory;
+    const struct wined3d_format *format = volume->resource.format;
 
     TRACE("volume %p, map_desc %p, box %p, flags %#x.\n",
             volume, map_desc, box, flags);
@@ -535,6 +589,13 @@ HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume,
         WARN("Volume is already mapped.\n");
         return WINED3DERR_INVALIDCALL;
     }
+    if ((format->flags & WINED3DFMT_FLAG_BLOCKS) && !volume_check_block_align(volume, box))
+    {
+        WARN("Map box is misaligned for %ux%u blocks.\n",
+                format->block_width, format->block_height);
+        return WINED3DERR_INVALIDCALL;
+    }
+
     flags = wined3d_resource_sanitize_map_flags(&volume->resource, flags);
 
     if (volume->flags & WINED3D_VFLAG_PBO)
@@ -591,9 +652,16 @@ HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume,
 
     TRACE("Base memory pointer %p.\n", base_memory);
 
-    map_desc->row_pitch = volume->resource.format->byte_count * volume->resource.width; /* Bytes / row */
-    map_desc->slice_pitch = volume->resource.format->byte_count
-            * volume->resource.width * volume->resource.height; /* Bytes / slice */
+    if (format->flags & WINED3DFMT_FLAG_BROKEN_PITCH)
+    {
+        map_desc->row_pitch = volume->resource.width * format->byte_count;
+        map_desc->slice_pitch = map_desc->row_pitch * volume->resource.height;
+    }
+    else
+    {
+        wined3d_volume_get_pitch(volume, &map_desc->row_pitch, &map_desc->slice_pitch);
+    }
+
     if (!box)
     {
         TRACE("No box supplied - all is ok\n");
@@ -603,10 +671,23 @@ HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume,
     {
         TRACE("Lock Box (%p) = l %u, t %u, r %u, b %u, fr %u, ba %u\n",
                 box, box->left, box->top, box->right, box->bottom, box->front, box->back);
-        map_desc->data = base_memory
-                + (map_desc->slice_pitch * box->front)     /* FIXME: is front < back or vica versa? */
-                + (map_desc->row_pitch * box->top)
-                + (box->left * volume->resource.format->byte_count);
+
+        if ((format->flags & (WINED3DFMT_FLAG_BLOCKS | WINED3DFMT_FLAG_BROKEN_PITCH)) == WINED3DFMT_FLAG_BLOCKS)
+        {
+            /* Compressed textures are block based, so calculate the offset of
+             * the block that contains the top-left pixel of the locked rectangle. */
+            map_desc->data = base_memory
+                    + (box->front * map_desc->slice_pitch)
+                    + ((box->top / format->block_height) * map_desc->row_pitch)
+                    + ((box->left / format->block_width) * format->block_byte_count);
+        }
+        else
+        {
+            map_desc->data = base_memory
+                    + (map_desc->slice_pitch * box->front)
+                    + (map_desc->row_pitch * box->top)
+                    + (box->left * volume->resource.format->byte_count);
+        }
     }
 
     if (!(flags & (WINED3D_MAP_NO_DIRTY_UPDATE | WINED3D_MAP_READONLY)))




More information about the wine-cvs mailing list