From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx10_43/tests/d3dx10.c | 3 +- dlls/d3dx10_43/texture.c | 97 +++++++++++++++++++++-------------- dlls/d3dx9_36/d3dx_helpers.c | 69 +++++++++++++++++++++++++ dlls/d3dx9_36/d3dx_helpers.h | 17 ++++++ 4 files changed, 146 insertions(+), 40 deletions(-)
diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c index 49292c8982a..486e77ca549 100644 --- a/dlls/d3dx10_43/tests/d3dx10.c +++ b/dlls/d3dx10_43/tests/d3dx10.c @@ -1114,7 +1114,7 @@ static const struct test_invalid_image_load_info 2, 2, D3DX10_DEFAULT, D3DX10_DEFAULT, 2, (D3D10_USAGE)D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, 7 }, - D3DERR_INVALIDCALL, D3DERR_INVALIDCALL, .todo_hr = TRUE, .todo_process_hr = TRUE + D3DERR_INVALIDCALL, D3DERR_INVALIDCALL }, /* * Usage/BindFlags/CpuAccessFlags are validated in the call to @@ -1978,7 +1978,6 @@ static void check_resource_info(ID3D10Resource *resource, const struct test_imag ok_(__FILE__, line)(desc_2d.Height == expected_height, "Got unexpected Height %u, expected %u.\n", desc_2d.Height, expected_height); - todo_wine_if(expected_mip_levels != image->expected_info.MipLevels) ok_(__FILE__, line)(desc_2d.MipLevels == expected_mip_levels, "Got unexpected MipLevels %u, expected %u.\n", desc_2d.MipLevels, expected_mip_levels); diff --git a/dlls/d3dx10_43/texture.c b/dlls/d3dx10_43/texture.c index db33bd20a1f..1c9f303929a 100644 --- a/dlls/d3dx10_43/texture.c +++ b/dlls/d3dx10_43/texture.c @@ -638,8 +638,8 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO D3D10_SUBRESOURCE_DATA **resource_data) { const struct pixel_format_desc *fmt_desc, *src_desc; - BYTE *res_data = NULL, *pixels_buffer; - uint32_t pixels_size, pixels_offset; + struct d3dx_subresource_data *sub_rsrcs = NULL; + uint32_t loaded_mip_levels, max_mip_levels; D3DX10_IMAGE_INFO img_info; struct d3dx_image image; unsigned int i, j; @@ -650,8 +650,6 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO
if (load_info->FirstMipLevel != D3DX10_DEFAULT) FIXME("load_info->FirstMipLevel is ignored.\n"); - if (load_info->MipLevels != D3DX10_DEFAULT) - FIXME("load_info->MipLevels is ignored.\n"); if (load_info->Usage != D3DX10_DEFAULT) FIXME("load_info->Usage is ignored.\n"); if (load_info->BindFlags != D3DX10_DEFAULT) @@ -660,8 +658,6 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO FIXME("load_info->CpuAccessFlags is ignored.\n"); if (load_info->MiscFlags != D3DX10_DEFAULT) FIXME("load_info->MiscFlags is ignored.\n"); - if (load_info->MipFilter != D3DX10_DEFAULT) - FIXME("load_info->MipFilter is ignored.\n");
*resource_data = NULL; if (!load_info->Filter || load_info->Filter == D3DX10_DEFAULT) @@ -717,62 +713,89 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO goto end; }
- load_info->MipLevels = img_info.MipLevels; + max_mip_levels = d3dx_get_max_mip_levels_for_size(load_info->Width, load_info->Height, load_info->Depth); + if (!load_info->MipLevels || load_info->MipLevels == D3DX10_DEFAULT || load_info->MipLevels == D3DX10_FROM_FILE) + load_info->MipLevels = (load_info->MipLevels == D3DX10_FROM_FILE) ? img_info.MipLevels : max_mip_levels; + load_info->MipLevels = min(max_mip_levels, load_info->MipLevels);
- pixels_size = d3dx_calculate_layer_pixels_size(fmt_desc->format, load_info->Width, load_info->Height, - load_info->Depth, load_info->MipLevels) * img_info.ArraySize; - pixels_offset = (sizeof(**resource_data) * load_info->MipLevels * img_info.ArraySize); - if (!(res_data = malloc(pixels_size + pixels_offset))) - { - hr = E_OUTOFMEMORY; + hr = d3dx_create_subresource_data_for_texture(load_info->Width, load_info->Height, load_info->Depth, + load_info->MipLevels, img_info.ArraySize, fmt_desc, &sub_rsrcs); + if (FAILED(hr)) goto end; - } - - pixels_buffer = res_data + pixels_offset; - *resource_data = (D3D10_SUBRESOURCE_DATA *)res_data;
src_desc = get_d3dx_pixel_format_info(image.format); + loaded_mip_levels = min(img_info.MipLevels, load_info->MipLevels); for (i = 0; i < img_info.ArraySize; ++i) { struct volume dst_size = { load_info->Width, load_info->Height, load_info->Depth };
- for (j = 0; j < load_info->MipLevels; ++j) + for (j = 0; j < loaded_mip_levels; ++j) { + struct d3dx_subresource_data *sub_rsrc = &sub_rsrcs[i * load_info->MipLevels + j]; const RECT unaligned_rect = { 0, 0, dst_size.width, dst_size.height }; struct d3dx_pixels src_pixels, dst_pixels; - uint32_t dst_row_pitch, dst_slice_pitch;
hr = d3dx_image_get_pixels(&image, i, j, &src_pixels); if (FAILED(hr)) - break; + goto end;
- hr = d3dx_calculate_pixels_size(fmt_desc->format, dst_size.width, dst_size.height, &dst_row_pitch, - &dst_slice_pitch); - if (FAILED(hr)) - break; - - set_d3dx_pixels(&dst_pixels, pixels_buffer, dst_row_pitch, dst_slice_pitch, NULL, dst_size.width, + set_d3dx_pixels(&dst_pixels, sub_rsrc->data, sub_rsrc->row_pitch, sub_rsrc->slice_pitch, NULL, dst_size.width, dst_size.height, dst_size.depth, &unaligned_rect);
hr = d3dx_load_pixels_from_pixels(&dst_pixels, fmt_desc, &src_pixels, src_desc, load_info->Filter, 0); if (FAILED(hr)) - break; - - (*resource_data)[i * load_info->MipLevels + j].pSysMem = pixels_buffer; - (*resource_data)[i * load_info->MipLevels + j].SysMemPitch = dst_row_pitch; - (*resource_data)[i * load_info->MipLevels + j].SysMemSlicePitch = dst_slice_pitch; + goto end;
- pixels_buffer += dst_slice_pitch * dst_size.depth; d3dx_get_next_mip_level_size(&dst_size); } }
- if (FAILED(hr)) + if (loaded_mip_levels < load_info->MipLevels) { - *resource_data = NULL; - goto end; + struct volume base_level_size = { load_info->Width, load_info->Height, load_info->Depth }; + const uint32_t base_level = loaded_mip_levels - 1; + + if (!load_info->MipFilter || load_info->MipFilter == D3DX10_DEFAULT) + load_info->MipFilter = D3DX10_FILTER_LINEAR; + if (FAILED(hr = d3dx_validate_filter(load_info->MipFilter))) + { + ERR("Invalid mip filter argument %#x.\n", load_info->MipFilter); + goto end; + } + + d3dx_get_mip_level_size(&base_level_size, base_level); + for (i = 0; i < img_info.ArraySize; ++i) + { + struct volume src_size, dst_size; + + src_size = dst_size = base_level_size; + for (j = base_level; j < (load_info->MipLevels - 1); ++j) + { + struct d3dx_subresource_data *dst_data = &sub_rsrcs[i * load_info->MipLevels + j + 1]; + struct d3dx_subresource_data *src_data = &sub_rsrcs[i * load_info->MipLevels + j]; + const RECT src_unaligned_rect = { 0, 0, src_size.width, src_size.height }; + struct d3dx_pixels src_pixels, dst_pixels; + RECT dst_unaligned_rect; + + d3dx_get_next_mip_level_size(&dst_size); + SetRect(&dst_unaligned_rect, 0, 0, dst_size.width, dst_size.height); + set_d3dx_pixels(&dst_pixels, dst_data->data, dst_data->row_pitch, dst_data->slice_pitch, NULL, + dst_size.width, dst_size.height, dst_size.depth, &dst_unaligned_rect); + set_d3dx_pixels(&src_pixels, src_data->data, src_data->row_pitch, src_data->slice_pitch, NULL, + src_size.width, src_size.height, src_size.depth, &src_unaligned_rect); + + hr = d3dx_load_pixels_from_pixels(&dst_pixels, fmt_desc, &src_pixels, fmt_desc, load_info->MipFilter, 0); + if (FAILED(hr)) + goto end; + + src_size = dst_size; + } + } }
+ *resource_data = (D3D10_SUBRESOURCE_DATA *)sub_rsrcs; + sub_rsrcs = NULL; + load_info->Usage = D3D10_USAGE_DEFAULT; load_info->BindFlags = D3D10_BIND_SHADER_RESOURCE; load_info->MiscFlags = img_info.MiscFlags; @@ -783,11 +806,9 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO assert(load_info->pSrcInfo); *load_info->pSrcInfo = img_info;
- res_data = NULL; - end: d3dx_image_cleanup(&image); - free(res_data); + free(sub_rsrcs); return hr; }
diff --git a/dlls/d3dx9_36/d3dx_helpers.c b/dlls/d3dx9_36/d3dx_helpers.c index 3e1bda400d7..69a54ed4188 100644 --- a/dlls/d3dx9_36/d3dx_helpers.c +++ b/dlls/d3dx9_36/d3dx_helpers.c @@ -445,6 +445,28 @@ void d3dx_get_next_mip_level_size(struct volume *size) size->depth = max(size->depth / 2, 1); }
+void d3dx_get_mip_level_size(struct volume *size, uint32_t level) +{ + uint32_t i; + + for (i = 0; i < level; ++i) + d3dx_get_next_mip_level_size(size); +} + +uint32_t d3dx_get_max_mip_levels_for_size(uint32_t width, uint32_t height, uint32_t depth) +{ + struct volume tmp = { width, height, depth }; + uint32_t mip_levels = 1; + + while (!(tmp.width == 1 && tmp.height == 1 && tmp.depth == 1)) + { + d3dx_get_next_mip_level_size(&tmp); + mip_levels++; + } + + return mip_levels; +} + static const char *debug_volume(const struct volume *volume) { if (!volume) @@ -3158,3 +3180,50 @@ void get_aligned_rect(uint32_t left, uint32_t top, uint32_t right, uint32_t bott aligned_rect->bottom = min((aligned_rect->bottom + fmt_desc->block_height - 1) & ~(fmt_desc->block_height - 1), height); } + +HRESULT d3dx_create_subresource_data_for_texture(uint32_t width, uint32_t height, uint32_t depth, + uint32_t mip_levels, uint32_t layer_count, const struct pixel_format_desc *fmt_desc, + struct d3dx_subresource_data **out_sub_rsrc_data) +{ + struct d3dx_subresource_data *sub_rsrcs = NULL; + uint8_t *sub_rsrc_data = NULL, *pixels_ptr; + uint32_t pixels_size, pixels_offset; + unsigned int i, j; + HRESULT hr = S_OK; + + *out_sub_rsrc_data = NULL; + pixels_offset = sizeof(*sub_rsrcs) * mip_levels * layer_count; + pixels_size = d3dx_calculate_layer_pixels_size(fmt_desc->format, width, height, depth, mip_levels) * layer_count; + if (!(sub_rsrc_data = malloc(pixels_size + pixels_offset))) + return E_OUTOFMEMORY; + + sub_rsrcs = (struct d3dx_subresource_data *)sub_rsrc_data; + pixels_ptr = sub_rsrc_data + pixels_offset; + for (i = 0; i < layer_count; ++i) + { + struct volume size = { width, height, depth }; + + for (j = 0; j < mip_levels; ++j) + { + uint32_t row_pitch, slice_pitch; + + hr = d3dx_calculate_pixels_size(fmt_desc->format, size.width, size.height, &row_pitch, &slice_pitch); + if (FAILED(hr)) + goto exit; + + sub_rsrcs[i * mip_levels + j].data = pixels_ptr; + sub_rsrcs[i * mip_levels + j].row_pitch = row_pitch; + sub_rsrcs[i * mip_levels + j].slice_pitch = slice_pitch; + + pixels_ptr += slice_pitch * size.depth; + d3dx_get_next_mip_level_size(&size); + } + } + + *out_sub_rsrc_data = sub_rsrcs; + sub_rsrc_data = NULL; + +exit: + free(sub_rsrc_data); + return hr; +} diff --git a/dlls/d3dx9_36/d3dx_helpers.h b/dlls/d3dx9_36/d3dx_helpers.h index 83c213db311..aadbb2a9ea6 100644 --- a/dlls/d3dx9_36/d3dx_helpers.h +++ b/dlls/d3dx9_36/d3dx_helpers.h @@ -404,6 +404,8 @@ void format_from_d3dx_color(const struct pixel_format_desc *format, const struct
enum d3dx_pixel_format_id d3dx_pixel_format_id_from_dxgi_format(uint32_t format); void d3dx_get_next_mip_level_size(struct volume *size); +void d3dx_get_mip_level_size(struct volume *size, uint32_t level); +uint32_t d3dx_get_max_mip_levels_for_size(uint32_t width, uint32_t height, uint32_t depth); HRESULT d3dx_calculate_pixels_size(enum d3dx_pixel_format_id format, uint32_t width, uint32_t height, uint32_t *pitch, uint32_t *size); uint32_t d3dx_calculate_layer_pixels_size(enum d3dx_pixel_format_id format, uint32_t width, uint32_t height, @@ -438,6 +440,21 @@ struct d3dx_buffer_wrapper HRESULT d3dx_save_pixels_to_memory(struct d3dx_pixels *src_pixels, const struct pixel_format_desc *src_fmt_desc, enum d3dx_image_file_format file_format, const struct d3dx_buffer_wrapper *wrapper, struct d3dx_buffer *dst_buffer);
+/* + * Structure that is able to be cast to D3D10_SUBRESOURCE_DATA and + * D3D11_SUBRESOURCE_DATA. + */ +struct d3dx_subresource_data +{ + const void *data; + UINT row_pitch; + UINT slice_pitch; +}; + +HRESULT d3dx_create_subresource_data_for_texture(uint32_t width, uint32_t height, uint32_t depth, + uint32_t mip_levels, uint32_t layer_count, const struct pixel_format_desc *fmt_desc, + struct d3dx_subresource_data **out_sub_rsrc_data); + /* debug helpers */ const char *debug_d3dx_image_file_format(enum d3dx_image_file_format format); #endif /* __WINE_D3DX_HELPERS_H */