From: Ziqing Hui Subject: [PATCH 1/3] d3dx10: Implement D3DX10CreateTextureFromMemory initially. Message-Id: Date: Fri, 18 Jun 2021 14:29:01 +0800 Signed-off-by: Ziqing Hui --- dlls/d3dx10_43/d3dx10_43_main.c | 11 -- dlls/d3dx10_43/tests/d3dx10.c | 7 +- dlls/d3dx10_43/texture.c | 233 ++++++++++++++++++++++++++++++++ 3 files changed, 236 insertions(+), 15 deletions(-) diff --git a/dlls/d3dx10_43/d3dx10_43_main.c b/dlls/d3dx10_43/d3dx10_43_main.c index 181cf38687d..06b00cb0393 100644 --- a/dlls/d3dx10_43/d3dx10_43_main.c +++ b/dlls/d3dx10_43/d3dx10_43_main.c @@ -187,17 +187,6 @@ HRESULT WINAPI D3DX10CreateDeviceAndSwapChain(IDXGIAdapter *adapter, D3D10_DRIVE D3D10_1_SDK_VERSION, desc, swapchain, (ID3D10Device1 **)device); } -HRESULT WINAPI D3DX10CreateTextureFromMemory(ID3D10Device *device, const void *src_data, - SIZE_T src_data_size, D3DX10_IMAGE_LOAD_INFO *loadinfo, ID3DX10ThreadPump *pump, - ID3D10Resource **texture, HRESULT *hresult) -{ - FIXME("device %p, src_data %p, src_data_size %lu, loadinfo %p, pump %p, texture %p, " - "hresult %p, stub!\n", - device, src_data, src_data_size, loadinfo, pump, texture, hresult); - - return E_NOTIMPL; -} - HRESULT WINAPI D3DX10FilterTexture(ID3D10Resource *texture, UINT src_level, UINT filter) { FIXME("texture %p, src_level %u, filter %#x stub!\n", texture, src_level, filter); diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c index 47f6e337f2e..211b0fce5ba 100644 --- a/dlls/d3dx10_43/tests/d3dx10.c +++ b/dlls/d3dx10_43/tests/d3dx10.c @@ -1040,6 +1040,7 @@ 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 != 1) ok_(__FILE__, line)(desc_2d.MipLevels == expected_mip_levels, "Got unexpected MipLevels %u, expected %u.\n", desc_2d.MipLevels, expected_mip_levels); @@ -1146,6 +1147,7 @@ static void check_resource_data(ID3D10Resource *resource, const struct test_imag { line_match = !memcmp(image->expected_data + stride * i, (BYTE *)map.pData + map.RowPitch * i, stride); + todo_wine ok_(__FILE__, line)(line_match, "Data mismatch for line %u.\n", i); if (!line_match) break; @@ -1971,8 +1973,6 @@ static void test_create_texture(void) /* D3DX10CreateTextureFromMemory tests */ - todo_wine - { hr = D3DX10CreateTextureFromMemory(device, NULL, 0, NULL, NULL, &resource, NULL); ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr); hr = D3DX10CreateTextureFromMemory(device, NULL, sizeof(test_bmp_1bpp), NULL, NULL, &resource, NULL); @@ -1981,14 +1981,13 @@ static void test_create_texture(void) ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr); hr = D3DX10CreateTextureFromMemory(device, test_bmp_1bpp, sizeof(test_bmp_1bpp) - 1, NULL, NULL, &resource, NULL); ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr); - } for (i = 0; i < ARRAY_SIZE(test_image); ++i) { winetest_push_context("Test %u", i); hr = D3DX10CreateTextureFromMemory(device, test_image[i].data, test_image[i].size, NULL, NULL, &resource, NULL); - todo_wine + todo_wine_if(test_image[i].expected_info.Format != DXGI_FORMAT_R8G8B8A8_UNORM) ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); if (hr == S_OK) { diff --git a/dlls/d3dx10_43/texture.c b/dlls/d3dx10_43/texture.c index ea9b5120c47..be5461d5421 100644 --- a/dlls/d3dx10_43/texture.c +++ b/dlls/d3dx10_43/texture.c @@ -85,6 +85,140 @@ static D3D10_RESOURCE_DIMENSION wic_dimension_to_d3dx10_dimension(WICDdsDimensio } } +static unsigned int get_bpp_from_format(DXGI_FORMAT format) +{ + switch (format) + { + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + case DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT_R32G32B32A32_UINT: + case DXGI_FORMAT_R32G32B32A32_SINT: + return 128; + case DXGI_FORMAT_R32G32B32_TYPELESS: + case DXGI_FORMAT_R32G32B32_FLOAT: + case DXGI_FORMAT_R32G32B32_UINT: + case DXGI_FORMAT_R32G32B32_SINT: + return 96; + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + case DXGI_FORMAT_R16G16B16A16_FLOAT: + case DXGI_FORMAT_R16G16B16A16_UNORM: + case DXGI_FORMAT_R16G16B16A16_UINT: + case DXGI_FORMAT_R16G16B16A16_SNORM: + case DXGI_FORMAT_R16G16B16A16_SINT: + case DXGI_FORMAT_R32G32_TYPELESS: + case DXGI_FORMAT_R32G32_FLOAT: + case DXGI_FORMAT_R32G32_UINT: + case DXGI_FORMAT_R32G32_SINT: + case DXGI_FORMAT_R32G8X24_TYPELESS: + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + case DXGI_FORMAT_Y416: + case DXGI_FORMAT_Y210: + case DXGI_FORMAT_Y216: + return 64; + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + case DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT_R10G10B10A2_UINT: + case DXGI_FORMAT_R11G11B10_FLOAT: + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_R8G8B8A8_UINT: + case DXGI_FORMAT_R8G8B8A8_SNORM: + case DXGI_FORMAT_R8G8B8A8_SINT: + case DXGI_FORMAT_R16G16_TYPELESS: + case DXGI_FORMAT_R16G16_FLOAT: + case DXGI_FORMAT_R16G16_UNORM: + case DXGI_FORMAT_R16G16_UINT: + case DXGI_FORMAT_R16G16_SNORM: + case DXGI_FORMAT_R16G16_SINT: + case DXGI_FORMAT_R32_TYPELESS: + case DXGI_FORMAT_D32_FLOAT: + case DXGI_FORMAT_R32_FLOAT: + case DXGI_FORMAT_R32_UINT: + case DXGI_FORMAT_R32_SINT: + case DXGI_FORMAT_R24G8_TYPELESS: + case DXGI_FORMAT_D24_UNORM_S8_UINT: + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + case DXGI_FORMAT_R8G8_B8G8_UNORM: + case DXGI_FORMAT_G8R8_G8B8_UNORM: + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8X8_UNORM: + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + case DXGI_FORMAT_AYUV: + case DXGI_FORMAT_Y410: + case DXGI_FORMAT_YUY2: + return 32; + case DXGI_FORMAT_P010: + case DXGI_FORMAT_P016: + return 24; + case DXGI_FORMAT_R8G8_TYPELESS: + case DXGI_FORMAT_R8G8_UNORM: + case DXGI_FORMAT_R8G8_UINT: + case DXGI_FORMAT_R8G8_SNORM: + case DXGI_FORMAT_R8G8_SINT: + case DXGI_FORMAT_R16_TYPELESS: + case DXGI_FORMAT_R16_FLOAT: + case DXGI_FORMAT_D16_UNORM: + case DXGI_FORMAT_R16_UNORM: + case DXGI_FORMAT_R16_UINT: + case DXGI_FORMAT_R16_SNORM: + case DXGI_FORMAT_R16_SINT: + case DXGI_FORMAT_B5G6R5_UNORM: + case DXGI_FORMAT_B5G5R5A1_UNORM: + case DXGI_FORMAT_A8P8: + case DXGI_FORMAT_B4G4R4A4_UNORM: + return 16; + case DXGI_FORMAT_NV12: + case DXGI_FORMAT_420_OPAQUE: + case DXGI_FORMAT_NV11: + return 12; + case DXGI_FORMAT_R8_TYPELESS: + case DXGI_FORMAT_R8_UNORM: + case DXGI_FORMAT_R8_UINT: + case DXGI_FORMAT_R8_SNORM: + case DXGI_FORMAT_R8_SINT: + case DXGI_FORMAT_A8_UNORM: + case DXGI_FORMAT_AI44: + case DXGI_FORMAT_IA44: + case DXGI_FORMAT_P8: + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC5_SNORM: + case DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC6H_SF16: + case DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + return 8; + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC4_SNORM: + return 4; + case DXGI_FORMAT_R1_UNORM: + return 1; + default: + return 0; + } +} + static DXGI_FORMAT get_d3dx10_dds_format(DXGI_FORMAT format) { unsigned int i; @@ -377,3 +511,102 @@ end: } return S_OK; } + +HRESULT WINAPI D3DX10CreateTextureFromMemory(ID3D10Device *device, const void *src_data, SIZE_T src_data_size, + D3DX10_IMAGE_LOAD_INFO *load_info, ID3DX10ThreadPump *pump, ID3D10Resource **texture, HRESULT *hresult) +{ + unsigned int frame_count, width, height, stride, frame_size; + D3D10_TEXTURE2D_DESC texture_2d_desc; + IWICBitmapFrameDecode *frame = NULL; + IWICImagingFactory *factory = NULL; + IWICBitmapDecoder *decoder = NULL; + ID3D10Texture2D *texture_2d; + D3DX10_IMAGE_INFO img_info; + IWICStream *stream = NULL; + BYTE *buffer = NULL; + HRESULT hr; + + TRACE("device %p, src_data %p, src_data_size %lu, load_info %p, pump %p, texture %p, hresult %p.\n", + device, src_data, src_data_size, load_info, pump, texture, hresult); + + if (!src_data || !src_data_size || !texture) + return E_FAIL; + if (load_info) + FIXME("load_info is ignored.\n"); + if (pump) + FIXME("Thread pump is not supported yet.\n"); + + hr = D3DX10GetImageInfoFromMemory(src_data, src_data_size, NULL, &img_info, NULL); + if (FAILED(hr)) + return E_FAIL; + if (img_info.Format != DXGI_FORMAT_R8G8B8A8_UNORM) + { + FIXME("Unsupported format %#x.\n", img_info.Format); + return E_FAIL; + } + + WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory); + IWICImagingFactory_CreateStream(factory, &stream); + hr = IWICStream_InitializeFromMemory(stream, (BYTE *)src_data, src_data_size); + if (FAILED(hr)) + goto end; + hr = IWICImagingFactory_CreateDecoderFromStream(factory, (IStream *)stream, NULL, 0, &decoder); + if (FAILED(hr)) + goto end; + hr = IWICBitmapDecoder_GetFrameCount(decoder, &frame_count); + if (FAILED(hr) || !frame_count) + goto end; + hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame); + if (FAILED(hr)) + goto end; + + width = img_info.Width; + height = img_info.Height; + stride = (width * get_bpp_from_format(img_info.Format) + 7) / 8; + frame_size = stride * height; + + buffer = heap_alloc(frame_size); + if (!buffer) + { + hr = E_FAIL; + goto end; + } + + hr = IWICBitmapFrameDecode_CopyPixels(frame, NULL, stride, frame_size, buffer); + if (FAILED(hr)) + goto end; + + memset(&texture_2d_desc, 0, sizeof(texture_2d_desc)); + texture_2d_desc.Width = width; + texture_2d_desc.Height = height; + texture_2d_desc.MipLevels = 1; + texture_2d_desc.ArraySize = img_info.ArraySize; + texture_2d_desc.Format = img_info.Format; + texture_2d_desc.SampleDesc.Count = 1; + texture_2d_desc.Usage = D3D10_USAGE_DEFAULT; + texture_2d_desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + texture_2d_desc.MiscFlags = img_info.MiscFlags; + + hr = ID3D10Device_CreateTexture2D(device, &texture_2d_desc, NULL, &texture_2d); + if (FAILED(hr)) + goto end; + ID3D10Device_UpdateSubresource(device, (ID3D10Resource *)texture_2d, 0, NULL, buffer, stride, frame_size); + + *texture = (ID3D10Resource *)texture_2d; + +end: + if (buffer) + heap_free(buffer); + if (frame) + IWICBitmapFrameDecode_Release(frame); + if (decoder) + IWICBitmapDecoder_Release(decoder); + if (stream) + IWICStream_Release(stream); + if (factory) + IWICImagingFactory_Release(factory); + + if (hr != S_OK) + return E_FAIL; + return S_OK; +}