2 * Copyright (C) 2009-2010 Tony Wasserka
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
20 #include "wine/debug.h"
21 #include "wine/unicode.h"
22 #include "d3dx9_36_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(d3dx
);
30 /* Wine-specific WIC GUIDs */
32 DEFINE_GUID(GUID_WineContainerFormatTga
, 0x0c44fda1,0xa5c5,0x4298,0x96,0x85,0x47,0x3f,0xc1,0x7c,0xd3,0x22);
34 /************************************************************
35 * D3DXGetImageInfoFromFileInMemory
37 * Fills a D3DXIMAGE_INFO structure with info about an image
40 * data [I] pointer to the image file data
41 * datasize [I] size of the passed data
42 * info [O] pointer to the destination structure
45 * Success: D3D_OK, if info is not NULL and data and datasize make up a valid image file or
46 * if info is NULL and data and datasize are not NULL
47 * Failure: D3DXERR_INVALIDDATA, if data is no valid image file and datasize and info are not NULL
48 * D3DERR_INVALIDCALL, if data is NULL or
52 * datasize may be bigger than the actual file size
55 HRESULT WINAPI
D3DXGetImageInfoFromFileInMemory(LPCVOID data
, UINT datasize
, D3DXIMAGE_INFO
*info
)
57 IWICImagingFactory
*factory
;
58 IWICBitmapDecoder
*decoder
= NULL
;
65 FIXME("(%p, %d, %p): partially implemented\n", data
, datasize
, info
);
67 /* TODO: Add support for (or at least detect) TGA, DDS, PPM and DIB */
69 if (!data
|| !datasize
)
70 return D3DERR_INVALIDCALL
;
75 initresult
= CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
77 hr
= CoCreateInstance(&CLSID_WICImagingFactory
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IWICImagingFactory
, (void**)&factory
);
80 IWICImagingFactory_CreateStream(factory
, &stream
);
81 IWICStream_InitializeFromMemory(stream
, (BYTE
*)data
, datasize
);
82 hr
= IWICImagingFactory_CreateDecoderFromStream(factory
, (IStream
*)stream
, NULL
, 0, &decoder
);
83 IStream_Release(stream
);
84 IWICImagingFactory_Release(factory
);
88 GUID container_format
;
91 hr
= IWICBitmapDecoder_GetContainerFormat(decoder
, &container_format
);
93 if (IsEqualGUID(&container_format
, &GUID_ContainerFormatBmp
)) {
94 TRACE("File type is BMP\n");
95 info
->ImageFileFormat
= D3DXIFF_BMP
;
96 } else if (IsEqualGUID(&container_format
, &GUID_ContainerFormatPng
)) {
97 TRACE("File type is PNG\n");
98 info
->ImageFileFormat
= D3DXIFF_PNG
;
99 } else if(IsEqualGUID(&container_format
, &GUID_ContainerFormatJpeg
)) {
100 TRACE("File type is JPG\n");
101 info
->ImageFileFormat
= D3DXIFF_JPG
;
102 } else if(IsEqualGUID(&container_format
, &GUID_WineContainerFormatTga
)) {
103 TRACE("File type is TGA\n");
104 info
->ImageFileFormat
= D3DXIFF_TGA
;
106 WARN("Unsupported image file format %s\n", debugstr_guid(&container_format
));
107 hr
= D3DXERR_INVALIDDATA
;
112 hr
= IWICBitmapDecoder_GetFrameCount(decoder
, &frame_count
);
113 if (SUCCEEDED(hr
) && !frame_count
)
114 hr
= D3DXERR_INVALIDDATA
;
117 IWICBitmapFrameDecode
*frame
= NULL
;
119 hr
= IWICBitmapDecoder_GetFrame(decoder
, 0, &frame
);
122 hr
= IWICBitmapFrameDecode_GetSize(frame
, &info
->Width
, &info
->Height
);
125 WICPixelFormatGUID pixel_format
;
127 hr
= IWICBitmapFrameDecode_GetPixelFormat(frame
, &pixel_format
);
129 if (IsEqualGUID(&pixel_format
, &GUID_WICPixelFormat1bppIndexed
))
130 info
->Format
= D3DFMT_L8
;
131 else if (IsEqualGUID(&pixel_format
, &GUID_WICPixelFormat4bppIndexed
))
132 info
->Format
= D3DFMT_L8
;
133 else if (IsEqualGUID(&pixel_format
, &GUID_WICPixelFormat8bppIndexed
))
134 info
->Format
= D3DFMT_L8
;
135 else if (IsEqualGUID(&pixel_format
, &GUID_WICPixelFormat16bppBGR555
))
136 info
->Format
= D3DFMT_X1R5G5B5
;
137 else if (IsEqualGUID(&pixel_format
, &GUID_WICPixelFormat24bppBGR
))
138 info
->Format
= D3DFMT_R8G8B8
;
139 else if (IsEqualGUID(&pixel_format
, &GUID_WICPixelFormat32bppBGR
))
140 info
->Format
= D3DFMT_X8R8G8B8
;
141 else if (IsEqualGUID(&pixel_format
, &GUID_WICPixelFormat32bppBGRA
))
142 info
->Format
= D3DFMT_A8R8G8B8
;
144 WARN("Unsupported pixel format %s\n", debugstr_guid(&pixel_format
));
145 hr
= D3DXERR_INVALIDDATA
;
151 IWICBitmapFrameDecode_Release(frame
);
155 info
->ResourceType
= D3DRTYPE_TEXTURE
;
160 IWICBitmapDecoder_Release(decoder
);
162 if (SUCCEEDED(initresult
))
166 /* Missing formats are not detected yet and will fail silently without the FIXME */
167 FIXME("Invalid or unsupported image file\n");
168 return D3DXERR_INVALIDDATA
;
174 /************************************************************
175 * D3DXGetImageInfoFromFile
178 * Success: D3D_OK, if we successfully load a valid image file or
179 * if we successfully load a file which is no valid image and info is NULL
180 * Failure: D3DXERR_INVALIDDATA, if we fail to load file or
181 * if file is not a valid image file and info is not NULL
182 * D3DERR_INVALIDCALL, if file is NULL
185 HRESULT WINAPI
D3DXGetImageInfoFromFileA(LPCSTR file
, D3DXIMAGE_INFO
*info
)
191 TRACE("(%s, %p): relay\n", debugstr_a(file
), info
);
193 if( !file
) return D3DERR_INVALIDCALL
;
195 strlength
= MultiByteToWideChar(CP_ACP
, 0, file
, -1, NULL
, 0);
196 widename
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, strlength
* sizeof(WCHAR
));
197 MultiByteToWideChar(CP_ACP
, 0, file
, -1, widename
, strlength
);
199 hr
= D3DXGetImageInfoFromFileW(widename
, info
);
200 HeapFree(GetProcessHeap(), 0, widename
);
205 HRESULT WINAPI
D3DXGetImageInfoFromFileW(LPCWSTR file
, D3DXIMAGE_INFO
*info
)
211 TRACE("(%s, %p): relay\n", debugstr_w(file
), info
);
213 if( !file
) return D3DERR_INVALIDCALL
;
215 hr
= map_view_of_file(file
, &buffer
, &size
);
216 if(FAILED(hr
)) return D3DXERR_INVALIDDATA
;
218 hr
= D3DXGetImageInfoFromFileInMemory(buffer
, size
, info
);
219 UnmapViewOfFile(buffer
);
224 /************************************************************
225 * D3DXGetImageInfoFromResource
228 * Success: D3D_OK, if resource is a valid image file
229 * Failure: D3DXERR_INVALIDDATA, if resource is no valid image file or NULL or
230 * if we fail to load resource
233 HRESULT WINAPI
D3DXGetImageInfoFromResourceA(HMODULE module
, LPCSTR resource
, D3DXIMAGE_INFO
*info
)
237 TRACE("(%p, %s, %p)\n", module
, debugstr_a(resource
), info
);
239 resinfo
= FindResourceA(module
, resource
, (LPCSTR
)RT_RCDATA
);
245 hr
= load_resource_into_memory(module
, resinfo
, &buffer
, &size
);
246 if(FAILED(hr
)) return D3DXERR_INVALIDDATA
;
247 return D3DXGetImageInfoFromFileInMemory(buffer
, size
, info
);
250 resinfo
= FindResourceA(module
, resource
, (LPCSTR
)RT_BITMAP
);
252 FIXME("Implement loading bitmaps from resource type RT_BITMAP\n");
255 return D3DXERR_INVALIDDATA
;
258 HRESULT WINAPI
D3DXGetImageInfoFromResourceW(HMODULE module
, LPCWSTR resource
, D3DXIMAGE_INFO
*info
)
262 TRACE("(%p, %s, %p)\n", module
, debugstr_w(resource
), info
);
264 resinfo
= FindResourceW(module
, resource
, (LPCWSTR
)RT_RCDATA
);
270 hr
= load_resource_into_memory(module
, resinfo
, &buffer
, &size
);
271 if(FAILED(hr
)) return D3DXERR_INVALIDDATA
;
272 return D3DXGetImageInfoFromFileInMemory(buffer
, size
, info
);
275 resinfo
= FindResourceW(module
, resource
, (LPCWSTR
)RT_BITMAP
);
277 FIXME("Implement loading bitmaps from resource type RT_BITMAP\n");
280 return D3DXERR_INVALIDDATA
;
283 /************************************************************
284 * D3DXLoadSurfaceFromFileInMemory
286 * Loads data from a given buffer into a surface and fills a given
287 * D3DXIMAGE_INFO structure with info about the source data.
290 * pDestSurface [I] pointer to the surface
291 * pDestPalette [I] palette to use
292 * pDestRect [I] to be filled area of the surface
293 * pSrcData [I] pointer to the source data
294 * SrcDataSize [I] size of the source data in bytes
295 * pSrcRect [I] area of the source data to load
296 * dwFilter [I] filter to apply on stretching
297 * Colorkey [I] colorkey
298 * pSrcInfo [O] pointer to a D3DXIMAGE_INFO structure
302 * Failure: D3DERR_INVALIDCALL, if pDestSurface or pSrcData or SrcDataSize are NULL
303 * D3DXERR_INVALIDDATA, if pSrcData is no valid image file
306 HRESULT WINAPI
D3DXLoadSurfaceFromFileInMemory(LPDIRECT3DSURFACE9 pDestSurface
,
307 CONST PALETTEENTRY
*pDestPalette
,
308 CONST RECT
*pDestRect
,
311 CONST RECT
*pSrcRect
,
314 D3DXIMAGE_INFO
*pSrcInfo
)
316 D3DXIMAGE_INFO imginfo
;
319 IWICImagingFactory
*factory
;
320 IWICBitmapDecoder
*decoder
;
321 IWICBitmapFrameDecode
*bitmapframe
;
324 const PixelFormatDesc
*formatdesc
;
328 TRACE("(%p, %p, %p, %p, %d, %p, %d, %x, %p)\n", pDestSurface
, pDestPalette
, pDestRect
, pSrcData
,
329 SrcDataSize
, pSrcRect
, dwFilter
, Colorkey
, pSrcInfo
);
331 if (!pDestSurface
|| !pSrcData
| !SrcDataSize
)
332 return D3DERR_INVALIDCALL
;
334 hr
= D3DXGetImageInfoFromFileInMemory(pSrcData
, SrcDataSize
, &imginfo
);
339 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
341 if (FAILED(CoCreateInstance(&CLSID_WICImagingFactory
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IWICImagingFactory
, (void**)&factory
)))
344 if (FAILED(IWICImagingFactory_CreateStream(factory
, &stream
)))
346 IWICImagingFactory_Release(factory
);
350 IWICStream_InitializeFromMemory(stream
, (BYTE
*)pSrcData
, SrcDataSize
);
352 hr
= IWICImagingFactory_CreateDecoderFromStream(factory
, (IStream
*)stream
, NULL
, 0, &decoder
);
354 IStream_Release(stream
);
355 IWICImagingFactory_Release(factory
);
360 hr
= IWICBitmapDecoder_GetFrame(decoder
, 0, &bitmapframe
);
367 wicrect
.X
= pSrcRect
->left
;
368 wicrect
.Y
= pSrcRect
->top
;
369 wicrect
.Width
= pSrcRect
->right
- pSrcRect
->left
;
370 wicrect
.Height
= pSrcRect
->bottom
- pSrcRect
->top
;
376 wicrect
.Width
= imginfo
.Width
;
377 wicrect
.Height
= imginfo
.Height
;
380 SetRect(&rect
, 0, 0, wicrect
.Width
, wicrect
.Height
);
382 formatdesc
= get_format_info(imginfo
.Format
);
384 if (formatdesc
->format
== D3DFMT_UNKNOWN
)
386 FIXME("Unsupported pixel format\n");
387 hr
= D3DXERR_INVALIDDATA
;
394 pitch
= formatdesc
->bytes_per_pixel
* wicrect
.Width
;
395 buffer
= HeapAlloc(GetProcessHeap(), 0, pitch
* wicrect
.Height
);
397 hr
= IWICBitmapFrameDecode_CopyPixels(bitmapframe
, &wicrect
, pitch
,
398 pitch
* wicrect
.Height
, buffer
);
402 hr
= D3DXLoadSurfaceFromMemory(pDestSurface
, pDestPalette
, pDestRect
,
403 buffer
, imginfo
.Format
, pitch
,
404 NULL
, &rect
, dwFilter
, Colorkey
);
407 HeapFree(GetProcessHeap(), 0, buffer
);
410 IWICBitmapFrameDecode_Release(bitmapframe
);
413 IWICBitmapDecoder_Release(decoder
);
419 return D3DXERR_INVALIDDATA
;
427 /************************************************************
428 * D3DXLoadSurfaceFromFile
430 HRESULT WINAPI
D3DXLoadSurfaceFromFileA(LPDIRECT3DSURFACE9 pDestSurface
,
431 CONST PALETTEENTRY
*pDestPalette
,
432 CONST RECT
*pDestRect
,
434 CONST RECT
*pSrcRect
,
437 D3DXIMAGE_INFO
*pSrcInfo
)
443 TRACE("(%p, %p, %p, %s, %p, %u, %#x, %p): relay\n", pDestSurface
, pDestPalette
, pDestRect
, debugstr_a(pSrcFile
),
444 pSrcRect
, dwFilter
, Colorkey
, pSrcInfo
);
446 if( !pSrcFile
|| !pDestSurface
) return D3DERR_INVALIDCALL
;
448 strlength
= MultiByteToWideChar(CP_ACP
, 0, pSrcFile
, -1, NULL
, 0);
449 pWidename
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, strlength
* sizeof(WCHAR
));
450 MultiByteToWideChar(CP_ACP
, 0, pSrcFile
, -1, pWidename
, strlength
);
452 hr
= D3DXLoadSurfaceFromFileW(pDestSurface
, pDestPalette
, pDestRect
, pWidename
, pSrcRect
, dwFilter
, Colorkey
, pSrcInfo
);
453 HeapFree(GetProcessHeap(), 0, pWidename
);
458 HRESULT WINAPI
D3DXLoadSurfaceFromFileW(LPDIRECT3DSURFACE9 pDestSurface
,
459 CONST PALETTEENTRY
*pDestPalette
,
460 CONST RECT
*pDestRect
,
462 CONST RECT
*pSrcRect
,
465 D3DXIMAGE_INFO
*pSrcInfo
)
471 TRACE("(%p, %p, %p, %s, %p, %u, %#x, %p): relay\n", pDestSurface
, pDestPalette
, pDestRect
, debugstr_w(pSrcFile
),
472 pSrcRect
, Filter
, Colorkey
, pSrcInfo
);
474 if( !pSrcFile
|| !pDestSurface
) return D3DERR_INVALIDCALL
;
476 hr
= map_view_of_file(pSrcFile
, &pBuffer
, &dwSize
);
477 if(FAILED(hr
)) return D3DXERR_INVALIDDATA
;
479 hr
= D3DXLoadSurfaceFromFileInMemory(pDestSurface
, pDestPalette
, pDestRect
, pBuffer
, dwSize
, pSrcRect
, Filter
, Colorkey
, pSrcInfo
);
480 UnmapViewOfFile(pBuffer
);
485 /************************************************************
486 * D3DXLoadSurfaceFromResource
488 HRESULT WINAPI
D3DXLoadSurfaceFromResourceA(LPDIRECT3DSURFACE9 pDestSurface
,
489 CONST PALETTEENTRY
*pDestPalette
,
490 CONST RECT
*pDestRect
,
493 CONST RECT
*pSrcRect
,
496 D3DXIMAGE_INFO
*pSrcInfo
)
500 TRACE("(%p, %p, %p, %p, %s, %p, %u, %#x, %p): relay\n", pDestSurface
, pDestPalette
, pDestRect
, hSrcModule
,
501 debugstr_a(pResource
), pSrcRect
, dwFilter
, Colorkey
, pSrcInfo
);
503 if( !pDestSurface
) return D3DERR_INVALIDCALL
;
505 hResInfo
= FindResourceA(hSrcModule
, pResource
, (LPCSTR
)RT_RCDATA
);
511 hr
= load_resource_into_memory(hSrcModule
, hResInfo
, &pBuffer
, &dwSize
);
512 if(FAILED(hr
)) return D3DXERR_INVALIDDATA
;
513 return D3DXLoadSurfaceFromFileInMemory(pDestSurface
, pDestPalette
, pDestRect
, pBuffer
, dwSize
, pSrcRect
, dwFilter
, Colorkey
, pSrcInfo
);
516 hResInfo
= FindResourceA(hSrcModule
, pResource
, (LPCSTR
)RT_BITMAP
);
518 FIXME("Implement loading bitmaps from resource type RT_BITMAP\n");
521 return D3DXERR_INVALIDDATA
;
524 HRESULT WINAPI
D3DXLoadSurfaceFromResourceW(LPDIRECT3DSURFACE9 pDestSurface
,
525 CONST PALETTEENTRY
*pDestPalette
,
526 CONST RECT
*pDestRect
,
529 CONST RECT
*pSrcRect
,
532 D3DXIMAGE_INFO
*pSrcInfo
)
536 TRACE("(%p, %p, %p, %p, %s, %p, %u, %#x, %p): relay\n", pDestSurface
, pDestPalette
, pDestRect
, hSrcModule
,
537 debugstr_w(pResource
), pSrcRect
, dwFilter
, Colorkey
, pSrcInfo
);
539 if( !pDestSurface
) return D3DERR_INVALIDCALL
;
541 hResInfo
= FindResourceW(hSrcModule
, pResource
, (LPCWSTR
)RT_RCDATA
);
547 hr
= load_resource_into_memory(hSrcModule
, hResInfo
, &pBuffer
, &dwSize
);
548 if(FAILED(hr
)) return D3DXERR_INVALIDDATA
;
549 return D3DXLoadSurfaceFromFileInMemory(pDestSurface
, pDestPalette
, pDestRect
, pBuffer
, dwSize
, pSrcRect
, dwFilter
, Colorkey
, pSrcInfo
);
552 hResInfo
= FindResourceW(hSrcModule
, pResource
, (LPCWSTR
)RT_BITMAP
);
554 FIXME("Implement loading bitmaps from resource type RT_BITMAP\n");
557 return D3DXERR_INVALIDDATA
;
561 /************************************************************
562 * helper functions for D3DXLoadSurfaceFromMemory
564 struct argb_conversion_info
566 CONST PixelFormatDesc
*srcformat
;
567 CONST PixelFormatDesc
*destformat
;
568 DWORD srcshift
[4], destshift
[4];
569 DWORD srcmask
[4], destmask
[4];
570 BOOL process_channel
[4];
574 static void init_argb_conversion_info(CONST PixelFormatDesc
*srcformat
, CONST PixelFormatDesc
*destformat
, struct argb_conversion_info
*info
)
577 ZeroMemory(info
->process_channel
, 4 * sizeof(BOOL
));
578 info
->channelmask
= 0;
580 info
->srcformat
= srcformat
;
581 info
->destformat
= destformat
;
583 for(i
= 0;i
< 4;i
++) {
584 /* srcshift is used to extract the _relevant_ components */
585 info
->srcshift
[i
] = srcformat
->shift
[i
] + max( srcformat
->bits
[i
] - destformat
->bits
[i
], 0);
587 /* destshift is used to move the components to the correct position */
588 info
->destshift
[i
] = destformat
->shift
[i
] + max(destformat
->bits
[i
] - srcformat
->bits
[i
], 0);
590 info
->srcmask
[i
] = ((1 << srcformat
->bits
[i
]) - 1) << srcformat
->shift
[i
];
591 info
->destmask
[i
] = ((1 << destformat
->bits
[i
]) - 1) << destformat
->shift
[i
];
593 /* channelmask specifies bits which aren't used in the source format but in the destination one */
594 if(destformat
->bits
[i
]) {
595 if(srcformat
->bits
[i
]) info
->process_channel
[i
] = TRUE
;
596 else info
->channelmask
|= info
->destmask
[i
];
601 /************************************************************
602 * get_relevant_argb_components
604 * Extracts the relevant components from the source color and
605 * drops the less significant bits if they aren't used by the destination format.
607 static void get_relevant_argb_components(CONST
struct argb_conversion_info
*info
, CONST DWORD col
, DWORD
*out
)
611 if(info
->process_channel
[i
])
612 out
[i
] = (col
& info
->srcmask
[i
]) >> info
->srcshift
[i
];
615 /************************************************************
618 * Recombines the output of get_relevant_argb_components and converts
619 * it to the destination format.
621 static void make_argb_color(CONST
struct argb_conversion_info
*info
, CONST DWORD
*in
, DWORD
*out
)
626 for(i
= 0;i
< 4;i
++) {
627 if(info
->process_channel
[i
]) {
628 /* necessary to make sure that e.g. an X4R4G4B4 white maps to an R8G8B8 white instead of 0xf0f0f0 */
630 for(shift
= info
->destshift
[i
]; shift
> info
->destformat
->shift
[i
]; shift
-= info
->srcformat
->bits
[i
]) *out
|= in
[i
] << shift
;
631 *out
|= (in
[i
] >> (info
->destformat
->shift
[i
] - shift
)) << info
->destformat
->shift
[i
];
634 *out
|= info
->channelmask
; /* new channels are set to their maximal value */
637 /************************************************************
640 * Copies the source buffer to the destination buffer, performing
641 * any necessary format conversion and color keying.
642 * Pixels outsize the source rect are blacked out.
643 * Works only for ARGB formats with 1 - 4 bytes per pixel.
645 static void copy_simple_data(CONST BYTE
*src
, UINT srcpitch
, POINT srcsize
,
646 CONST PixelFormatDesc
*srcformat
,
647 BYTE
*dest
, UINT destpitch
, POINT destsize
,
648 CONST PixelFormatDesc
*destformat
,
651 struct argb_conversion_info conv_info
, ck_conv_info
;
652 DWORD channels
[4], pixel
;
653 UINT minwidth
, minheight
;
656 ZeroMemory(channels
, sizeof(channels
));
657 init_argb_conversion_info(srcformat
, destformat
, &conv_info
);
659 minwidth
= (srcsize
.x
< destsize
.x
) ? srcsize
.x
: destsize
.x
;
660 minheight
= (srcsize
.y
< destsize
.y
) ? srcsize
.y
: destsize
.y
;
663 /* color keys are always represented in D3DFMT_A8R8G8B8 format */
664 const PixelFormatDesc
*ckformatdesc
;
666 ckformatdesc
= get_format_info(D3DFMT_A8R8G8B8
);
667 init_argb_conversion_info(srcformat
, ckformatdesc
, &ck_conv_info
);
670 for(y
= 0;y
< minheight
;y
++) {
671 const BYTE
*srcptr
= src
+ y
* srcpitch
;
672 BYTE
*destptr
= dest
+ y
* destpitch
;
673 for(x
= 0;x
< minwidth
;x
++) {
674 /* extract source color components */
675 if(srcformat
->type
== FORMAT_ARGB
) get_relevant_argb_components(&conv_info
, *(const DWORD
*)srcptr
, channels
);
677 /* recombine the components */
678 if(destformat
->type
== FORMAT_ARGB
) make_argb_color(&conv_info
, channels
, (DWORD
*)destptr
);
681 get_relevant_argb_components(&ck_conv_info
, *(const DWORD
*)srcptr
, channels
);
682 make_argb_color(&ck_conv_info
, channels
, &pixel
);
683 if(pixel
== colorkey
)
684 /* make this pixel transparent */
685 *(DWORD
*)destptr
&= ~conv_info
.destmask
[0];
688 srcptr
+= srcformat
->bytes_per_pixel
;
689 destptr
+= destformat
->bytes_per_pixel
;
692 if(srcsize
.x
< destsize
.x
) /* black out remaining pixels */
693 ZeroMemory(destptr
, destformat
->bytes_per_pixel
* (destsize
.x
- srcsize
.x
));
695 if(srcsize
.y
< destsize
.y
) /* black out remaining pixels */
696 ZeroMemory(dest
+ srcsize
.y
* destpitch
, destpitch
* (destsize
.y
- srcsize
.y
));
699 /************************************************************
700 * point_filter_simple_data
702 * Copies the source buffer to the destination buffer, performing
703 * any necessary format conversion, color keying and stretching
704 * using a point filter.
705 * Works only for ARGB formats with 1 - 4 bytes per pixel.
707 static void point_filter_simple_data(CONST BYTE
*src
, UINT srcpitch
, POINT srcsize
,
708 CONST PixelFormatDesc
*srcformat
,
709 BYTE
*dest
, UINT destpitch
, POINT destsize
,
710 CONST PixelFormatDesc
*destformat
,
713 struct argb_conversion_info conv_info
, ck_conv_info
;
714 DWORD channels
[4], pixel
;
718 ZeroMemory(channels
, sizeof(channels
));
719 init_argb_conversion_info(srcformat
, destformat
, &conv_info
);
722 /* color keys are always represented in D3DFMT_A8R8G8B8 format */
723 const PixelFormatDesc
*ckformatdesc
;
725 ckformatdesc
= get_format_info(D3DFMT_A8R8G8B8
);
726 init_argb_conversion_info(srcformat
, ckformatdesc
, &ck_conv_info
);
729 for(y
= 0;y
< destsize
.y
;y
++) {
730 BYTE
*destptr
= dest
+ y
* destpitch
;
731 const BYTE
*bufptr
= src
+ srcpitch
* (y
* srcsize
.y
/ destsize
.y
);
733 for(x
= 0;x
< destsize
.x
;x
++) {
734 const BYTE
*srcptr
= bufptr
+ (x
* srcsize
.x
/ destsize
.x
) * srcformat
->bytes_per_pixel
;
736 /* extract source color components */
737 if(srcformat
->type
== FORMAT_ARGB
) get_relevant_argb_components(&conv_info
, *(const DWORD
*)srcptr
, channels
);
739 /* recombine the components */
740 if(destformat
->type
== FORMAT_ARGB
) make_argb_color(&conv_info
, channels
, (DWORD
*)destptr
);
743 get_relevant_argb_components(&ck_conv_info
, *(const DWORD
*)srcptr
, channels
);
744 make_argb_color(&ck_conv_info
, channels
, &pixel
);
745 if(pixel
== colorkey
)
746 /* make this pixel transparent */
747 *(DWORD
*)destptr
&= ~conv_info
.destmask
[0];
750 destptr
+= destformat
->bytes_per_pixel
;
755 /************************************************************
756 * D3DXLoadSurfaceFromMemory
758 * Loads data from a given memory chunk into a surface,
759 * applying any of the specified filters.
762 * pDestSurface [I] pointer to the surface
763 * pDestPalette [I] palette to use
764 * pDestRect [I] to be filled area of the surface
765 * pSrcMemory [I] pointer to the source data
766 * SrcFormat [I] format of the source pixel data
767 * SrcPitch [I] number of bytes in a row
768 * pSrcPalette [I] palette used in the source image
769 * pSrcRect [I] area of the source data to load
770 * dwFilter [I] filter to apply on stretching
771 * Colorkey [I] colorkey
774 * Success: D3D_OK, if we successfully load the pixel data into our surface or
775 * if pSrcMemory is NULL but the other parameters are valid
776 * Failure: D3DERR_INVALIDCALL, if pDestSurface, SrcPitch or pSrcRect are NULL or
777 * if SrcFormat is an invalid format (other than D3DFMT_UNKNOWN) or
778 * if DestRect is invalid
779 * D3DXERR_INVALIDDATA, if we fail to lock pDestSurface
780 * E_FAIL, if SrcFormat is D3DFMT_UNKNOWN or the dimensions of pSrcRect are invalid
783 * pSrcRect specifies the dimensions of the source data;
784 * negative values for pSrcRect are allowed as we're only looking at the width and height anyway.
787 HRESULT WINAPI
D3DXLoadSurfaceFromMemory(LPDIRECT3DSURFACE9 pDestSurface
,
788 CONST PALETTEENTRY
*pDestPalette
,
789 CONST RECT
*pDestRect
,
793 CONST PALETTEENTRY
*pSrcPalette
,
794 CONST RECT
*pSrcRect
,
798 CONST PixelFormatDesc
*srcformatdesc
, *destformatdesc
;
799 D3DSURFACE_DESC surfdesc
;
800 D3DLOCKED_RECT lockrect
;
801 POINT srcsize
, destsize
;
804 TRACE("(%p, %p, %p, %p, %x, %u, %p, %p %u, %#x)\n", pDestSurface
, pDestPalette
, pDestRect
, pSrcMemory
,
805 SrcFormat
, SrcPitch
, pSrcPalette
, pSrcRect
, dwFilter
, Colorkey
);
807 if( !pDestSurface
|| !pSrcMemory
|| !pSrcRect
) return D3DERR_INVALIDCALL
;
808 if(SrcFormat
== D3DFMT_UNKNOWN
|| pSrcRect
->left
>= pSrcRect
->right
|| pSrcRect
->top
>= pSrcRect
->bottom
) return E_FAIL
;
810 if(dwFilter
== D3DX_DEFAULT
) dwFilter
= D3DX_FILTER_TRIANGLE
| D3DX_FILTER_DITHER
;
812 IDirect3DSurface9_GetDesc(pDestSurface
, &surfdesc
);
814 srcformatdesc
= get_format_info(SrcFormat
);
815 destformatdesc
= get_format_info(surfdesc
.Format
);
816 if( srcformatdesc
->type
== FORMAT_UNKNOWN
|| srcformatdesc
->bytes_per_pixel
> 4) return E_NOTIMPL
;
817 if(destformatdesc
->type
== FORMAT_UNKNOWN
|| destformatdesc
->bytes_per_pixel
> 4) return E_NOTIMPL
;
819 srcsize
.x
= pSrcRect
->right
- pSrcRect
->left
;
820 srcsize
.y
= pSrcRect
->bottom
- pSrcRect
->top
;
822 destsize
.x
= surfdesc
.Width
;
823 destsize
.y
= surfdesc
.Height
;
825 if(pDestRect
->left
> pDestRect
->right
|| pDestRect
->right
> surfdesc
.Width
) return D3DERR_INVALIDCALL
;
826 if(pDestRect
->top
> pDestRect
->bottom
|| pDestRect
->bottom
> surfdesc
.Height
) return D3DERR_INVALIDCALL
;
827 if(pDestRect
->left
< 0 || pDestRect
->top
< 0) return D3DERR_INVALIDCALL
;
828 destsize
.x
= pDestRect
->right
- pDestRect
->left
;
829 destsize
.y
= pDestRect
->bottom
- pDestRect
->top
;
830 if(destsize
.x
== 0 || destsize
.y
== 0) return D3D_OK
;
833 hr
= IDirect3DSurface9_LockRect(pDestSurface
, &lockrect
, pDestRect
, 0);
834 if(FAILED(hr
)) return D3DXERR_INVALIDDATA
;
836 if((dwFilter
& 0xF) == D3DX_FILTER_NONE
) {
837 copy_simple_data(pSrcMemory
, SrcPitch
, srcsize
, srcformatdesc
,
838 lockrect
.pBits
, lockrect
.Pitch
, destsize
, destformatdesc
,
840 } else /*if((dwFilter & 0xF) == D3DX_FILTER_POINT) */ {
841 /* always apply a point filter until D3DX_FILTER_LINEAR, D3DX_FILTER_TRIANGLE and D3DX_FILTER_BOX are implemented */
842 point_filter_simple_data(pSrcMemory
, SrcPitch
, srcsize
, srcformatdesc
,
843 lockrect
.pBits
, lockrect
.Pitch
, destsize
, destformatdesc
,
847 IDirect3DSurface9_UnlockRect(pDestSurface
);
851 /************************************************************
852 * D3DXLoadSurfaceFromSurface
854 * Copies the contents from one surface to another, performing any required
855 * format conversion, resizing or filtering.
858 * pDestSurface [I] pointer to the destination surface
859 * pDestPalette [I] palette to use
860 * pDestRect [I] to be filled area of the surface
861 * pSrcSurface [I] pointer to the source surface
862 * pSrcPalette [I] palette used for the source surface
863 * pSrcRect [I] area of the source data to load
864 * dwFilter [I] filter to apply on resizing
865 * Colorkey [I] any ARGB value or 0 to disable color-keying
869 * Failure: D3DERR_INVALIDCALL, if pDestSurface or pSrcSurface are NULL
870 * D3DXERR_INVALIDDATA, if one of the surfaces is not lockable
873 HRESULT WINAPI
D3DXLoadSurfaceFromSurface(LPDIRECT3DSURFACE9 pDestSurface
,
874 CONST PALETTEENTRY
*pDestPalette
,
875 CONST RECT
*pDestRect
,
876 LPDIRECT3DSURFACE9 pSrcSurface
,
877 CONST PALETTEENTRY
*pSrcPalette
,
878 CONST RECT
*pSrcRect
,
884 D3DSURFACE_DESC SrcDesc
;
887 TRACE("(%p, %p, %p, %p, %p, %p, %u, %#x): relay\n", pDestSurface
, pDestPalette
, pDestRect
,
888 pSrcSurface
, pSrcPalette
, pSrcRect
, dwFilter
, Colorkey
);
890 if( !pDestSurface
|| !pSrcSurface
) return D3DERR_INVALIDCALL
;
892 IDirect3DSurface9_GetDesc(pSrcSurface
, &SrcDesc
);
894 if( !pSrcRect
) SetRect(&rect
, 0, 0, SrcDesc
.Width
, SrcDesc
.Height
);
895 else rect
= *pSrcRect
;
897 hr
= IDirect3DSurface9_LockRect(pSrcSurface
, &lock
, NULL
, D3DLOCK_READONLY
);
898 if(FAILED(hr
)) return D3DXERR_INVALIDDATA
;
900 hr
= D3DXLoadSurfaceFromMemory(pDestSurface
, pDestPalette
, pDestRect
,
901 lock
.pBits
, SrcDesc
.Format
, lock
.Pitch
,
902 pSrcPalette
, &rect
, dwFilter
, Colorkey
);
904 IDirect3DSurface9_UnlockRect(pSrcSurface
);