d3dx10: Add D3DX10CreateAsyncTextureProcessor implementation.
[wine.git] / dlls / d3dx10_43 / texture.c
blob7a43d8409dad16189fadf2e20413a13d0f98bfc1
1 /*
2 * Copyright 2020 Ziqing Hui for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "wine/debug.h"
21 #define COBJMACROS
23 #include "d3d10_1.h"
24 #include "d3dx10.h"
25 #include "wincodec.h"
26 #include "dxhelpers.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
30 HRESULT WINAPI WICCreateImagingFactory_Proxy(UINT sdk_version, IWICImagingFactory **imaging_factory);
32 static const struct
34 const GUID *wic_container_guid;
35 D3DX10_IMAGE_FILE_FORMAT d3dx_file_format;
37 file_formats[] =
39 { &GUID_ContainerFormatBmp, D3DX10_IFF_BMP },
40 { &GUID_ContainerFormatJpeg, D3DX10_IFF_JPG },
41 { &GUID_ContainerFormatPng, D3DX10_IFF_PNG },
42 { &GUID_ContainerFormatDds, D3DX10_IFF_DDS },
43 { &GUID_ContainerFormatTiff, D3DX10_IFF_TIFF },
44 { &GUID_ContainerFormatGif, D3DX10_IFF_GIF },
45 { &GUID_ContainerFormatWmp, D3DX10_IFF_WMP },
48 static const struct
50 const GUID *wic_guid;
51 DXGI_FORMAT dxgi_format;
53 wic_pixel_formats[] =
55 { &GUID_WICPixelFormatBlackWhite, DXGI_FORMAT_R1_UNORM },
56 { &GUID_WICPixelFormat8bppAlpha, DXGI_FORMAT_A8_UNORM },
57 { &GUID_WICPixelFormat8bppGray, DXGI_FORMAT_R8_UNORM },
58 { &GUID_WICPixelFormat16bppGray, DXGI_FORMAT_R16_UNORM },
59 { &GUID_WICPixelFormat16bppGrayHalf, DXGI_FORMAT_R16_FLOAT },
60 { &GUID_WICPixelFormat32bppGrayFloat, DXGI_FORMAT_R32_FLOAT },
61 { &GUID_WICPixelFormat16bppBGR565, DXGI_FORMAT_B5G6R5_UNORM },
62 { &GUID_WICPixelFormat16bppBGRA5551, DXGI_FORMAT_B5G5R5A1_UNORM },
63 { &GUID_WICPixelFormat32bppBGR, DXGI_FORMAT_B8G8R8X8_UNORM },
64 { &GUID_WICPixelFormat32bppBGRA, DXGI_FORMAT_B8G8R8A8_UNORM },
65 { &GUID_WICPixelFormat32bppRGBA, DXGI_FORMAT_R8G8B8A8_UNORM },
66 { &GUID_WICPixelFormat32bppRGBA1010102, DXGI_FORMAT_R10G10B10A2_UNORM },
67 { &GUID_WICPixelFormat32bppRGBA1010102XR, DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM },
68 { &GUID_WICPixelFormat64bppRGBA, DXGI_FORMAT_R16G16B16A16_UNORM },
69 { &GUID_WICPixelFormat64bppRGBAHalf, DXGI_FORMAT_R16G16B16A16_FLOAT },
70 { &GUID_WICPixelFormat96bppRGBFloat, DXGI_FORMAT_R32G32B32_FLOAT },
71 { &GUID_WICPixelFormat128bppRGBAFloat, DXGI_FORMAT_R32G32B32A32_FLOAT }
74 static const DXGI_FORMAT block_compressed_formats[] =
76 DXGI_FORMAT_BC1_TYPELESS, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM_SRGB,
77 DXGI_FORMAT_BC2_TYPELESS, DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_BC2_UNORM_SRGB,
78 DXGI_FORMAT_BC3_TYPELESS, DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_BC3_UNORM_SRGB,
79 DXGI_FORMAT_BC4_TYPELESS, DXGI_FORMAT_BC4_UNORM, DXGI_FORMAT_BC4_SNORM,
80 DXGI_FORMAT_BC5_TYPELESS, DXGI_FORMAT_BC5_UNORM, DXGI_FORMAT_BC5_SNORM,
81 DXGI_FORMAT_BC6H_TYPELESS, DXGI_FORMAT_BC6H_UF16, DXGI_FORMAT_BC6H_SF16,
82 DXGI_FORMAT_BC7_TYPELESS, DXGI_FORMAT_BC7_UNORM, DXGI_FORMAT_BC7_UNORM_SRGB
85 static const DXGI_FORMAT to_be_converted_format[] =
87 DXGI_FORMAT_UNKNOWN,
88 DXGI_FORMAT_R8_UNORM,
89 DXGI_FORMAT_R8G8_UNORM,
90 DXGI_FORMAT_B5G6R5_UNORM,
91 DXGI_FORMAT_B4G4R4A4_UNORM,
92 DXGI_FORMAT_B5G5R5A1_UNORM,
93 DXGI_FORMAT_B8G8R8X8_UNORM,
94 DXGI_FORMAT_B8G8R8A8_UNORM
97 static D3DX10_IMAGE_FILE_FORMAT wic_container_guid_to_file_format(GUID *container_format)
99 unsigned int i;
101 for (i = 0; i < ARRAY_SIZE(file_formats); ++i)
103 if (IsEqualGUID(file_formats[i].wic_container_guid, container_format))
104 return file_formats[i].d3dx_file_format;
106 return D3DX10_IFF_FORCE_DWORD;
109 static const GUID *dxgi_format_to_wic_guid(DXGI_FORMAT format)
111 unsigned int i;
113 for (i = 0; i < ARRAY_SIZE(wic_pixel_formats); ++i)
115 if (wic_pixel_formats[i].dxgi_format == format)
116 return wic_pixel_formats[i].wic_guid;
119 return NULL;
122 static D3D10_RESOURCE_DIMENSION wic_dimension_to_d3dx10_dimension(WICDdsDimension wic_dimension)
124 switch (wic_dimension)
126 case WICDdsTexture1D:
127 return D3D10_RESOURCE_DIMENSION_TEXTURE1D;
128 case WICDdsTexture2D:
129 case WICDdsTextureCube:
130 return D3D10_RESOURCE_DIMENSION_TEXTURE2D;
131 case WICDdsTexture3D:
132 return D3D10_RESOURCE_DIMENSION_TEXTURE3D;
133 default:
134 return D3D10_RESOURCE_DIMENSION_UNKNOWN;
138 static BOOL is_block_compressed(DXGI_FORMAT format)
140 unsigned int i;
142 for (i = 0; i < ARRAY_SIZE(block_compressed_formats); ++i)
143 if (format == block_compressed_formats[i])
144 return TRUE;
146 return FALSE;
149 static unsigned int get_bpp_from_format(DXGI_FORMAT format)
151 switch (format)
153 case DXGI_FORMAT_R32G32B32A32_TYPELESS:
154 case DXGI_FORMAT_R32G32B32A32_FLOAT:
155 case DXGI_FORMAT_R32G32B32A32_UINT:
156 case DXGI_FORMAT_R32G32B32A32_SINT:
157 return 128;
158 case DXGI_FORMAT_R32G32B32_TYPELESS:
159 case DXGI_FORMAT_R32G32B32_FLOAT:
160 case DXGI_FORMAT_R32G32B32_UINT:
161 case DXGI_FORMAT_R32G32B32_SINT:
162 return 96;
163 case DXGI_FORMAT_R16G16B16A16_TYPELESS:
164 case DXGI_FORMAT_R16G16B16A16_FLOAT:
165 case DXGI_FORMAT_R16G16B16A16_UNORM:
166 case DXGI_FORMAT_R16G16B16A16_UINT:
167 case DXGI_FORMAT_R16G16B16A16_SNORM:
168 case DXGI_FORMAT_R16G16B16A16_SINT:
169 case DXGI_FORMAT_R32G32_TYPELESS:
170 case DXGI_FORMAT_R32G32_FLOAT:
171 case DXGI_FORMAT_R32G32_UINT:
172 case DXGI_FORMAT_R32G32_SINT:
173 case DXGI_FORMAT_R32G8X24_TYPELESS:
174 case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
175 case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
176 case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
177 case DXGI_FORMAT_Y416:
178 case DXGI_FORMAT_Y210:
179 case DXGI_FORMAT_Y216:
180 return 64;
181 case DXGI_FORMAT_R10G10B10A2_TYPELESS:
182 case DXGI_FORMAT_R10G10B10A2_UNORM:
183 case DXGI_FORMAT_R10G10B10A2_UINT:
184 case DXGI_FORMAT_R11G11B10_FLOAT:
185 case DXGI_FORMAT_R8G8B8A8_TYPELESS:
186 case DXGI_FORMAT_R8G8B8A8_UNORM:
187 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
188 case DXGI_FORMAT_R8G8B8A8_UINT:
189 case DXGI_FORMAT_R8G8B8A8_SNORM:
190 case DXGI_FORMAT_R8G8B8A8_SINT:
191 case DXGI_FORMAT_R16G16_TYPELESS:
192 case DXGI_FORMAT_R16G16_FLOAT:
193 case DXGI_FORMAT_R16G16_UNORM:
194 case DXGI_FORMAT_R16G16_UINT:
195 case DXGI_FORMAT_R16G16_SNORM:
196 case DXGI_FORMAT_R16G16_SINT:
197 case DXGI_FORMAT_R32_TYPELESS:
198 case DXGI_FORMAT_D32_FLOAT:
199 case DXGI_FORMAT_R32_FLOAT:
200 case DXGI_FORMAT_R32_UINT:
201 case DXGI_FORMAT_R32_SINT:
202 case DXGI_FORMAT_R24G8_TYPELESS:
203 case DXGI_FORMAT_D24_UNORM_S8_UINT:
204 case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
205 case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
206 case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
207 case DXGI_FORMAT_R8G8_B8G8_UNORM:
208 case DXGI_FORMAT_G8R8_G8B8_UNORM:
209 case DXGI_FORMAT_B8G8R8A8_UNORM:
210 case DXGI_FORMAT_B8G8R8X8_UNORM:
211 case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
212 case DXGI_FORMAT_B8G8R8A8_TYPELESS:
213 case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
214 case DXGI_FORMAT_B8G8R8X8_TYPELESS:
215 case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
216 case DXGI_FORMAT_AYUV:
217 case DXGI_FORMAT_Y410:
218 case DXGI_FORMAT_YUY2:
219 return 32;
220 case DXGI_FORMAT_P010:
221 case DXGI_FORMAT_P016:
222 return 24;
223 case DXGI_FORMAT_R8G8_TYPELESS:
224 case DXGI_FORMAT_R8G8_UNORM:
225 case DXGI_FORMAT_R8G8_UINT:
226 case DXGI_FORMAT_R8G8_SNORM:
227 case DXGI_FORMAT_R8G8_SINT:
228 case DXGI_FORMAT_R16_TYPELESS:
229 case DXGI_FORMAT_R16_FLOAT:
230 case DXGI_FORMAT_D16_UNORM:
231 case DXGI_FORMAT_R16_UNORM:
232 case DXGI_FORMAT_R16_UINT:
233 case DXGI_FORMAT_R16_SNORM:
234 case DXGI_FORMAT_R16_SINT:
235 case DXGI_FORMAT_B5G6R5_UNORM:
236 case DXGI_FORMAT_B5G5R5A1_UNORM:
237 case DXGI_FORMAT_A8P8:
238 case DXGI_FORMAT_B4G4R4A4_UNORM:
239 return 16;
240 case DXGI_FORMAT_NV12:
241 case DXGI_FORMAT_420_OPAQUE:
242 case DXGI_FORMAT_NV11:
243 return 12;
244 case DXGI_FORMAT_R8_TYPELESS:
245 case DXGI_FORMAT_R8_UNORM:
246 case DXGI_FORMAT_R8_UINT:
247 case DXGI_FORMAT_R8_SNORM:
248 case DXGI_FORMAT_R8_SINT:
249 case DXGI_FORMAT_A8_UNORM:
250 case DXGI_FORMAT_AI44:
251 case DXGI_FORMAT_IA44:
252 case DXGI_FORMAT_P8:
253 case DXGI_FORMAT_BC2_TYPELESS:
254 case DXGI_FORMAT_BC2_UNORM:
255 case DXGI_FORMAT_BC2_UNORM_SRGB:
256 case DXGI_FORMAT_BC3_TYPELESS:
257 case DXGI_FORMAT_BC3_UNORM:
258 case DXGI_FORMAT_BC3_UNORM_SRGB:
259 case DXGI_FORMAT_BC5_TYPELESS:
260 case DXGI_FORMAT_BC5_UNORM:
261 case DXGI_FORMAT_BC5_SNORM:
262 case DXGI_FORMAT_BC6H_TYPELESS:
263 case DXGI_FORMAT_BC6H_UF16:
264 case DXGI_FORMAT_BC6H_SF16:
265 case DXGI_FORMAT_BC7_TYPELESS:
266 case DXGI_FORMAT_BC7_UNORM:
267 case DXGI_FORMAT_BC7_UNORM_SRGB:
268 return 8;
269 case DXGI_FORMAT_BC1_TYPELESS:
270 case DXGI_FORMAT_BC1_UNORM:
271 case DXGI_FORMAT_BC1_UNORM_SRGB:
272 case DXGI_FORMAT_BC4_TYPELESS:
273 case DXGI_FORMAT_BC4_UNORM:
274 case DXGI_FORMAT_BC4_SNORM:
275 return 4;
276 case DXGI_FORMAT_R1_UNORM:
277 return 1;
278 default:
279 return 0;
283 static DXGI_FORMAT get_d3dx10_dds_format(DXGI_FORMAT format)
285 unsigned int i;
287 for (i = 0; i < ARRAY_SIZE(to_be_converted_format); ++i)
289 if (format == to_be_converted_format[i])
290 return DXGI_FORMAT_R8G8B8A8_UNORM;
292 return format;
295 HRESULT WINAPI D3DX10GetImageInfoFromFileA(const char *src_file, ID3DX10ThreadPump *pump, D3DX10_IMAGE_INFO *info,
296 HRESULT *result)
298 WCHAR *buffer;
299 int str_len;
300 HRESULT hr;
302 TRACE("src_file %s, pump %p, info %p, result %p.\n", debugstr_a(src_file), pump, info, result);
304 if (!src_file)
305 return E_FAIL;
307 str_len = MultiByteToWideChar(CP_ACP, 0, src_file, -1, NULL, 0);
308 if (!str_len)
309 return HRESULT_FROM_WIN32(GetLastError());
311 buffer = malloc(str_len * sizeof(*buffer));
312 if (!buffer)
313 return E_OUTOFMEMORY;
315 MultiByteToWideChar(CP_ACP, 0, src_file, -1, buffer, str_len);
316 hr = D3DX10GetImageInfoFromFileW(buffer, pump, info, result);
318 free(buffer);
320 return hr;
323 HRESULT WINAPI D3DX10GetImageInfoFromFileW(const WCHAR *src_file, ID3DX10ThreadPump *pump, D3DX10_IMAGE_INFO *info,
324 HRESULT *result)
326 void *buffer = NULL;
327 DWORD size = 0;
328 HRESULT hr;
330 TRACE("src_file %s, pump %p, info %p, result %p.\n", debugstr_w(src_file), pump, info, result);
332 if (!src_file)
333 return E_FAIL;
335 if (pump)
337 ID3DX10DataProcessor *processor;
338 ID3DX10DataLoader *loader;
340 if (FAILED((hr = D3DX10CreateAsyncFileLoaderW(src_file, &loader))))
341 return hr;
342 if (FAILED((hr = D3DX10CreateAsyncTextureInfoProcessor(info, &processor))))
344 ID3DX10DataLoader_Destroy(loader);
345 return hr;
347 hr = ID3DX10ThreadPump_AddWorkItem(pump, loader, processor, result, NULL);
348 if (FAILED(hr))
350 ID3DX10DataLoader_Destroy(loader);
351 ID3DX10DataProcessor_Destroy(processor);
353 return hr;
356 if (SUCCEEDED((hr = load_file(src_file, &buffer, &size))))
358 hr = get_image_info(buffer, size, info);
359 free(buffer);
361 if (result)
362 *result = hr;
363 return hr;
366 HRESULT WINAPI D3DX10GetImageInfoFromResourceA(HMODULE module, const char *resource, ID3DX10ThreadPump *pump,
367 D3DX10_IMAGE_INFO *info, HRESULT *result)
369 void *buffer;
370 HRESULT hr;
371 DWORD size;
373 TRACE("module %p, resource %s, pump %p, info %p, result %p.\n",
374 module, debugstr_a(resource), pump, info, result);
376 if (pump)
378 ID3DX10DataProcessor *processor;
379 ID3DX10DataLoader *loader;
381 if (FAILED((hr = D3DX10CreateAsyncResourceLoaderA(module, resource, &loader))))
382 return hr;
383 if (FAILED((hr = D3DX10CreateAsyncTextureInfoProcessor(info, &processor))))
385 ID3DX10DataLoader_Destroy(loader);
386 return hr;
388 if (FAILED((hr = ID3DX10ThreadPump_AddWorkItem(pump, loader, processor, result, NULL))))
390 ID3DX10DataLoader_Destroy(loader);
391 ID3DX10DataProcessor_Destroy(processor);
393 return hr;
396 if (FAILED((hr = load_resourceA(module, resource, &buffer, &size))))
397 return hr;
398 hr = get_image_info(buffer, size, info);
399 if (result)
400 *result = hr;
401 return hr;
404 HRESULT WINAPI D3DX10GetImageInfoFromResourceW(HMODULE module, const WCHAR *resource, ID3DX10ThreadPump *pump,
405 D3DX10_IMAGE_INFO *info, HRESULT *result)
407 void *buffer;
408 HRESULT hr;
409 DWORD size;
411 TRACE("module %p, resource %s, pump %p, info %p, result %p.\n",
412 module, debugstr_w(resource), pump, info, result);
414 if (pump)
416 ID3DX10DataProcessor *processor;
417 ID3DX10DataLoader *loader;
419 if (FAILED((hr = D3DX10CreateAsyncResourceLoaderW(module, resource, &loader))))
420 return hr;
421 if (FAILED((hr = D3DX10CreateAsyncTextureInfoProcessor(info, &processor))))
423 ID3DX10DataLoader_Destroy(loader);
424 return hr;
426 if (FAILED((hr = ID3DX10ThreadPump_AddWorkItem(pump, loader, processor, result, NULL))))
428 ID3DX10DataLoader_Destroy(loader);
429 ID3DX10DataProcessor_Destroy(processor);
431 return hr;
434 if (FAILED((hr = load_resourceW(module, resource, &buffer, &size))))
435 return hr;
436 hr = get_image_info(buffer, size, info);
437 if (result)
438 *result = hr;
439 return hr;
442 HRESULT get_image_info(const void *data, SIZE_T size, D3DX10_IMAGE_INFO *img_info)
444 IWICBitmapFrameDecode *frame = NULL;
445 IWICImagingFactory *factory = NULL;
446 IWICDdsDecoder *dds_decoder = NULL;
447 IWICBitmapDecoder *decoder = NULL;
448 WICDdsParameters dds_params;
449 IWICStream *stream = NULL;
450 unsigned int frame_count;
451 GUID container_format;
452 HRESULT hr;
454 WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory);
455 IWICImagingFactory_CreateStream(factory, &stream);
456 hr = IWICStream_InitializeFromMemory(stream, (BYTE *)data, size);
457 if (FAILED(hr))
459 WARN("Failed to initialize stream.\n");
460 goto end;
462 hr = IWICImagingFactory_CreateDecoderFromStream(factory, (IStream *)stream, NULL, 0, &decoder);
463 if (FAILED(hr))
464 goto end;
466 hr = IWICBitmapDecoder_GetContainerFormat(decoder, &container_format);
467 if (FAILED(hr))
468 goto end;
469 img_info->ImageFileFormat = wic_container_guid_to_file_format(&container_format);
470 if (img_info->ImageFileFormat == D3DX10_IFF_FORCE_DWORD)
472 hr = E_FAIL;
473 WARN("Unsupported image file format %s.\n", debugstr_guid(&container_format));
474 goto end;
477 hr = IWICBitmapDecoder_GetFrameCount(decoder, &frame_count);
478 if (FAILED(hr) || !frame_count)
479 goto end;
480 hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
481 if (FAILED(hr))
482 goto end;
483 hr = IWICBitmapFrameDecode_GetSize(frame, &img_info->Width, &img_info->Height);
484 if (FAILED(hr))
485 goto end;
487 if (img_info->ImageFileFormat == D3DX10_IFF_DDS)
489 hr = IWICBitmapDecoder_QueryInterface(decoder, &IID_IWICDdsDecoder, (void **)&dds_decoder);
490 if (FAILED(hr))
491 goto end;
492 hr = IWICDdsDecoder_GetParameters(dds_decoder, &dds_params);
493 if (FAILED(hr))
494 goto end;
495 img_info->ArraySize = dds_params.ArraySize;
496 img_info->Depth = dds_params.Depth;
497 img_info->MipLevels = dds_params.MipLevels;
498 img_info->ResourceDimension = wic_dimension_to_d3dx10_dimension(dds_params.Dimension);
499 img_info->Format = get_d3dx10_dds_format(dds_params.DxgiFormat);
500 img_info->MiscFlags = 0;
501 if (dds_params.Dimension == WICDdsTextureCube)
503 img_info->MiscFlags = D3D10_RESOURCE_MISC_TEXTURECUBE;
504 img_info->ArraySize *= 6;
507 else
509 img_info->ArraySize = 1;
510 img_info->Depth = 1;
511 img_info->MipLevels = 1;
512 img_info->ResourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D;
513 img_info->Format = DXGI_FORMAT_R8G8B8A8_UNORM;
514 img_info->MiscFlags = 0;
517 end:
518 if (dds_decoder)
519 IWICDdsDecoder_Release(dds_decoder);
520 if (frame)
521 IWICBitmapFrameDecode_Release(frame);
522 if (decoder)
523 IWICBitmapDecoder_Release(decoder);
524 if (stream)
525 IWICStream_Release(stream);
526 if (factory)
527 IWICImagingFactory_Release(factory);
529 if (hr != S_OK)
531 WARN("Invalid or unsupported image file.\n");
532 return E_FAIL;
534 return S_OK;
537 HRESULT WINAPI D3DX10GetImageInfoFromMemory(const void *src_data, SIZE_T src_data_size, ID3DX10ThreadPump *pump,
538 D3DX10_IMAGE_INFO *img_info, HRESULT *result)
540 HRESULT hr;
542 TRACE("src_data %p, src_data_size %Iu, pump %p, img_info %p, hresult %p.\n",
543 src_data, src_data_size, pump, img_info, result);
545 if (!src_data)
546 return E_FAIL;
548 if (pump)
550 ID3DX10DataProcessor *processor;
551 ID3DX10DataLoader *loader;
553 if (FAILED((hr = D3DX10CreateAsyncMemoryLoader(src_data, src_data_size, &loader))))
554 return hr;
555 if (FAILED((hr = D3DX10CreateAsyncTextureInfoProcessor(img_info, &processor))))
557 ID3DX10DataLoader_Destroy(loader);
558 return hr;
560 if (FAILED((hr = ID3DX10ThreadPump_AddWorkItem(pump, loader, processor, result, NULL))))
562 ID3DX10DataLoader_Destroy(loader);
563 ID3DX10DataProcessor_Destroy(processor);
565 return hr;
568 hr = get_image_info(src_data, src_data_size, img_info);
569 if (result)
570 *result = hr;
571 return hr;
574 static HRESULT create_texture(ID3D10Device *device, const void *data, SIZE_T size,
575 D3DX10_IMAGE_LOAD_INFO *load_info, ID3D10Resource **texture)
577 D3D10_SUBRESOURCE_DATA *resource_data;
578 D3DX10_IMAGE_LOAD_INFO load_info_copy;
579 HRESULT hr;
581 init_load_info(load_info, &load_info_copy);
583 if (FAILED((hr = load_texture_data(data, size, &load_info_copy, &resource_data))))
584 return hr;
585 hr = create_d3d_texture(device, &load_info_copy, resource_data, texture);
586 free(resource_data);
587 return hr;
590 HRESULT WINAPI D3DX10CreateTextureFromFileA(ID3D10Device *device, const char *src_file,
591 D3DX10_IMAGE_LOAD_INFO *load_info, ID3DX10ThreadPump *pump, ID3D10Resource **texture, HRESULT *hresult)
593 WCHAR *buffer;
594 int str_len;
595 HRESULT hr;
597 TRACE("device %p, src_file %s, load_info %p, pump %p, texture %p, hresult %p.\n",
598 device, debugstr_a(src_file), load_info, pump, texture, hresult);
600 if (!device)
601 return E_INVALIDARG;
602 if (!src_file)
603 return E_FAIL;
605 if (!(str_len = MultiByteToWideChar(CP_ACP, 0, src_file, -1, NULL, 0)))
606 return HRESULT_FROM_WIN32(GetLastError());
608 if (!(buffer = malloc(str_len * sizeof(*buffer))))
609 return E_OUTOFMEMORY;
611 MultiByteToWideChar(CP_ACP, 0, src_file, -1, buffer, str_len);
612 hr = D3DX10CreateTextureFromFileW(device, buffer, load_info, pump, texture, hresult);
614 free(buffer);
616 return hr;
619 HRESULT WINAPI D3DX10CreateTextureFromFileW(ID3D10Device *device, const WCHAR *src_file,
620 D3DX10_IMAGE_LOAD_INFO *load_info, ID3DX10ThreadPump *pump, ID3D10Resource **texture, HRESULT *hresult)
622 void *buffer = NULL;
623 DWORD size = 0;
624 HRESULT hr;
626 TRACE("device %p, src_file %s, load_info %p, pump %p, texture %p, hresult %p.\n",
627 device, debugstr_w(src_file), load_info, pump, texture, hresult);
629 if (!device)
630 return E_INVALIDARG;
631 if (!src_file)
632 return E_FAIL;
634 if (FAILED((hr = load_file(src_file, &buffer, &size))))
636 if (hresult)
637 *hresult = hr;
638 return hr;
641 hr = D3DX10CreateTextureFromMemory(device, buffer, size, load_info, pump, texture, hresult);
643 free(buffer);
645 return hr;
648 HRESULT WINAPI D3DX10CreateTextureFromResourceA(ID3D10Device *device, HMODULE module, const char *resource,
649 D3DX10_IMAGE_LOAD_INFO *load_info, ID3DX10ThreadPump *pump, ID3D10Resource **texture, HRESULT *hresult)
651 void *buffer;
652 DWORD size;
653 HRESULT hr;
655 TRACE("device %p, module %p, resource %s, load_info %p, pump %p, texture %p, hresult %p.\n",
656 device, module, debugstr_a(resource), load_info, pump, texture, hresult);
658 if (!device)
659 return E_INVALIDARG;
661 hr = load_resourceA(module, resource, &buffer, &size);
662 if (FAILED(hr))
663 return hr;
665 return D3DX10CreateTextureFromMemory(device, buffer, size, load_info, pump, texture, hresult);
668 HRESULT WINAPI D3DX10CreateTextureFromResourceW(ID3D10Device *device, HMODULE module, const WCHAR *resource,
669 D3DX10_IMAGE_LOAD_INFO *load_info, ID3DX10ThreadPump *pump, ID3D10Resource **texture, HRESULT *hresult)
671 void *buffer;
672 DWORD size;
673 HRESULT hr;
675 TRACE("device %p, module %p, resource %s, load_info %p, pump %p, texture %p, hresult %p.\n",
676 device, module, debugstr_w(resource), load_info, pump, texture, hresult);
678 if (!device)
679 return E_INVALIDARG;
681 hr = load_resourceW(module, resource, &buffer, &size);
682 if (FAILED(hr))
683 return hr;
685 return D3DX10CreateTextureFromMemory(device, buffer, size, load_info, pump, texture, hresult);
688 void init_load_info(const D3DX10_IMAGE_LOAD_INFO *load_info, D3DX10_IMAGE_LOAD_INFO *out)
690 if (load_info)
692 *out = *load_info;
693 return;
696 out->Width = D3DX10_DEFAULT;
697 out->Height = D3DX10_DEFAULT;
698 out->Depth = D3DX10_DEFAULT;
699 out->FirstMipLevel = D3DX10_DEFAULT;
700 out->MipLevels = D3DX10_DEFAULT;
701 out->Usage = D3DX10_DEFAULT;
702 out->BindFlags = D3DX10_DEFAULT;
703 out->CpuAccessFlags = D3DX10_DEFAULT;
704 out->MiscFlags = D3DX10_DEFAULT;
705 out->Format = D3DX10_DEFAULT;
706 out->Filter = D3DX10_DEFAULT;
707 out->MipFilter = D3DX10_DEFAULT;
708 out->pSrcInfo = NULL;
711 HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO *load_info,
712 D3D10_SUBRESOURCE_DATA **resource_data)
714 unsigned int frame_count, width, height, stride, frame_size;
715 IWICFormatConverter *converter = NULL;
716 IWICDdsFrameDecode *dds_frame = NULL;
717 IWICBitmapFrameDecode *frame = NULL;
718 IWICImagingFactory *factory = NULL;
719 IWICBitmapDecoder *decoder = NULL;
720 BYTE *res_data = NULL, *buffer;
721 D3DX10_IMAGE_INFO img_info;
722 IWICStream *stream = NULL;
723 const GUID *dst_format;
724 BOOL can_convert;
725 GUID src_format;
726 HRESULT hr;
728 if (load_info->Width != D3DX10_DEFAULT)
729 FIXME("load_info->Width is ignored.\n");
730 if (load_info->Height != D3DX10_DEFAULT)
731 FIXME("load_info->Height is ignored.\n");
732 if (load_info->Depth != D3DX10_DEFAULT)
733 FIXME("load_info->Depth is ignored.\n");
734 if (load_info->FirstMipLevel != D3DX10_DEFAULT)
735 FIXME("load_info->FirstMipLevel is ignored.\n");
736 if (load_info->MipLevels != D3DX10_DEFAULT)
737 FIXME("load_info->MipLevels is ignored.\n");
738 if (load_info->Usage != D3DX10_DEFAULT)
739 FIXME("load_info->Usage is ignored.\n");
740 if (load_info->BindFlags != D3DX10_DEFAULT)
741 FIXME("load_info->BindFlags is ignored.\n");
742 if (load_info->CpuAccessFlags != D3DX10_DEFAULT)
743 FIXME("load_info->CpuAccessFlags is ignored.\n");
744 if (load_info->MiscFlags != D3DX10_DEFAULT)
745 FIXME("load_info->MiscFlags is ignored.\n");
746 if (load_info->Format != D3DX10_DEFAULT)
747 FIXME("load_info->Format is ignored.\n");
748 if (load_info->Filter != D3DX10_DEFAULT)
749 FIXME("load_info->Filter is ignored.\n");
750 if (load_info->MipFilter != D3DX10_DEFAULT)
751 FIXME("load_info->MipFilter is ignored.\n");
752 if (load_info->pSrcInfo)
753 FIXME("load_info->pSrcInfo is ignored.\n");
755 if (FAILED(D3DX10GetImageInfoFromMemory(data, size, NULL, &img_info, NULL)))
756 return E_FAIL;
757 if (img_info.MiscFlags & D3D10_RESOURCE_MISC_TEXTURECUBE)
759 FIXME("Cube map is not supported.\n");
760 return E_FAIL;
762 if (img_info.ArraySize != 1)
764 FIXME("img_info.ArraySize = %u not supported.\n", img_info.ArraySize);
765 return E_NOTIMPL;
768 if (FAILED(hr = WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory)))
769 goto end;
770 if (FAILED(hr = IWICImagingFactory_CreateStream(factory, &stream)))
771 goto end;
772 if (FAILED(hr = IWICStream_InitializeFromMemory(stream, (BYTE *)data, size)))
773 goto end;
774 if (FAILED(hr = IWICImagingFactory_CreateDecoderFromStream(factory, (IStream *)stream, NULL, 0, &decoder)))
775 goto end;
776 if (FAILED(hr = IWICBitmapDecoder_GetFrameCount(decoder, &frame_count)) || !frame_count)
777 goto end;
778 if (FAILED(hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame)))
779 goto end;
780 if (FAILED(hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &src_format)))
781 goto end;
783 width = img_info.Width;
784 height = img_info.Height;
785 if (is_block_compressed(img_info.Format))
787 width = (width + 3) & ~3;
788 height = (height + 3) & ~3;
790 stride = (width * get_bpp_from_format(img_info.Format) + 7) / 8;
791 frame_size = stride * height;
793 if (!(res_data = malloc(sizeof(**resource_data) + frame_size)))
795 hr = E_FAIL;
796 goto end;
798 buffer = res_data + sizeof(**resource_data);
800 if (is_block_compressed(img_info.Format))
802 if (FAILED(hr = IWICBitmapFrameDecode_QueryInterface(frame, &IID_IWICDdsFrameDecode, (void **)&dds_frame)))
803 goto end;
804 if (FAILED(hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, NULL, stride * 4, frame_size, buffer)))
805 goto end;
807 else
809 if (!(dst_format = dxgi_format_to_wic_guid(img_info.Format)))
811 hr = E_FAIL;
812 FIXME("Unsupported DXGI format %#x.\n", img_info.Format);
813 goto end;
816 if (IsEqualGUID(&src_format, dst_format))
818 if (FAILED(hr = IWICBitmapFrameDecode_CopyPixels(frame, NULL, stride, frame_size, buffer)))
819 goto end;
821 else
823 if (FAILED(hr = IWICImagingFactory_CreateFormatConverter(factory, &converter)))
824 goto end;
825 if (FAILED(hr = IWICFormatConverter_CanConvert(converter, &src_format, dst_format, &can_convert)))
826 goto end;
827 if (!can_convert)
829 WARN("Format converting %s to %s is not supported by WIC.\n",
830 debugstr_guid(&src_format), debugstr_guid(dst_format));
831 goto end;
833 if (FAILED(hr = IWICFormatConverter_Initialize(converter, (IWICBitmapSource *)frame, dst_format,
834 WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom)))
835 goto end;
836 if (FAILED(hr = IWICFormatConverter_CopyPixels(converter, NULL, stride, frame_size, buffer)))
837 goto end;
841 load_info->Width = width;
842 load_info->Height = height;
843 load_info->MipLevels = 1;
844 load_info->Format = img_info.Format;
845 load_info->Usage = D3D10_USAGE_DEFAULT;
846 load_info->BindFlags = D3D10_BIND_SHADER_RESOURCE;
847 load_info->MiscFlags = img_info.MiscFlags;
849 *resource_data = (D3D10_SUBRESOURCE_DATA *)res_data;
850 res_data = NULL;
851 (*resource_data)->pSysMem = buffer;
852 (*resource_data)->SysMemPitch = stride;
853 (*resource_data)->SysMemSlicePitch = frame_size;
855 hr = S_OK;
857 end:
858 if (converter)
859 IWICFormatConverter_Release(converter);
860 if (dds_frame)
861 IWICDdsFrameDecode_Release(dds_frame);
862 free(res_data);
863 if (frame)
864 IWICBitmapFrameDecode_Release(frame);
865 if (decoder)
866 IWICBitmapDecoder_Release(decoder);
867 if (stream)
868 IWICStream_Release(stream);
869 if (factory)
870 IWICImagingFactory_Release(factory);
871 return hr;
874 HRESULT create_d3d_texture(ID3D10Device *device, D3DX10_IMAGE_LOAD_INFO *load_info,
875 D3D10_SUBRESOURCE_DATA *resource_data, ID3D10Resource **texture)
877 D3D10_TEXTURE2D_DESC texture_2d_desc;
878 ID3D10Texture2D *texture_2d;
879 HRESULT hr;
881 memset(&texture_2d_desc, 0, sizeof(texture_2d_desc));
882 texture_2d_desc.Width = load_info->Width;
883 texture_2d_desc.Height = load_info->Height;
884 texture_2d_desc.MipLevels = load_info->MipLevels;
885 texture_2d_desc.ArraySize = 1;
886 texture_2d_desc.Format = load_info->Format;
887 texture_2d_desc.SampleDesc.Count = 1;
888 texture_2d_desc.Usage = load_info->Usage;
889 texture_2d_desc.BindFlags = load_info->BindFlags;
890 texture_2d_desc.MiscFlags = load_info->MiscFlags;
892 if (FAILED(hr = ID3D10Device_CreateTexture2D(device, &texture_2d_desc, resource_data, &texture_2d)))
893 return hr;
895 *texture = (ID3D10Resource *)texture_2d;
896 return S_OK;
899 HRESULT WINAPI D3DX10CreateTextureFromMemory(ID3D10Device *device, const void *src_data, SIZE_T src_data_size,
900 D3DX10_IMAGE_LOAD_INFO *load_info, ID3DX10ThreadPump *pump, ID3D10Resource **texture, HRESULT *hresult)
902 HRESULT hr;
904 TRACE("device %p, src_data %p, src_data_size %Iu, load_info %p, pump %p, texture %p, hresult %p.\n",
905 device, src_data, src_data_size, load_info, pump, texture, hresult);
907 if (!device)
908 return E_INVALIDARG;
909 if (!src_data)
910 return E_FAIL;
911 if (pump)
912 FIXME("Thread pump is not supported yet.\n");
914 hr = create_texture(device, src_data, src_data_size, load_info, texture);
915 if (hresult)
916 *hresult = hr;
917 return hr;