d3dx9: Apply current transform in ID3DXSprite_Draw instead of ID3DXSprite_Flush.
[wine/d3dx9TW.git] / dlls / d3dx9_36 / dds.c
blobb66f9cbbbd7cd864beb721c6a1f0522500c5659a
1 /*
2 * Copyright (C) 2009 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"
22 #define COBJMACROS
23 #include "d3dx9_36_private.h"
24 #include "wincodec.h"
25 #undef MAKE_DDHRESULT
26 #include "ddraw.h"
28 #ifndef DDSD_DEPTH
29 #define DDSD_DEPTH 0x00800000
30 #undef DDSD_ALL
31 #define DDSD_ALL 0x00fff9ee
32 #endif
34 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
36 const GUID GUID_d3dx_container_format_dds = { 0x2559CD66, 0xA5D4, 0x44AB, { 0xBD, 0xF3, 0x72, 0x69, 0xBA, 0x9B, 0xC9, 0xE0 } };
37 const GUID GUID_d3dx_pixel_format32bppRGB = { 0x55F197D5, 0xE1AB, 0x48B9, { 0x99, 0x51, 0x01, 0x13, 0xB4, 0x6B, 0x8A, 0x85 } };
38 const GUID GUID_d3dx_pixel_format32bppRGBA = { 0xE170EC37, 0x48D4, 0x443B, { 0x8E, 0xA7, 0xA4, 0x63, 0x28, 0x43, 0x74, 0x57 } };
40 typedef struct DDSFrameDecode {
41 const IWICBitmapFrameDecodeVtbl *lpVtbl;
42 LONG ref;
44 IStream *pStream;
45 DDSURFACEDESC2 Desc;
46 const WICPixelFormatGUID *pPixelFormat;
48 BYTE *pImageData;
49 UINT Width, Height;
50 UINT StreamOffset;
52 BOOL bInitialized;
53 } DDSFrameDecode;
55 static HRESULT WINAPI DDSFrameDecode_QueryInterface(IWICBitmapFrameDecode *iface, REFIID iid, void **ppv)
57 DDSFrameDecode *This = (DDSFrameDecode*)iface;
58 TRACE("(%p)\n", This);
60 if (!ppv) return E_INVALIDARG;
62 if (IsEqualIID(&IID_IUnknown, iid) ||
63 IsEqualIID(&IID_IWICBitmapSource, iid) ||
64 IsEqualIID(&IID_IWICBitmapFrameDecode, iid)) {
65 *ppv = This;
66 IUnknown_AddRef((IUnknown*)*ppv);
67 return S_OK;
68 } else {
69 *ppv = NULL;
70 return E_NOINTERFACE;
74 static ULONG WINAPI DDSFrameDecode_AddRef(IWICBitmapFrameDecode *iface)
76 DDSFrameDecode *This = (DDSFrameDecode*)iface;
77 ULONG ref = InterlockedIncrement(&This->ref);
79 TRACE("(%p) AddRef to %u\n", iface, ref);
81 return ref;
84 static ULONG WINAPI DDSFrameDecode_Release(IWICBitmapFrameDecode *iface)
86 DDSFrameDecode *This = (DDSFrameDecode*)iface;
87 ULONG ref = InterlockedDecrement(&This->ref);
89 TRACE("(%p) Release to %u\n", iface, ref);
91 if (ref == 0) {
92 if(This->pImageData) HeapFree(GetProcessHeap(), 0, This->pImageData);
93 if(This->pStream) IStream_Release(This->pStream);
94 HeapFree(GetProcessHeap(), 0, This);
96 return ref;
99 static HRESULT WINAPI DDSFrameDecode_CopyPalette(IWICBitmapFrameDecode *iface, IWICPalette *pIPalette)
101 DDSFrameDecode *This = (DDSFrameDecode*)iface;
102 FIXME("(%p): stub\n", This);
103 return E_NOTIMPL;
106 static HRESULT WINAPI DDSFrameDecode_CopyPixels(IWICBitmapFrameDecode *iface, const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
108 DDSFrameDecode *This = (DDSFrameDecode*)iface;
109 LARGE_INTEGER Pos;
110 HRESULT hr;
111 UINT bytesperrow;
112 UINT row;
113 BYTE *src;
114 BYTE *dst;
115 WICRect rect;
116 TRACE("(%p)\n", This);
118 if( !prc ) {
119 rect.X = 0;
120 rect.Y = 0;
121 rect.Width = This->Width;
122 rect.Height = This->Height;
123 } else rect = *prc;
125 if(cbStride < (unsigned)This->Desc.lPitch) return E_INVALIDARG;
126 if(cbStride * rect.Height > cbBufferSize) return E_INVALIDARG;
128 if(rect.X < 0 || rect.Y < 0 || (unsigned)(rect.X + rect.Width) > This->Width || (unsigned)(rect.Y + rect.Height) > This->Height)
129 return E_INVALIDARG;
131 Pos.QuadPart = This->StreamOffset;
132 hr = IStream_Seek(This->pStream, Pos, STREAM_SEEK_SET, NULL);
133 if(FAILED(hr)) return E_INVALIDARG;
135 if( !This->pImageData) This->pImageData = HeapAlloc(GetProcessHeap(), 0, This->Height * This->Desc.lPitch);
137 hr = IStream_Read(This->pStream, This->pImageData, This->Height * This->Desc.lPitch, NULL);
138 if(FAILED(hr)) return E_INVALIDARG;
140 src = This->pImageData + rect.X * This->Desc.ddpfPixelFormat.dwRGBBitCount / 8;
141 dst = pbBuffer;
142 bytesperrow = (rect.Width * This->Desc.ddpfPixelFormat.dwRGBBitCount) / 8;
143 for (row = 0; row < (unsigned)rect.Height; row++) {
144 memcpy(dst, src, bytesperrow);
145 src += This->Desc.lPitch;
146 dst += cbStride;
149 return S_OK;
152 static HRESULT WINAPI DDSFrameDecode_GetPixelFormat(IWICBitmapFrameDecode *iface, WICPixelFormatGUID *pPixelFormat)
154 DDSFrameDecode *This = (DDSFrameDecode*)iface;
155 TRACE("(%p)\n", This);
157 if( !pPixelFormat ) return E_INVALIDARG;
158 *pPixelFormat = *This->pPixelFormat;
160 return S_OK;
163 static HRESULT WINAPI DDSFrameDecode_GetResolution(IWICBitmapFrameDecode *iface, double *pDpiX, double *pDpiY)
165 DDSFrameDecode *This = (DDSFrameDecode*)iface;
166 FIXME("(%p): stub\n", This);
167 return E_NOTIMPL;
170 static HRESULT WINAPI DDSFrameDecode_GetSize(IWICBitmapFrameDecode *iface, UINT *puiWidth, UINT *puiHeight)
172 DDSFrameDecode *This = (DDSFrameDecode*)iface;
173 TRACE("(%p)\n", This);
175 if( !puiWidth || !puiHeight ) return E_INVALIDARG;
177 *puiWidth = This->Width;
178 *puiHeight = This->Height;
180 return S_OK;
183 static HRESULT WINAPI DDSFrameDecode_GetColorContexts(IWICBitmapFrameDecode *iface, UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
185 DDSFrameDecode *This = (DDSFrameDecode*)iface;
186 FIXME("(%p): stub\n", This);
187 return E_NOTIMPL;
190 static HRESULT WINAPI DDSFrameDecode_GetMetadataQueryReader(IWICBitmapFrameDecode *iface, IWICMetadataQueryReader **ppIMetadataQueryReader)
192 DDSFrameDecode *This = (DDSFrameDecode*)iface;
193 FIXME("(%p): stub\n", This);
194 return E_NOTIMPL;
197 static HRESULT WINAPI DDSFrameDecode_GetThumbnail(IWICBitmapFrameDecode *iface, IWICBitmapSource **ppIThumbnail)
199 DDSFrameDecode *This = (DDSFrameDecode*)iface;
200 FIXME("(%p): stub\n", This);
201 return E_NOTIMPL;
204 static const IWICBitmapFrameDecodeVtbl DDSFrameDecodeVtbl = {
205 DDSFrameDecode_QueryInterface,
206 DDSFrameDecode_AddRef,
207 DDSFrameDecode_Release,
208 DDSFrameDecode_GetSize,
209 DDSFrameDecode_GetPixelFormat,
210 DDSFrameDecode_GetResolution,
211 DDSFrameDecode_CopyPalette,
212 DDSFrameDecode_CopyPixels,
213 DDSFrameDecode_GetMetadataQueryReader,
214 DDSFrameDecode_GetColorContexts,
215 DDSFrameDecode_GetThumbnail
219 typedef struct DDSDecoder {
220 const IWICBitmapDecoderVtbl *lpVtbl;
221 LONG ref;
223 IStream *pStream;
224 DDSURFACEDESC2 Desc;
225 const WICPixelFormatGUID *pPixelFormat;
226 BOOL bInitialized;
228 DDSFrameDecode **ppFrameDecoders;
229 UINT NumFrames;
230 } DDSDecoder;
232 static HRESULT WINAPI DDSDecoder_QueryInterface(IWICBitmapDecoder *iface, REFIID iid, void **ppv)
234 DDSDecoder *This = (DDSDecoder*)iface;
235 TRACE("(%p)\n", This);
237 if (!ppv) return E_INVALIDARG;
239 if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IWICBitmapDecoder, iid)) {
240 *ppv = This;
241 IUnknown_AddRef((IUnknown*)*ppv);
242 return S_OK;
243 } else {
244 *ppv = NULL;
245 return E_NOINTERFACE;
249 static ULONG WINAPI DDSDecoder_AddRef(IWICBitmapDecoder *iface)
251 DDSDecoder *This = (DDSDecoder*)iface;
252 ULONG ref = InterlockedIncrement(&This->ref);
254 TRACE("(%p) AddRef to %u\n", iface, ref);
256 return ref;
259 static ULONG WINAPI DDSDecoder_Release(IWICBitmapDecoder *iface)
261 DDSDecoder *This = (DDSDecoder*)iface;
262 ULONG ref = InterlockedDecrement(&This->ref);
264 TRACE("(%p) Release to %u\n", iface, ref);
266 if (ref == 0) {
267 if(This->ppFrameDecoders) {
268 UINT i;
269 for(i = 0;i < This->NumFrames;i++) if(This->ppFrameDecoders[i]) IUnknown_Release((IUnknown*)(This->ppFrameDecoders[i]));
270 HeapFree(GetProcessHeap(), 0, This->ppFrameDecoders);
272 if(This->pStream) IStream_Release(This->pStream);
273 HeapFree(GetProcessHeap(), 0, This);
275 return ref;
278 struct dds_pixel_format {
279 WORD bitcount; /* 0 for end of list */
280 DWORD redmask;
281 DWORD greenmask;
282 DWORD bluemask;
283 DWORD alphamask;
284 const WICPixelFormatGUID *pixelformat;
287 static const struct dds_pixel_format dds_pixel_formats[] = {
288 { 16, 0x7c00, 0x3e0, 0x1f, 0, &GUID_WICPixelFormat16bppBGR555 },
289 { 16, 0xf800, 0x7e0, 0x1f, 0, &GUID_WICPixelFormat16bppBGR565 },
290 { 24, 0xff0000, 0xff00, 0xff, 0, &GUID_WICPixelFormat24bppBGR },
291 { 32, 0xff0000, 0xff00, 0xff, 0, &GUID_WICPixelFormat32bppBGR },
292 { 32, 0xff0000, 0xff00, 0xff, 0xff000000, &GUID_WICPixelFormat32bppBGRA },
293 { 32, 0xff, 0xff00, 0xff0000, 0, &GUID_d3dx_pixel_format32bppRGB },
294 { 32, 0xff, 0xff00, 0xff0000, 0xff000000, &GUID_d3dx_pixel_format32bppRGBA },
295 { 0, 0, 0, 0, 0, NULL }
299 static HRESULT DDSDecoder_ReadHeaders(DDSDecoder *This, IStream *pStream)
301 DWORD dwMagic;
302 ULONG BytesRead;
303 HRESULT hr;
305 if(This->bInitialized) return WINCODEC_ERR_WRONGSTATE;
307 hr = IStream_Read(pStream, &dwMagic, sizeof(DWORD), &BytesRead);
308 if(FAILED(hr)) return hr;
309 if(BytesRead != sizeof(DWORD)) return E_INVALIDARG;
310 if(dwMagic != 0x20534444) {
311 TRACE("File is not a DDS file\n");
312 return E_INVALIDARG;
315 hr = IStream_Read(pStream, &This->Desc, sizeof(DDSURFACEDESC2), &BytesRead);
316 if(FAILED(hr)) return hr;
317 if(BytesRead != sizeof(DDSURFACEDESC2)) return E_INVALIDARG;
319 if(This->Desc.dwSize != 124) {
320 WARN("Invalid DDSURFACEDESC2 structure size %d\n", This->Desc.dwSize);
321 return E_INVALIDARG;
323 if( !(This->Desc.dwFlags & (DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT)) ) {
324 WARN("Invalid DDS flags %#x\n", This->Desc.dwFlags);
325 return E_INVALIDARG;
327 if(This->Desc.dwHeight == 0 || This->Desc.dwWidth == 0) return E_INVALIDARG;
329 if( !(This->Desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE) ) {
330 WARN("DDS caps %#x don't contain DDSCAPS_TEXTURE\n", This->Desc.ddsCaps.dwCaps);
331 return E_INVALIDARG;
334 if(This->Desc.dwFlags & DDSD_PITCH) {
335 /* TODO */
336 } else if(This->Desc.dwFlags & DDSD_LINEARSIZE) {
337 /* TODO */
338 } else {
339 This->Desc.lPitch = This->Desc.dwWidth * This->Desc.ddpfPixelFormat.dwRGBBitCount / 8;
341 This->Desc.lPitch = This->Desc.dwWidth * This->Desc.ddpfPixelFormat.dwRGBBitCount / 8;
343 This->NumFrames = 1;
344 if(This->Desc.dwFlags & DDSD_MIPMAPCOUNT) This->NumFrames = This->Desc.dwMipMapCount + 1; /* TODO: Verify the + 1 */
345 if(This->Desc.dwFlags & DDSD_DEPTH) {
346 FIXME("Depth images aren't supported, yet\n");
347 return E_NOTIMPL;
350 if(This->Desc.ddpfPixelFormat.dwFlags == DDPF_RGB) {
351 UINT i;
352 for(i = 0;dds_pixel_formats[i].bitcount != 0;i++) {
353 if(dds_pixel_formats[i].bitcount == This->Desc.ddpfPixelFormat.dwRGBBitCount &&
354 dds_pixel_formats[i].redmask == This->Desc.ddpfPixelFormat.dwRBitMask &&
355 dds_pixel_formats[i].greenmask == This->Desc.ddpfPixelFormat.dwGBitMask &&
356 dds_pixel_formats[i].bluemask == This->Desc.ddpfPixelFormat.dwBBitMask) {
357 This->pPixelFormat = dds_pixel_formats[i].pixelformat;
358 break;
361 if(dds_pixel_formats[i].bitcount == 0) {
362 WARN("Unknown RGB pixel format %#x, %#x, %#x\n", This->Desc.ddpfPixelFormat.dwRBitMask,
363 This->Desc.ddpfPixelFormat.dwGBitMask,
364 This->Desc.ddpfPixelFormat.dwBBitMask);
365 return E_NOTIMPL;
367 } else if(This->Desc.ddpfPixelFormat.dwFlags == (DDPF_RGB | DDPF_ALPHAPIXELS)) {
368 UINT i;
369 for(i = 0;dds_pixel_formats[i].bitcount != 0;i++) {
370 if(dds_pixel_formats[i].bitcount == This->Desc.ddpfPixelFormat.dwRGBBitCount &&
371 dds_pixel_formats[i].redmask == This->Desc.ddpfPixelFormat.dwRBitMask &&
372 dds_pixel_formats[i].greenmask == This->Desc.ddpfPixelFormat.dwGBitMask &&
373 dds_pixel_formats[i].bluemask == This->Desc.ddpfPixelFormat.dwBBitMask &&
374 dds_pixel_formats[i].alphamask == This->Desc.ddpfPixelFormat.dwRGBAlphaBitMask) {
375 This->pPixelFormat = dds_pixel_formats[i].pixelformat;
376 break;
379 if(dds_pixel_formats[i].bitcount == 0) {
380 WARN("Unknown ARGB pixel format %#x, %#x, %#x, %#x\n", This->Desc.ddpfPixelFormat.dwRGBAlphaBitMask,
381 This->Desc.ddpfPixelFormat.dwRBitMask,
382 This->Desc.ddpfPixelFormat.dwGBitMask,
383 This->Desc.ddpfPixelFormat.dwBBitMask);
384 return E_NOTIMPL;
386 } else if(This->Desc.ddpfPixelFormat.dwFlags & DDPF_FOURCC) {
387 FIXME("FourCC images not supported, yet!, %#x\n", This->Desc.ddpfPixelFormat.dwFlags);
388 return E_NOTIMPL;
389 } else if(This->Desc.ddpfPixelFormat.dwFlags & DDPF_LUMINANCE) {
390 FIXME("Luminance images not supported, yet!, %#x\n", This->Desc.ddpfPixelFormat.dwFlags);
391 return E_NOTIMPL;
392 } else {
393 WARN("Unknown flags %#x\n", This->Desc.ddpfPixelFormat.dwFlags);
394 return E_INVALIDARG;
397 This->bInitialized = TRUE;
398 return S_OK;
401 static HRESULT WINAPI DDSDecoder_QueryCapability(IWICBitmapDecoder *iface, IStream *pIStream, DWORD *pdwCapability)
403 DDSDecoder *This = (DDSDecoder*)iface;
404 ULARGE_INTEGER StreamPosition;
405 LARGE_INTEGER LargeInt;
406 HRESULT hr;
407 TRACE("(%p)\n", This);
409 if( !pdwCapability ) return E_INVALIDARG;
411 /* save current stream position */
412 LargeInt.QuadPart = 0;
413 IStream_Seek(pIStream, LargeInt, STREAM_SEEK_CUR, &StreamPosition);
415 hr = DDSDecoder_ReadHeaders(This, pIStream);
417 /* restore stream position */
418 LargeInt.QuadPart = StreamPosition.QuadPart;
419 IStream_Seek(pIStream, LargeInt, STREAM_SEEK_SET, &StreamPosition);
421 if(FAILED(hr)) return hr;
422 *pdwCapability = WICBitmapDecoderCapabilityCanDecodeAllImages;
423 return S_OK;
426 static HRESULT WINAPI DDSDecoder_Initialize(IWICBitmapDecoder *iface, IStream *pIStream, WICDecodeOptions cacheOptions)
428 DDSDecoder *This = (DDSDecoder*)iface;
429 LARGE_INTEGER LargeInt;
430 HRESULT hr;
431 UINT i;
432 TRACE("(%p)\n", This);
434 LargeInt.QuadPart = 0;
435 IStream_Seek(pIStream, LargeInt, STREAM_SEEK_SET, NULL);
437 hr = DDSDecoder_ReadHeaders(This, pIStream);
438 if(FAILED(hr)) return hr;
440 This->ppFrameDecoders = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->NumFrames * sizeof(DDSFrameDecode*));
441 if( !This->ppFrameDecoders ) return E_OUTOFMEMORY;
443 This->pStream = pIStream;
444 IStream_AddRef(pIStream);
446 for(i = 0;i < This->NumFrames;i++) {
447 This->ppFrameDecoders[i] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DDSFrameDecode));
449 This->ppFrameDecoders[i]->lpVtbl = &DDSFrameDecodeVtbl;
450 This->ppFrameDecoders[i]->ref = 1;
451 This->ppFrameDecoders[i]->Desc = This->Desc;
452 This->ppFrameDecoders[i]->pPixelFormat = This->pPixelFormat;
453 This->ppFrameDecoders[i]->pImageData = NULL;
454 This->ppFrameDecoders[i]->pStream = This->pStream;
455 IStream_AddRef(This->pStream);
456 This->ppFrameDecoders[i]->bInitialized = TRUE;
458 /* TODO: Use substreams instead of offsets */
459 if(i > 0) {
460 if(This->Desc.dwFlags & DDSD_DEPTH) {
461 FIXME("TODO: Support depth textures\n");
463 if(This->Desc.dwFlags & DDSD_MIPMAPCOUNT) {
464 This->ppFrameDecoders[i]->Width = This->ppFrameDecoders[i-1]->Width / 2;
465 This->ppFrameDecoders[i]->Height = This->ppFrameDecoders[i-1]->Height / 2;
466 This->ppFrameDecoders[i]->StreamOffset = This->ppFrameDecoders[i-1]->StreamOffset + This->ppFrameDecoders[i]->Width * This->ppFrameDecoders[i]->Height * This->Desc.ddpfPixelFormat.dwRGBBitCount / 8;
468 } else {
469 This->ppFrameDecoders[i]->Width = This->Desc.dwWidth;
470 This->ppFrameDecoders[i]->Height = This->Desc.dwHeight;
471 This->ppFrameDecoders[i]->StreamOffset = sizeof(DWORD) + This->Desc.dwSize;
475 return S_OK;
478 static HRESULT WINAPI DDSDecoder_GetContainerFormat(IWICBitmapDecoder *iface, GUID *pguidContainerFormat)
480 DDSDecoder *This = (DDSDecoder*)iface;
481 TRACE("(%p)\n", This);
483 if (!pguidContainerFormat) return E_INVALIDARG;
484 memcpy(pguidContainerFormat, &GUID_d3dx_container_format_dds, sizeof(GUID));
486 return S_OK;
489 static HRESULT WINAPI DDSDecoder_GetDecoderInfo(IWICBitmapDecoder *iface, IWICBitmapDecoderInfo **ppIDecoderInfo)
491 DDSDecoder *This = (DDSDecoder*)iface;
492 FIXME("(%p): stub\n", This);
493 return E_NOTIMPL;
496 static HRESULT WINAPI DDSDecoder_CopyPalette(IWICBitmapDecoder *iface, IWICPalette *pIPalette)
498 DDSDecoder *This = (DDSDecoder*)iface;
499 FIXME("(%p): stub\n", This);
500 return E_NOTIMPL;
503 static HRESULT WINAPI DDSDecoder_GetMetadataQueryReader(IWICBitmapDecoder *iface, IWICMetadataQueryReader **ppIMetadataQueryReader)
505 DDSDecoder *This = (DDSDecoder*)iface;
506 FIXME("(%p): stub\n", This);
507 return E_NOTIMPL;
510 static HRESULT WINAPI DDSDecoder_GetPreview(IWICBitmapDecoder *iface, IWICBitmapSource **ppIBitmapSource)
512 DDSDecoder *This = (DDSDecoder*)iface;
513 FIXME("(%p): stub\n", This);
514 return E_NOTIMPL;
517 static HRESULT WINAPI DDSDecoder_GetColorContexts(IWICBitmapDecoder *iface, UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
519 DDSDecoder *This = (DDSDecoder*)iface;
520 FIXME("(%p): stub\n", This);
521 return E_NOTIMPL;
524 static HRESULT WINAPI DDSDecoder_GetThumbnail(IWICBitmapDecoder *iface, IWICBitmapSource **ppIThumbnail)
526 DDSDecoder *This = (DDSDecoder*)iface;
527 FIXME("(%p): stub\n", This);
528 return E_NOTIMPL;
531 static HRESULT WINAPI DDSDecoder_GetFrameCount(IWICBitmapDecoder *iface, UINT *pCount)
533 DDSDecoder *This = (DDSDecoder*)iface;
534 TRACE("(%p)\n", This);
536 if( !pCount ) return E_INVALIDARG;
537 *pCount = This->NumFrames;
539 return S_OK;
542 /***********************************************
543 * DDSDecoder_GetFrame
545 * Frame indices for normal textures:
546 * 0: Main image
547 * 1: Mipmap 1
548 * 2: Mipmap 2
549 * ...
552 static HRESULT WINAPI DDSDecoder_GetFrame(IWICBitmapDecoder *iface, UINT index, IWICBitmapFrameDecode **ppIBitmapFrame)
554 DDSDecoder *This = (DDSDecoder*)iface;
555 TRACE("(%p)\n", This);
557 if (!This->pStream) return WINCODEC_ERR_WRONGSTATE;
558 if(index >= This->NumFrames) return E_INVALIDARG;
560 *ppIBitmapFrame = (IWICBitmapFrameDecode*)This->ppFrameDecoders[index];
561 IWICBitmapFrameDecode_AddRef((IWICBitmapFrameDecode*)This->ppFrameDecoders[index]);
563 return S_OK;
567 static const IWICBitmapDecoderVtbl DDSDecoderVtbl = {
568 DDSDecoder_QueryInterface,
569 DDSDecoder_AddRef,
570 DDSDecoder_Release,
571 DDSDecoder_QueryCapability,
572 DDSDecoder_Initialize,
573 DDSDecoder_GetContainerFormat,
574 DDSDecoder_GetDecoderInfo,
575 DDSDecoder_CopyPalette,
576 DDSDecoder_GetMetadataQueryReader,
577 DDSDecoder_GetPreview,
578 DDSDecoder_GetColorContexts,
579 DDSDecoder_GetThumbnail,
580 DDSDecoder_GetFrameCount,
581 DDSDecoder_GetFrame
584 HRESULT DDSDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
586 DDSDecoder *This;
587 HRESULT ret;
589 TRACE("(%p,%s,%p)\n", pUnkOuter, debugstr_guid(iid), ppv);
591 if (!ppv) return E_INVALIDARG;
592 *ppv = NULL;
594 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
596 This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DDSDecoder));
597 if (!This) return E_OUTOFMEMORY;
599 This->lpVtbl = &DDSDecoderVtbl;
600 This->ref = 1;
602 ret = IWICBitmapDecoder_QueryInterface((IWICBitmapDecoder*)This, iid, ppv);
603 IWICBitmapDecoder_Release((IWICBitmapDecoder*)This);
605 return ret;