[PATCH 2/5] wined3d: Implement locking of block-based volume textures.
Stefan Dösinger
stefan at codeweavers.com
Wed Sep 18 05:24:56 CDT 2013
---
dlls/wined3d/volume.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++----
1 file 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)))
--
1.8.1.5
More information about the wine-patches
mailing list