2 * Copyright 2000 Bradley Baetz
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
18 * FIXME: Some flags are ignored
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(msvideo
);
37 typedef struct tagWINE_HDD
{
41 LPBITMAPINFOHEADER lpbi
;
44 HPALETTE hpal
; /* Palette to use for the DIB */
45 BOOL begun
; /* DrawDibBegin has been called */
46 LPBITMAPINFOHEADER lpbiOut
; /* Output format */
47 HIC hic
; /* HIC for decompression */
48 HDC hMemDC
; /* DC for buffering */
49 HBITMAP hOldDib
; /* Original Dib */
50 HBITMAP hDib
; /* DibSection */
51 LPVOID lpvbits
; /* Buffer for holding decompressed dib */
53 struct tagWINE_HDD
* next
;
56 static int num_colours(const BITMAPINFOHEADER
*lpbi
)
59 return lpbi
->biClrUsed
;
60 if(lpbi
->biBitCount
<=8)
61 return 1<<lpbi
->biBitCount
;
65 static WINE_HDD
* HDD_FirstHdd
/* = NULL */;
67 static WINE_HDD
* MSVIDEO_GetHddPtr(HDRAWDIB hd
)
71 for (hdd
= HDD_FirstHdd
; hdd
!= NULL
&& hdd
->hSelf
!= hd
; hdd
= hdd
->next
);
75 static UINT_PTR HDD_HandleRef
= 1;
77 /***********************************************************************
78 * DrawDibOpen [MSVFW32.@]
80 HDRAWDIB VFWAPI
DrawDibOpen(void)
86 whdd
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(WINE_HDD
));
87 TRACE("=> %p\n", whdd
);
89 while (MSVIDEO_GetHddPtr((HDRAWDIB
)HDD_HandleRef
) != NULL
) HDD_HandleRef
++;
90 whdd
->hSelf
= (HDRAWDIB
)HDD_HandleRef
++;
92 whdd
->next
= HDD_FirstHdd
;
98 /***********************************************************************
99 * DrawDibClose [MSVFW32.@]
101 BOOL VFWAPI
DrawDibClose(HDRAWDIB hdd
)
103 WINE_HDD
* whdd
= MSVIDEO_GetHddPtr(hdd
);
106 TRACE("(%p)\n", hdd
);
108 if (!whdd
) return FALSE
;
110 if (whdd
->begun
) DrawDibEnd(hdd
);
112 for (p
= &HDD_FirstHdd
; *p
!= NULL
; p
= &((*p
)->next
))
121 HeapFree(GetProcessHeap(), 0, whdd
);
126 /***********************************************************************
127 * DrawDibEnd [MSVFW32.@]
129 BOOL VFWAPI
DrawDibEnd(HDRAWDIB hdd
)
132 WINE_HDD
*whdd
= MSVIDEO_GetHddPtr(hdd
);
134 TRACE("(%p)\n", hdd
);
136 if (!whdd
) return FALSE
;
138 whdd
->hpal
= 0; /* Do not free this */
140 HeapFree(GetProcessHeap(), 0, whdd
->lpbi
);
142 HeapFree(GetProcessHeap(), 0, whdd
->lpbiOut
);
143 whdd
->lpbiOut
= NULL
;
148 HeapFree(GetProcessHeap(), 0, whdd->lpvbuf);*/
152 SelectObject(whdd
->hMemDC
, whdd
->hOldDib
);
153 DeleteDC(whdd
->hMemDC
);
157 if (whdd
->hDib
) DeleteObject(whdd
->hDib
);
162 ICDecompressEnd(whdd
->hic
);
167 whdd
->lpvbits
= NULL
;
172 /***********************************************************************
173 * DrawDibBegin [MSVFW32.@]
175 BOOL VFWAPI
DrawDibBegin(HDRAWDIB hdd
,
179 LPBITMAPINFOHEADER lpbi
,
187 TRACE("(%p,%p,%d,%d,%p,%d,%d,0x%08x)\n",
188 hdd
, hdc
, dxDst
, dyDst
, lpbi
, dxSrc
, dySrc
, wFlags
);
190 TRACE("lpbi: %ld,%ld/%ld,%d,%d,%ld,%ld,%ld,%ld,%ld,%ld\n",
191 lpbi
->biSize
, lpbi
->biWidth
, lpbi
->biHeight
, lpbi
->biPlanes
,
192 lpbi
->biBitCount
, lpbi
->biCompression
, lpbi
->biSizeImage
,
193 lpbi
->biXPelsPerMeter
, lpbi
->biYPelsPerMeter
, lpbi
->biClrUsed
,
194 lpbi
->biClrImportant
);
196 if (wFlags
& ~(DDF_BUFFER
))
197 FIXME("wFlags == 0x%08x not handled\n", wFlags
& ~(DDF_BUFFER
));
199 whdd
= MSVIDEO_GetHddPtr(hdd
);
200 if (!whdd
) return FALSE
;
202 if (whdd
->begun
) DrawDibEnd(hdd
);
204 if (lpbi
->biCompression
)
208 whdd
->hic
= ICOpen(ICTYPE_VIDEO
, lpbi
->biCompression
, ICMODE_DECOMPRESS
);
211 WARN("Could not open IC. biCompression == 0x%08lx\n", lpbi
->biCompression
);
217 size
= ICDecompressGetFormat(whdd
->hic
, lpbi
, NULL
);
218 if (size
== ICERR_UNSUPPORTED
)
220 WARN("Codec doesn't support GetFormat, giving up.\n");
227 whdd
->lpbiOut
= HeapAlloc(GetProcessHeap(), 0, size
);
229 if (ICDecompressGetFormat(whdd
->hic
, lpbi
, whdd
->lpbiOut
) != ICERR_OK
)
235 /* FIXME: Use Ex functions if available? */
236 if (ICDecompressBegin(whdd
->hic
, lpbi
, whdd
->lpbiOut
) != ICERR_OK
)
239 TRACE("biSizeImage == %ld\n", whdd
->lpbiOut
->biSizeImage
);
240 TRACE("biCompression == %ld\n", whdd
->lpbiOut
->biCompression
);
241 TRACE("biBitCount == %d\n", whdd
->lpbiOut
->biBitCount
);
248 TRACE("Not compressed!\n");
249 if (lpbi
->biHeight
<= 0)
251 /* we don't draw inverted DIBs */
252 TRACE("detected inverted DIB\n");
257 dwSize
= lpbi
->biSize
+ num_colours(lpbi
)*sizeof(RGBQUAD
);
258 whdd
->lpbiOut
= HeapAlloc(GetProcessHeap(), 0, dwSize
);
259 memcpy(whdd
->lpbiOut
, lpbi
, dwSize
);
265 /*whdd->lpvbuf = HeapAlloc(GetProcessHeap(), 0, whdd->lpbiOut->biSizeImage);*/
267 whdd
->hMemDC
= CreateCompatibleDC(hdc
);
268 TRACE("Creating: %ld, %p\n", whdd
->lpbiOut
->biSize
, whdd
->lpvbits
);
269 whdd
->hDib
= CreateDIBSection(whdd
->hMemDC
, (BITMAPINFO
*)whdd
->lpbiOut
, DIB_RGB_COLORS
, &(whdd
->lpvbits
), 0, 0);
272 TRACE("Created: %p,%p\n", whdd
->hDib
, whdd
->lpvbits
);
277 TRACE("Error: %ld\n", GetLastError());
279 whdd
->hOldDib
= SelectObject(whdd
->hMemDC
, whdd
->hDib
);
287 whdd
->lpbi
= HeapAlloc(GetProcessHeap(), 0, lpbi
->biSize
);
288 memcpy(whdd
->lpbi
, lpbi
, lpbi
->biSize
);
298 HeapFree(GetProcessHeap(), 0, whdd
->lpbiOut
);
299 whdd
->lpbiOut
= NULL
;
305 /**********************************************************************
306 * DrawDibDraw [MSVFW32.@]
308 BOOL VFWAPI
DrawDibDraw(HDRAWDIB hdd
, HDC hdc
,
309 INT xDst
, INT yDst
, INT dxDst
, INT dyDst
,
310 LPBITMAPINFOHEADER lpbi
,
312 INT xSrc
, INT ySrc
, INT dxSrc
, INT dySrc
,
319 TRACE("(%p,%p,%d,%d,%d,%d,%p,%p,%d,%d,%d,%d,0x%08x)\n",
320 hdd
, hdc
, xDst
, yDst
, dxDst
, dyDst
, lpbi
, lpBits
, xSrc
, ySrc
, dxSrc
, dySrc
, wFlags
);
322 whdd
= MSVIDEO_GetHddPtr(hdd
);
323 if (!whdd
) return FALSE
;
325 TRACE("whdd=%p\n", whdd
);
327 if (wFlags
& ~(DDF_SAME_HDC
| DDF_SAME_DRAW
| DDF_NOTKEYFRAME
| DDF_UPDATE
| DDF_DONTDRAW
| DDF_BACKGROUNDPAL
))
328 FIXME("wFlags == 0x%08x not handled\n", wFlags
);
333 lpBits
= (LPSTR
)lpbi
+ (WORD
)(lpbi
->biSize
) + (WORD
)(num_colours(lpbi
)*sizeof(RGBQUAD
));
337 #define CHANGED(x) (whdd->x != x)
339 /* Check if anything changed from the parameters passed and our struct.
340 * If anything changed we need to run DrawDibBegin again to ensure we
341 * can support the changes.
345 else if (!(wFlags
& DDF_SAME_HDC
) && CHANGED(hdc
))
347 else if (!(wFlags
& DDF_SAME_DRAW
))
349 if (CHANGED(lpbi
) && memcmp(lpbi
, whdd
->lpbi
, sizeof(*lpbi
))) reopen
= 3;
350 else if (CHANGED(dxSrc
)) reopen
= 4;
351 else if (CHANGED(dySrc
)) reopen
= 5;
352 else if (CHANGED(dxDst
)) reopen
= 6;
353 else if (CHANGED(dyDst
)) reopen
= 7;
357 TRACE("Something changed (reason %d)!\n", reopen
);
358 ret
= DrawDibBegin(hdd
, hdc
, dxDst
, dyDst
, lpbi
, dxSrc
, dySrc
, 0);
365 /* If source dimensions are not specified derive them from bitmap header */
366 if (dxSrc
== -1 && dySrc
== -1)
368 dxSrc
= lpbi
->biWidth
;
369 dySrc
= lpbi
->biHeight
;
371 /* If destination dimensions are not specified derive them from source */
372 if (dxDst
== -1 && dyDst
== -1)
378 if (!(wFlags
& DDF_UPDATE
))
380 if (lpbi
->biCompression
)
384 TRACE("Compression == 0x%08lx\n", lpbi
->biCompression
);
386 if (wFlags
& DDF_NOTKEYFRAME
)
387 flags
|= ICDECOMPRESS_NOTKEYFRAME
;
389 ICDecompress(whdd
->hic
, flags
, lpbi
, lpBits
, whdd
->lpbiOut
, whdd
->lpvbits
);
393 /* BI_RGB: lpbi->biSizeImage isn't reliable */
394 DWORD biSizeImage
= ((lpbi
->biWidth
* lpbi
->biBitCount
+ 31) / 32) * 4 * lpbi
->biHeight
;
395 memcpy(whdd
->lpvbits
, lpBits
, biSizeImage
);
398 if (!(wFlags
& DDF_DONTDRAW
) && whdd
->hpal
)
400 if ((wFlags
& DDF_BACKGROUNDPAL
) && ! (wFlags
& DDF_SAME_HDC
))
401 SelectPalette(hdc
, whdd
->hpal
, TRUE
);
403 SelectPalette(hdc
, whdd
->hpal
, FALSE
);
406 ret
= StretchBlt(whdd
->hdc
, xDst
, yDst
, dxDst
, dyDst
, whdd
->hMemDC
, xSrc
, ySrc
, dxSrc
, dySrc
, SRCCOPY
);
407 TRACE("Painting %dx%d at %d,%d from %dx%d at %d,%d -> %d\n",
408 dxDst
, dyDst
, xDst
, yDst
, dxSrc
, dySrc
, xSrc
, ySrc
, ret
);
413 /*************************************************************************
414 * DrawDibStart [MSVFW32.@]
416 BOOL VFWAPI
DrawDibStart(HDRAWDIB hdd
, DWORD rate
) {
417 FIXME("(%p, %ld), stub\n", hdd
, rate
);
421 /*************************************************************************
422 * DrawDibStop [MSVFW32.@]
424 BOOL VFWAPI
DrawDibStop(HDRAWDIB hdd
) {
425 FIXME("(%p), stub\n", hdd
);
429 /***********************************************************************
430 * DrawDibChangePalette [MSVFW32.@]
432 BOOL VFWAPI
DrawDibChangePalette(HDRAWDIB hdd
, int iStart
, int iLen
, LPPALETTEENTRY lppe
)
434 FIXME("(%p, 0x%08x, 0x%08x, %p), stub\n", hdd
, iStart
, iLen
, lppe
);
438 /***********************************************************************
439 * DrawDibSetPalette [MSVFW32.@]
441 BOOL VFWAPI
DrawDibSetPalette(HDRAWDIB hdd
, HPALETTE hpal
)
445 TRACE("(%p, %p)\n", hdd
, hpal
);
447 whdd
= MSVIDEO_GetHddPtr(hdd
);
448 if (!whdd
) return FALSE
;
454 SelectPalette(whdd
->hdc
, hpal
, 0);
455 RealizePalette(whdd
->hdc
);
461 /***********************************************************************
462 * DrawDibGetBuffer [MSVFW32.@]
464 LPVOID VFWAPI
DrawDibGetBuffer(HDRAWDIB hdd
, LPBITMAPINFOHEADER lpbi
, DWORD dwSize
, DWORD dwFlags
)
466 FIXME("(%p, %p, 0x%08lx, 0x%08lx), stub\n", hdd
, lpbi
, dwSize
, dwFlags
);
470 /***********************************************************************
471 * DrawDibGetPalette [MSVFW32.@]
473 HPALETTE VFWAPI
DrawDibGetPalette(HDRAWDIB hdd
)
477 TRACE("(%p)\n", hdd
);
479 whdd
= MSVIDEO_GetHddPtr(hdd
);
480 if (!whdd
) return FALSE
;
485 /***********************************************************************
486 * DrawDibRealize [MSVFW32.@]
488 UINT VFWAPI
DrawDibRealize(HDRAWDIB hdd
, HDC hdc
, BOOL fBackground
)
493 FIXME("(%p, %p, %d), stub\n", hdd
, hdc
, fBackground
);
495 whdd
= MSVIDEO_GetHddPtr(hdd
);
496 if (!whdd
) return FALSE
;
505 whdd
->hpal
= CreateHalftonePalette(hdc
);
507 SelectPalette(hdc
, whdd
->hpal
, fBackground
);
508 ret
= RealizePalette(hdc
);
511 TRACE("=> %u\n", ret
);
515 /***********************************************************************
516 * DrawDibTime [MSVFW32.@]
518 BOOL VFWAPI
DrawDibTime(HDRAWDIB hdd
, LPDRAWDIBTIME lpddtime
)
520 FIXME("(%p, %p) stub\n", hdd
, lpddtime
);
524 /***********************************************************************
525 * DrawDibProfileDisplay [MSVFW32.@]
527 DWORD VFWAPI
DrawDibProfileDisplay(LPBITMAPINFOHEADER lpbi
)
529 FIXME("(%p) stub\n", lpbi
);
531 return PD_CAN_DRAW_DIB
;