Commit ac37f7a2 authored by Stefan Dösinger's avatar Stefan Dösinger Committed by Alexandre Julliard

wined3d: Implement locking of block-based volume textures.

parent 83b40487
......@@ -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,11 +671,24 @@ 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);
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
+ (map_desc->slice_pitch * box->front) /* FIXME: is front < back or vica versa? */
+ (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)))
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment