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"
20 #include "wine/heap.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(d3dx
);
30 HRESULT WINAPI
WICCreateImagingFactory_Proxy(UINT sdk_version
, IWICImagingFactory
**imaging_factory
);
34 const GUID
*wic_container_guid
;
35 D3DX10_IMAGE_FILE_FORMAT d3dx_file_format
;
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 DXGI_FORMAT to_be_converted_format
[] =
52 DXGI_FORMAT_R8G8_UNORM
,
53 DXGI_FORMAT_B5G6R5_UNORM
,
54 DXGI_FORMAT_B4G4R4A4_UNORM
,
55 DXGI_FORMAT_B5G5R5A1_UNORM
,
56 DXGI_FORMAT_B8G8R8X8_UNORM
,
57 DXGI_FORMAT_B8G8R8A8_UNORM
60 static D3DX10_IMAGE_FILE_FORMAT
wic_container_guid_to_file_format(GUID
*container_format
)
64 for (i
= 0; i
< ARRAY_SIZE(file_formats
); ++i
)
66 if (IsEqualGUID(file_formats
[i
].wic_container_guid
, container_format
))
67 return file_formats
[i
].d3dx_file_format
;
69 return D3DX10_IFF_FORCE_DWORD
;
72 static D3D10_RESOURCE_DIMENSION
wic_dimension_to_d3dx10_dimension(WICDdsDimension wic_dimension
)
74 switch (wic_dimension
)
77 return D3D10_RESOURCE_DIMENSION_TEXTURE1D
;
79 case WICDdsTextureCube
:
80 return D3D10_RESOURCE_DIMENSION_TEXTURE2D
;
82 return D3D10_RESOURCE_DIMENSION_TEXTURE3D
;
84 return D3D10_RESOURCE_DIMENSION_UNKNOWN
;
88 static unsigned int get_bpp_from_format(DXGI_FORMAT format
)
92 case DXGI_FORMAT_R32G32B32A32_TYPELESS
:
93 case DXGI_FORMAT_R32G32B32A32_FLOAT
:
94 case DXGI_FORMAT_R32G32B32A32_UINT
:
95 case DXGI_FORMAT_R32G32B32A32_SINT
:
97 case DXGI_FORMAT_R32G32B32_TYPELESS
:
98 case DXGI_FORMAT_R32G32B32_FLOAT
:
99 case DXGI_FORMAT_R32G32B32_UINT
:
100 case DXGI_FORMAT_R32G32B32_SINT
:
102 case DXGI_FORMAT_R16G16B16A16_TYPELESS
:
103 case DXGI_FORMAT_R16G16B16A16_FLOAT
:
104 case DXGI_FORMAT_R16G16B16A16_UNORM
:
105 case DXGI_FORMAT_R16G16B16A16_UINT
:
106 case DXGI_FORMAT_R16G16B16A16_SNORM
:
107 case DXGI_FORMAT_R16G16B16A16_SINT
:
108 case DXGI_FORMAT_R32G32_TYPELESS
:
109 case DXGI_FORMAT_R32G32_FLOAT
:
110 case DXGI_FORMAT_R32G32_UINT
:
111 case DXGI_FORMAT_R32G32_SINT
:
112 case DXGI_FORMAT_R32G8X24_TYPELESS
:
113 case DXGI_FORMAT_D32_FLOAT_S8X24_UINT
:
114 case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS
:
115 case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT
:
116 case DXGI_FORMAT_Y416
:
117 case DXGI_FORMAT_Y210
:
118 case DXGI_FORMAT_Y216
:
120 case DXGI_FORMAT_R10G10B10A2_TYPELESS
:
121 case DXGI_FORMAT_R10G10B10A2_UNORM
:
122 case DXGI_FORMAT_R10G10B10A2_UINT
:
123 case DXGI_FORMAT_R11G11B10_FLOAT
:
124 case DXGI_FORMAT_R8G8B8A8_TYPELESS
:
125 case DXGI_FORMAT_R8G8B8A8_UNORM
:
126 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
:
127 case DXGI_FORMAT_R8G8B8A8_UINT
:
128 case DXGI_FORMAT_R8G8B8A8_SNORM
:
129 case DXGI_FORMAT_R8G8B8A8_SINT
:
130 case DXGI_FORMAT_R16G16_TYPELESS
:
131 case DXGI_FORMAT_R16G16_FLOAT
:
132 case DXGI_FORMAT_R16G16_UNORM
:
133 case DXGI_FORMAT_R16G16_UINT
:
134 case DXGI_FORMAT_R16G16_SNORM
:
135 case DXGI_FORMAT_R16G16_SINT
:
136 case DXGI_FORMAT_R32_TYPELESS
:
137 case DXGI_FORMAT_D32_FLOAT
:
138 case DXGI_FORMAT_R32_FLOAT
:
139 case DXGI_FORMAT_R32_UINT
:
140 case DXGI_FORMAT_R32_SINT
:
141 case DXGI_FORMAT_R24G8_TYPELESS
:
142 case DXGI_FORMAT_D24_UNORM_S8_UINT
:
143 case DXGI_FORMAT_R24_UNORM_X8_TYPELESS
:
144 case DXGI_FORMAT_X24_TYPELESS_G8_UINT
:
145 case DXGI_FORMAT_R9G9B9E5_SHAREDEXP
:
146 case DXGI_FORMAT_R8G8_B8G8_UNORM
:
147 case DXGI_FORMAT_G8R8_G8B8_UNORM
:
148 case DXGI_FORMAT_B8G8R8A8_UNORM
:
149 case DXGI_FORMAT_B8G8R8X8_UNORM
:
150 case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM
:
151 case DXGI_FORMAT_B8G8R8A8_TYPELESS
:
152 case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
:
153 case DXGI_FORMAT_B8G8R8X8_TYPELESS
:
154 case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB
:
155 case DXGI_FORMAT_AYUV
:
156 case DXGI_FORMAT_Y410
:
157 case DXGI_FORMAT_YUY2
:
159 case DXGI_FORMAT_P010
:
160 case DXGI_FORMAT_P016
:
162 case DXGI_FORMAT_R8G8_TYPELESS
:
163 case DXGI_FORMAT_R8G8_UNORM
:
164 case DXGI_FORMAT_R8G8_UINT
:
165 case DXGI_FORMAT_R8G8_SNORM
:
166 case DXGI_FORMAT_R8G8_SINT
:
167 case DXGI_FORMAT_R16_TYPELESS
:
168 case DXGI_FORMAT_R16_FLOAT
:
169 case DXGI_FORMAT_D16_UNORM
:
170 case DXGI_FORMAT_R16_UNORM
:
171 case DXGI_FORMAT_R16_UINT
:
172 case DXGI_FORMAT_R16_SNORM
:
173 case DXGI_FORMAT_R16_SINT
:
174 case DXGI_FORMAT_B5G6R5_UNORM
:
175 case DXGI_FORMAT_B5G5R5A1_UNORM
:
176 case DXGI_FORMAT_A8P8
:
177 case DXGI_FORMAT_B4G4R4A4_UNORM
:
179 case DXGI_FORMAT_NV12
:
180 case DXGI_FORMAT_420_OPAQUE
:
181 case DXGI_FORMAT_NV11
:
183 case DXGI_FORMAT_R8_TYPELESS
:
184 case DXGI_FORMAT_R8_UNORM
:
185 case DXGI_FORMAT_R8_UINT
:
186 case DXGI_FORMAT_R8_SNORM
:
187 case DXGI_FORMAT_R8_SINT
:
188 case DXGI_FORMAT_A8_UNORM
:
189 case DXGI_FORMAT_AI44
:
190 case DXGI_FORMAT_IA44
:
192 case DXGI_FORMAT_BC2_TYPELESS
:
193 case DXGI_FORMAT_BC2_UNORM
:
194 case DXGI_FORMAT_BC2_UNORM_SRGB
:
195 case DXGI_FORMAT_BC3_TYPELESS
:
196 case DXGI_FORMAT_BC3_UNORM
:
197 case DXGI_FORMAT_BC3_UNORM_SRGB
:
198 case DXGI_FORMAT_BC5_TYPELESS
:
199 case DXGI_FORMAT_BC5_UNORM
:
200 case DXGI_FORMAT_BC5_SNORM
:
201 case DXGI_FORMAT_BC6H_TYPELESS
:
202 case DXGI_FORMAT_BC6H_UF16
:
203 case DXGI_FORMAT_BC6H_SF16
:
204 case DXGI_FORMAT_BC7_TYPELESS
:
205 case DXGI_FORMAT_BC7_UNORM
:
206 case DXGI_FORMAT_BC7_UNORM_SRGB
:
208 case DXGI_FORMAT_BC1_TYPELESS
:
209 case DXGI_FORMAT_BC1_UNORM
:
210 case DXGI_FORMAT_BC1_UNORM_SRGB
:
211 case DXGI_FORMAT_BC4_TYPELESS
:
212 case DXGI_FORMAT_BC4_UNORM
:
213 case DXGI_FORMAT_BC4_SNORM
:
215 case DXGI_FORMAT_R1_UNORM
:
222 static DXGI_FORMAT
get_d3dx10_dds_format(DXGI_FORMAT format
)
226 for (i
= 0; i
< ARRAY_SIZE(to_be_converted_format
); ++i
)
228 if (format
== to_be_converted_format
[i
])
229 return DXGI_FORMAT_R8G8B8A8_UNORM
;
234 static HRESULT
load_file(const WCHAR
*filename
, void **buffer
, DWORD
*size
)
241 file
= CreateFileW(filename
, GENERIC_READ
, FILE_SHARE_READ
, 0, OPEN_EXISTING
, 0, 0);
242 if (file
== INVALID_HANDLE_VALUE
)
244 hr
= HRESULT_FROM_WIN32(GetLastError());
248 *size
= GetFileSize(file
, NULL
);
249 if (*size
== INVALID_FILE_SIZE
)
251 hr
= HRESULT_FROM_WIN32(GetLastError());
255 *buffer
= heap_alloc(*size
);
262 ret
= ReadFile(file
, *buffer
, *size
, &bytes_read
, NULL
);
265 hr
= HRESULT_FROM_WIN32(GetLastError());
268 if (bytes_read
!= *size
)
280 if (file
!= INVALID_HANDLE_VALUE
)
285 static HRESULT
load_resource(HMODULE module
, HRSRC res_info
, void **buffer
, DWORD
*size
)
289 if (!(*size
= SizeofResource(module
, res_info
)))
290 return HRESULT_FROM_WIN32(GetLastError());
292 if (!(resource
= LoadResource(module
, res_info
)))
293 return HRESULT_FROM_WIN32(GetLastError());
295 if (!(*buffer
= LockResource(resource
)))
296 return HRESULT_FROM_WIN32(GetLastError());
301 HRESULT WINAPI
D3DX10GetImageInfoFromFileA(const char *src_file
, ID3DX10ThreadPump
*pump
, D3DX10_IMAGE_INFO
*info
,
308 TRACE("src_file %s, pump %p, info %p, result %p.\n", debugstr_a(src_file
), pump
, info
, result
);
310 if (!src_file
|| !info
)
313 str_len
= MultiByteToWideChar(CP_ACP
, 0, src_file
, -1, NULL
, 0);
315 return HRESULT_FROM_WIN32(GetLastError());
317 buffer
= heap_alloc(str_len
* sizeof(*buffer
));
319 return E_OUTOFMEMORY
;
321 MultiByteToWideChar(CP_ACP
, 0, src_file
, -1, buffer
, str_len
);
322 hr
= D3DX10GetImageInfoFromFileW(buffer
, pump
, info
, result
);
329 HRESULT WINAPI
D3DX10GetImageInfoFromFileW(const WCHAR
*src_file
, ID3DX10ThreadPump
*pump
, D3DX10_IMAGE_INFO
*info
,
336 TRACE("src_file %s, pump %p, info %p, result %p.\n", debugstr_w(src_file
), pump
, info
, result
);
338 if (!src_file
|| !info
)
341 if (FAILED(load_file(src_file
, &buffer
, &size
)))
342 return D3D10_ERROR_FILE_NOT_FOUND
;
344 hr
= D3DX10GetImageInfoFromMemory(buffer
, size
, pump
, info
, result
);
351 HRESULT WINAPI
D3DX10GetImageInfoFromResourceA(HMODULE module
, const char *resource
, ID3DX10ThreadPump
*pump
,
352 D3DX10_IMAGE_INFO
*info
, HRESULT
*result
)
359 TRACE("module %p, resource %s, pump %p, info %p, result %p.\n",
360 module
, debugstr_a(resource
), pump
, info
, result
);
362 if (!resource
|| !info
)
363 return D3DX10_ERR_INVALID_DATA
;
365 res_info
= FindResourceA(module
, resource
, (const char *)RT_RCDATA
);
368 /* Try loading the resource as bitmap data */
369 res_info
= FindResourceA(module
, resource
, (const char *)RT_BITMAP
);
371 return D3DX10_ERR_INVALID_DATA
;
374 hr
= load_resource(module
, res_info
, &buffer
, &size
);
376 return D3DX10_ERR_INVALID_DATA
;
378 return D3DX10GetImageInfoFromMemory(buffer
, size
, pump
, info
, result
);
381 HRESULT WINAPI
D3DX10GetImageInfoFromResourceW(HMODULE module
, const WCHAR
*resource
, ID3DX10ThreadPump
*pump
,
382 D3DX10_IMAGE_INFO
*info
, HRESULT
*result
)
389 TRACE("module %p, resource %s, pump %p, info %p, result %p.\n",
390 module
, debugstr_w(resource
), pump
, info
, result
);
392 if (!resource
|| !info
)
393 return D3DX10_ERR_INVALID_DATA
;
395 res_info
= FindResourceW(module
, resource
, (const WCHAR
*)RT_RCDATA
);
398 /* Try loading the resource as bitmap data */
399 res_info
= FindResourceW(module
, resource
, (const WCHAR
*)RT_BITMAP
);
401 return D3DX10_ERR_INVALID_DATA
;
404 hr
= load_resource(module
, res_info
, &buffer
, &size
);
406 return D3DX10_ERR_INVALID_DATA
;
408 return D3DX10GetImageInfoFromMemory(buffer
, size
, pump
, info
, result
);
411 HRESULT WINAPI
D3DX10GetImageInfoFromMemory(const void *src_data
, SIZE_T src_data_size
, ID3DX10ThreadPump
*pump
,
412 D3DX10_IMAGE_INFO
*img_info
, HRESULT
*hresult
)
414 IWICBitmapFrameDecode
*frame
= NULL
;
415 IWICImagingFactory
*factory
= NULL
;
416 IWICDdsDecoder
*dds_decoder
= NULL
;
417 IWICBitmapDecoder
*decoder
= NULL
;
418 WICDdsParameters dds_params
;
419 IWICStream
*stream
= NULL
;
420 unsigned int frame_count
;
421 GUID container_format
;
424 TRACE("src_data %p, src_data_size %lu, pump %p, img_info %p, hresult %p.\n",
425 src_data
, src_data_size
, pump
, img_info
, hresult
);
427 if (!src_data
|| !src_data_size
|| !img_info
)
430 FIXME("Thread pump is not supported yet.\n");
432 WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION
, &factory
);
433 IWICImagingFactory_CreateStream(factory
, &stream
);
434 hr
= IWICStream_InitializeFromMemory(stream
, (BYTE
*)src_data
, src_data_size
);
437 WARN("Failed to initialize stream.\n");
440 hr
= IWICImagingFactory_CreateDecoderFromStream(factory
, (IStream
*)stream
, NULL
, 0, &decoder
);
444 hr
= IWICBitmapDecoder_GetContainerFormat(decoder
, &container_format
);
447 img_info
->ImageFileFormat
= wic_container_guid_to_file_format(&container_format
);
448 if (img_info
->ImageFileFormat
== D3DX10_IFF_FORCE_DWORD
)
451 WARN("Unsupported image file format %s.\n", debugstr_guid(&container_format
));
455 hr
= IWICBitmapDecoder_GetFrameCount(decoder
, &frame_count
);
456 if (FAILED(hr
) || !frame_count
)
458 hr
= IWICBitmapDecoder_GetFrame(decoder
, 0, &frame
);
461 hr
= IWICBitmapFrameDecode_GetSize(frame
, &img_info
->Width
, &img_info
->Height
);
465 if (img_info
->ImageFileFormat
== D3DX10_IFF_DDS
)
467 hr
= IWICBitmapDecoder_QueryInterface(decoder
, &IID_IWICDdsDecoder
, (void **)&dds_decoder
);
470 hr
= IWICDdsDecoder_GetParameters(dds_decoder
, &dds_params
);
473 img_info
->ArraySize
= dds_params
.ArraySize
;
474 img_info
->Depth
= dds_params
.Depth
;
475 img_info
->MipLevels
= dds_params
.MipLevels
;
476 img_info
->ResourceDimension
= wic_dimension_to_d3dx10_dimension(dds_params
.Dimension
);
477 img_info
->Format
= get_d3dx10_dds_format(dds_params
.DxgiFormat
);
478 img_info
->MiscFlags
= 0;
479 if (dds_params
.Dimension
== WICDdsTextureCube
)
481 img_info
->MiscFlags
= D3D10_RESOURCE_MISC_TEXTURECUBE
;
482 img_info
->ArraySize
*= 6;
487 img_info
->ArraySize
= 1;
489 img_info
->MipLevels
= 1;
490 img_info
->ResourceDimension
= D3D10_RESOURCE_DIMENSION_TEXTURE2D
;
491 img_info
->Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
492 img_info
->MiscFlags
= 0;
497 IWICDdsDecoder_Release(dds_decoder
);
499 IWICBitmapFrameDecode_Release(frame
);
501 IWICBitmapDecoder_Release(decoder
);
503 IWICStream_Release(stream
);
505 IWICImagingFactory_Release(factory
);
509 WARN("Invalid or unsupported image file.\n");
515 HRESULT WINAPI
D3DX10CreateTextureFromMemory(ID3D10Device
*device
, const void *src_data
, SIZE_T src_data_size
,
516 D3DX10_IMAGE_LOAD_INFO
*load_info
, ID3DX10ThreadPump
*pump
, ID3D10Resource
**texture
, HRESULT
*hresult
)
518 unsigned int frame_count
, width
, height
, stride
, frame_size
;
519 D3D10_TEXTURE2D_DESC texture_2d_desc
;
520 D3D10_SUBRESOURCE_DATA resource_data
;
521 IWICBitmapFrameDecode
*frame
= NULL
;
522 IWICImagingFactory
*factory
= NULL
;
523 IWICBitmapDecoder
*decoder
= NULL
;
524 ID3D10Texture2D
*texture_2d
;
525 D3DX10_IMAGE_INFO img_info
;
526 IWICStream
*stream
= NULL
;
530 TRACE("device %p, src_data %p, src_data_size %lu, load_info %p, pump %p, texture %p, hresult %p.\n",
531 device
, src_data
, src_data_size
, load_info
, pump
, texture
, hresult
);
533 if (!src_data
|| !src_data_size
|| !texture
)
536 FIXME("load_info is ignored.\n");
538 FIXME("Thread pump is not supported yet.\n");
540 if (FAILED(D3DX10GetImageInfoFromMemory(src_data
, src_data_size
, NULL
, &img_info
, NULL
)))
542 if (img_info
.Format
!= DXGI_FORMAT_R8G8B8A8_UNORM
)
544 FIXME("Unsupported format %#x.\n", img_info
.Format
);
548 if (FAILED(hr
= WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION
, &factory
)))
550 if (FAILED(hr
= IWICImagingFactory_CreateStream(factory
, &stream
)))
552 if (FAILED(hr
= IWICStream_InitializeFromMemory(stream
, (BYTE
*)src_data
, src_data_size
)))
554 if (FAILED(hr
= IWICImagingFactory_CreateDecoderFromStream(factory
, (IStream
*)stream
, NULL
, 0, &decoder
)))
556 if (FAILED(hr
= IWICBitmapDecoder_GetFrameCount(decoder
, &frame_count
)) || !frame_count
)
558 if (FAILED(hr
= IWICBitmapDecoder_GetFrame(decoder
, 0, &frame
)))
561 width
= img_info
.Width
;
562 height
= img_info
.Height
;
563 stride
= (width
* get_bpp_from_format(img_info
.Format
) + 7) / 8;
564 frame_size
= stride
* height
;
566 if (!(buffer
= heap_alloc(frame_size
)))
571 if (FAILED(hr
= IWICBitmapFrameDecode_CopyPixels(frame
, NULL
, stride
, frame_size
, buffer
)))
574 memset(&texture_2d_desc
, 0, sizeof(texture_2d_desc
));
575 texture_2d_desc
.Width
= width
;
576 texture_2d_desc
.Height
= height
;
577 texture_2d_desc
.MipLevels
= 1;
578 texture_2d_desc
.ArraySize
= img_info
.ArraySize
;
579 texture_2d_desc
.Format
= img_info
.Format
;
580 texture_2d_desc
.SampleDesc
.Count
= 1;
581 texture_2d_desc
.Usage
= D3D10_USAGE_DEFAULT
;
582 texture_2d_desc
.BindFlags
= D3D10_BIND_SHADER_RESOURCE
;
583 texture_2d_desc
.MiscFlags
= img_info
.MiscFlags
;
585 resource_data
.pSysMem
= buffer
;
586 resource_data
.SysMemPitch
= stride
;
587 resource_data
.SysMemSlicePitch
= frame_size
;
589 if (FAILED(hr
= ID3D10Device_CreateTexture2D(device
, &texture_2d_desc
, &resource_data
, &texture_2d
)))
592 *texture
= (ID3D10Resource
*)texture_2d
;
599 IWICBitmapFrameDecode_Release(frame
);
601 IWICBitmapDecoder_Release(decoder
);
603 IWICStream_Release(stream
);
605 IWICImagingFactory_Release(factory
);