Commit 843ccd2d authored by Andrew Wesie's avatar Andrew Wesie Committed by Alexandre Julliard

wined3d: Unify the texture download functions.

parent c69eba92
......@@ -342,235 +342,6 @@ static BOOL fbo_blitter_supported(enum wined3d_blit_op blit_op, const struct win
return TRUE;
}
/* This call just downloads data, the caller is responsible for binding the
* correct texture. */
/* Context activation is done by the caller. */
static void texture2d_download_data(struct wined3d_texture *texture, unsigned int sub_resource_idx,
const struct wined3d_context *context, DWORD dst_location)
{
const struct wined3d_gl_info *gl_info = context->gl_info;
struct wined3d_texture_sub_resource *sub_resource;
unsigned int dst_row_pitch, dst_slice_pitch;
unsigned int src_row_pitch, src_slice_pitch;
const struct wined3d_format_gl *format_gl;
struct wined3d_bo_address data;
BYTE *temporary_mem = NULL;
unsigned int level;
GLenum target;
void *mem;
format_gl = wined3d_format_gl(texture->resource.format);
/* Only support read back of converted P8 textures. */
if (texture->flags & WINED3D_TEXTURE_CONVERTED && format_gl->f.id != WINED3DFMT_P8_UINT && !format_gl->f.download)
{
ERR("Trying to read back converted texture %p, %u with format %s.\n",
texture, sub_resource_idx, debug_d3dformat(format_gl->f.id));
return;
}
sub_resource = &texture->sub_resources[sub_resource_idx];
target = wined3d_texture_get_sub_resource_target(texture, sub_resource_idx);
level = sub_resource_idx % texture->level_count;
if (target == GL_TEXTURE_2D_ARRAY)
{
if (format_gl->f.download)
{
FIXME("Reading back converted array texture %p is not supported.\n", texture);
return;
}
/* NP2 emulation is not allowed on array textures. */
if (texture->flags & WINED3D_TEXTURE_COND_NP2_EMULATED)
ERR("Array texture %p uses NP2 emulation.\n", texture);
WARN_(d3d_perf)("Downloading all miplevel layers to get the data for a single sub-resource.\n");
if (!(temporary_mem = heap_calloc(texture->layer_count, sub_resource->size)))
{
ERR("Out of memory.\n");
return;
}
}
wined3d_texture_get_memory(texture, sub_resource_idx, &data, dst_location);
if (texture->flags & WINED3D_TEXTURE_COND_NP2_EMULATED)
{
if (format_gl->f.download)
{
FIXME("Reading back converted texture %p with NP2 emulation is not supported.\n", texture);
return;
}
wined3d_texture_get_pitch(texture, level, &dst_row_pitch, &dst_slice_pitch);
wined3d_format_calculate_pitch(&format_gl->f, texture->resource.device->surface_alignment,
wined3d_texture_get_level_pow2_width(texture, level),
wined3d_texture_get_level_pow2_height(texture, level),
&src_row_pitch, &src_slice_pitch);
if (!(temporary_mem = heap_alloc(src_slice_pitch)))
{
ERR("Out of memory.\n");
return;
}
if (data.buffer_object)
ERR("NP2 emulated texture uses PBO unexpectedly.\n");
if (texture->resource.format_flags & WINED3DFMT_FLAG_COMPRESSED)
ERR("Unexpected compressed format for NP2 emulated texture.\n");
}
if (format_gl->f.download)
{
struct wined3d_format f;
if (data.buffer_object)
ERR("Converted texture %p uses PBO unexpectedly.\n", texture);
WARN_(d3d_perf)("Downloading converted texture %p, %u with format %s.\n",
texture, sub_resource_idx, debug_d3dformat(format_gl->f.id));
f = format_gl->f;
f.byte_count = format_gl->f.conv_byte_count;
wined3d_texture_get_pitch(texture, level, &dst_row_pitch, &dst_slice_pitch);
wined3d_format_calculate_pitch(&f, texture->resource.device->surface_alignment,
wined3d_texture_get_level_width(texture, level),
wined3d_texture_get_level_height(texture, level),
&src_row_pitch, &src_slice_pitch);
if (!(temporary_mem = heap_alloc(src_slice_pitch)))
{
ERR("Failed to allocate memory.\n");
return;
}
}
if (temporary_mem)
{
mem = temporary_mem;
}
else if (data.buffer_object)
{
GL_EXTCALL(glBindBuffer(GL_PIXEL_PACK_BUFFER, data.buffer_object));
checkGLcall("glBindBuffer");
mem = data.addr;
}
else
{
mem = data.addr;
}
if (texture->resource.format_flags & WINED3DFMT_FLAG_COMPRESSED)
{
TRACE("Downloading compressed texture %p, %u, level %u, format %#x, type %#x, data %p.\n",
texture, sub_resource_idx, level, format_gl->format, format_gl->type, mem);
GL_EXTCALL(glGetCompressedTexImage(target, level, mem));
checkGLcall("glGetCompressedTexImage");
}
else
{
TRACE("Downloading texture %p, %u, level %u, format %#x, type %#x, data %p.\n",
texture, sub_resource_idx, level, format_gl->format, format_gl->type, mem);
gl_info->gl_ops.gl.p_glGetTexImage(target, level, format_gl->format, format_gl->type, mem);
checkGLcall("glGetTexImage");
}
if (format_gl->f.download)
{
format_gl->f.download(mem, data.addr, src_row_pitch, src_slice_pitch, dst_row_pitch, dst_slice_pitch,
wined3d_texture_get_level_width(texture, level),
wined3d_texture_get_level_height(texture, level), 1);
}
else if (texture->flags & WINED3D_TEXTURE_COND_NP2_EMULATED)
{
const BYTE *src_data;
unsigned int h, y;
BYTE *dst_data;
/*
* Some games (e.g. warhammer 40k) don't work properly with the odd pitches, preventing
* the surface pitch from being used to box non-power2 textures. Instead we have to use a hack to
* repack the texture so that the bpp * width pitch can be used instead of bpp * pow2width.
*
* We're doing this...
*
* instead of boxing the texture :
* |<-texture width ->| -->pow2width| /\
* |111111111111111111| | |
* |222 Texture 222222| boxed empty | texture height
* |3333 Data 33333333| | |
* |444444444444444444| | \/
* ----------------------------------- |
* | boxed empty | boxed empty | pow2height
* | | | \/
* -----------------------------------
*
*
* we're repacking the data to the expected texture width
*
* |<-texture width ->| -->pow2width| /\
* |111111111111111111222222222222222| |
* |222333333333333333333444444444444| texture height
* |444444 | |
* | | \/
* | | |
* | empty | pow2height
* | | \/
* -----------------------------------
*
* == is the same as
*
* |<-texture width ->| /\
* |111111111111111111|
* |222222222222222222|texture height
* |333333333333333333|
* |444444444444444444| \/
* --------------------
*
* This also means that any references to surface memory should work with the data as if it were a
* standard texture with a non-power2 width instead of a texture boxed up to be a power2 texture.
*
* internally the texture is still stored in a boxed format so any references to textureName will
* get a boxed texture with width pow2width and not a texture of width resource.width. */
src_data = mem;
dst_data = data.addr;
TRACE("Repacking the surface data from pitch %u to pitch %u.\n", src_row_pitch, dst_row_pitch);
h = wined3d_texture_get_level_height(texture, level);
for (y = 0; y < h; ++y)
{
memcpy(dst_data, src_data, dst_row_pitch);
src_data += src_row_pitch;
dst_data += dst_row_pitch;
}
}
else if (temporary_mem)
{
unsigned int layer = sub_resource_idx / texture->level_count;
void *src_data = temporary_mem + layer * sub_resource->size;
if (data.buffer_object)
{
GL_EXTCALL(glBindBuffer(GL_PIXEL_PACK_BUFFER, data.buffer_object));
checkGLcall("glBindBuffer");
GL_EXTCALL(glBufferSubData(GL_PIXEL_PACK_BUFFER, 0, sub_resource->size, src_data));
checkGLcall("glBufferSubData");
}
else
{
memcpy(data.addr, src_data, sub_resource->size);
}
}
if (data.buffer_object)
{
GL_EXTCALL(glBindBuffer(GL_PIXEL_PACK_BUFFER, 0));
checkGLcall("glBindBuffer");
}
heap_free(temporary_mem);
}
/* See also float_16_to_32() in wined3d_private.h */
static inline unsigned short float_32_to_16(const float *in)
{
......@@ -1666,9 +1437,11 @@ BOOL texture2d_load_sysmem(struct wined3d_texture *texture, unsigned int sub_res
/* Download the sub-resource to system memory. */
if (sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB))
{
struct wined3d_bo_address data;
wined3d_texture_bind_and_dirtify(texture, context,
!(sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB));
texture2d_download_data(texture, sub_resource_idx, context, dst_location);
wined3d_texture_get_memory(texture, sub_resource_idx, &data, dst_location);
wined3d_texture_download_data(texture, sub_resource_idx, context, &data);
++texture->download_count;
return TRUE;
}
......
......@@ -3347,6 +3347,8 @@ void wined3d_texture_bind_and_dirtify(struct wined3d_texture *texture,
struct wined3d_context *context, BOOL srgb) DECLSPEC_HIDDEN;
HRESULT wined3d_texture_check_box_dimensions(const struct wined3d_texture *texture,
unsigned int level, const struct wined3d_box *box) DECLSPEC_HIDDEN;
void wined3d_texture_download_data(struct wined3d_texture *texture, unsigned int sub_resource_idx,
struct wined3d_context *context, const struct wined3d_bo_address *data) DECLSPEC_HIDDEN;
GLenum wined3d_texture_get_gl_buffer(const struct wined3d_texture *texture) DECLSPEC_HIDDEN;
void wined3d_texture_get_memory(struct wined3d_texture *texture, unsigned int sub_resource_idx,
struct wined3d_bo_address *data, DWORD locations) DECLSPEC_HIDDEN;
......
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