- RtlTimeFieldsToTime should not normalize the time fields
[wine/multimedia.git] / dlls / msvideo / drawdib.c
blobf251960c04dc62728e9ae66965abc140eb75cf01
1 /*
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * FIXME: Some flags are ignored
20 * Handle palettes
23 #include <string.h>
24 #include "msvideo_private.h"
26 #include "wingdi.h"
27 #include "winuser.h"
29 #include "wine/debug.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(msvideo);
33 typedef struct tagWINE_HDD {
34 HDC hdc;
35 INT dxDst;
36 INT dyDst;
37 LPBITMAPINFOHEADER lpbi;
38 INT dxSrc;
39 INT dySrc;
40 HPALETTE hpal; /* Palette to use for the DIB */
41 BOOL begun; /* DrawDibBegin has been called */
42 LPBITMAPINFOHEADER lpbiOut; /* Output format */
43 HIC hic; /* HIC for decompression */
44 HDC hMemDC; /* DC for buffering */
45 HBITMAP hOldDib; /* Original Dib */
46 HBITMAP hDib; /* DibSection */
47 LPVOID lpvbits; /* Buffer for holding decompressed dib */
48 HDRAWDIB hSelf;
49 struct tagWINE_HDD* next;
50 } WINE_HDD;
52 int num_colours(LPBITMAPINFOHEADER lpbi)
54 if(lpbi->biClrUsed)
55 return lpbi->biClrUsed;
56 if(lpbi->biBitCount<=8)
57 return 1<<lpbi->biBitCount;
58 return 0;
61 static WINE_HDD* HDD_FirstHdd /* = NULL */;
63 static WINE_HDD* MSVIDEO_GetHddPtr(HDRAWDIB hd)
65 WINE_HDD* hdd;
67 for (hdd = HDD_FirstHdd; hdd != NULL && hdd->hSelf != hd; hdd = hdd->next);
68 return hdd;
71 static DWORD HDD_HandleRef = 1;
73 /***********************************************************************
74 * DrawDibOpen [MSVFW32.@]
76 HDRAWDIB VFWAPI DrawDibOpen(void)
78 WINE_HDD* whdd;
80 TRACE("(void)\n");
82 whdd = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WINE_HDD));
83 TRACE("=> %p\n", whdd);
85 while (MSVIDEO_GetHddPtr((HDRAWDIB)HDD_HandleRef) != NULL) HDD_HandleRef++;
86 whdd->hSelf = (HDRAWDIB)HDD_HandleRef++;
88 whdd->next = HDD_FirstHdd;
89 HDD_FirstHdd = whdd;
91 return whdd->hSelf;
94 /***********************************************************************
95 * DrawDibClose [MSVFW32.@]
97 BOOL VFWAPI DrawDibClose(HDRAWDIB hdd)
99 WINE_HDD* whdd = MSVIDEO_GetHddPtr(hdd);
100 WINE_HDD** p;
102 TRACE("(%p)\n", hdd);
104 if (!whdd) return FALSE;
106 if (whdd->begun) DrawDibEnd(hdd);
108 for (p = &HDD_FirstHdd; *p != NULL; p = &((*p)->next))
110 if (*p == whdd)
112 *p = whdd->next;
113 break;
117 HeapFree(GetProcessHeap(), 0, whdd);
119 return TRUE;
122 /***********************************************************************
123 * DrawDibEnd [MSVFW32.@]
125 BOOL VFWAPI DrawDibEnd(HDRAWDIB hdd)
127 BOOL ret = TRUE;
128 WINE_HDD *whdd = MSVIDEO_GetHddPtr(hdd);
130 TRACE("(%p)\n", hdd);
132 whdd->hpal = 0; /* Do not free this */
133 whdd->hdc = 0;
134 if (whdd->lpbi)
136 HeapFree(GetProcessHeap(), 0, whdd->lpbi);
137 whdd->lpbi = NULL;
139 if (whdd->lpbiOut)
141 HeapFree(GetProcessHeap(), 0, whdd->lpbiOut);
142 whdd->lpbiOut = NULL;
145 whdd->begun = FALSE;
147 /*if (whdd->lpvbits)
148 HeapFree(GetProcessHeap(), 0, whdd->lpvbuf);*/
150 if (whdd->hMemDC)
152 SelectObject(whdd->hMemDC, whdd->hOldDib);
153 DeleteDC(whdd->hMemDC);
154 whdd->hMemDC = 0;
157 if (whdd->hDib) DeleteObject(whdd->hDib);
158 whdd->hDib = 0;
160 if (whdd->hic)
162 ICDecompressEnd(whdd->hic);
163 ICClose(whdd->hic);
164 whdd->hic = 0;
167 whdd->lpvbits = NULL;
169 return ret;
172 /***********************************************************************
173 * DrawDibBegin [MSVFW32.@]
175 BOOL VFWAPI DrawDibBegin(HDRAWDIB hdd,
176 HDC hdc,
177 INT dxDst,
178 INT dyDst,
179 LPBITMAPINFOHEADER lpbi,
180 INT dxSrc,
181 INT dySrc,
182 UINT wFlags)
184 BOOL ret = TRUE;
185 WINE_HDD *whdd;
187 TRACE("(%p,%p,%d,%d,%p,%d,%d,0x%08lx)\n",
188 hdd, hdc, dxDst, dyDst, lpbi, dxSrc, dySrc, (DWORD)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)
206 DWORD size = 0;
208 whdd->hic = ICOpen(ICTYPE_VIDEO, lpbi->biCompression, ICMODE_DECOMPRESS);
209 if (!whdd->hic)
211 WARN("Could not open IC. biCompression == 0x%08lx\n", lpbi->biCompression);
212 ret = FALSE;
215 if (ret)
217 size = ICDecompressGetFormat(whdd->hic, lpbi, NULL);
218 if (size == ICERR_UNSUPPORTED)
220 WARN("Codec doesn't support GetFormat, giving up.\n");
221 ret = FALSE;
225 if (ret)
227 whdd->lpbiOut = HeapAlloc(GetProcessHeap(), 0, size);
229 if (ICDecompressGetFormat(whdd->hic, lpbi, whdd->lpbiOut) != ICERR_OK)
230 ret = FALSE;
233 if (ret)
235 /* FIXME: Use Ex functions if available? */
236 if (ICDecompressBegin(whdd->hic, lpbi, whdd->lpbiOut) != ICERR_OK)
237 ret = FALSE;
239 TRACE("biSizeImage == %ld\n", whdd->lpbiOut->biSizeImage);
240 TRACE("biCompression == %ld\n", whdd->lpbiOut->biCompression);
241 TRACE("biBitCount == %d\n", whdd->lpbiOut->biBitCount);
244 else
246 DWORD dwSize;
247 /* No compression */
248 TRACE("Not compressed!\n");
249 dwSize = lpbi->biSize + num_colours(lpbi)*sizeof(RGBQUAD);
250 whdd->lpbiOut = HeapAlloc(GetProcessHeap(), 0, dwSize);
251 memcpy(whdd->lpbiOut, lpbi, dwSize);
254 if (ret)
256 /*whdd->lpvbuf = HeapAlloc(GetProcessHeap(), 0, whdd->lpbiOut->biSizeImage);*/
258 whdd->hMemDC = CreateCompatibleDC(hdc);
259 TRACE("Creating: %ld, %p\n", whdd->lpbiOut->biSize, whdd->lpvbits);
260 whdd->hDib = CreateDIBSection(whdd->hMemDC, (BITMAPINFO *)whdd->lpbiOut, DIB_RGB_COLORS, &(whdd->lpvbits), 0, 0);
261 if (!whdd->hDib)
263 TRACE("Error: %ld\n", GetLastError());
265 TRACE("Created: %p,%p\n", whdd->hDib, whdd->lpvbits);
266 whdd->hOldDib = SelectObject(whdd->hMemDC, whdd->hDib);
269 if (ret)
271 whdd->hdc = hdc;
272 whdd->dxDst = dxDst;
273 whdd->dyDst = dyDst;
274 whdd->lpbi = HeapAlloc(GetProcessHeap(), 0, lpbi->biSize);
275 memcpy(whdd->lpbi, lpbi, lpbi->biSize);
276 whdd->dxSrc = dxSrc;
277 whdd->dySrc = dySrc;
278 whdd->begun = TRUE;
279 whdd->hpal = 0;
281 else
283 if (whdd->hic)
284 ICClose(whdd->hic);
285 if (whdd->lpbiOut)
287 HeapFree(GetProcessHeap(), 0, whdd->lpbiOut);
288 whdd->lpbiOut = NULL;
292 return ret;
295 /**********************************************************************
296 * DrawDibDraw [MSVFW32.@]
298 BOOL VFWAPI DrawDibDraw(HDRAWDIB hdd, HDC hdc,
299 INT xDst, INT yDst, INT dxDst, INT dyDst,
300 LPBITMAPINFOHEADER lpbi,
301 LPVOID lpBits,
302 INT xSrc, INT ySrc, INT dxSrc, INT dySrc,
303 UINT wFlags)
305 WINE_HDD *whdd;
306 BOOL ret = TRUE;
308 TRACE("(%p,%p,%d,%d,%d,%d,%p,%p,%d,%d,%d,%d,0x%08lx)\n",
309 hdd, hdc, xDst, yDst, dxDst, dyDst, lpbi, lpBits, xSrc, ySrc, dxSrc, dySrc, (DWORD)wFlags);
311 whdd = MSVIDEO_GetHddPtr(hdd);
312 if (!whdd) return FALSE;
314 if (wFlags & ~(DDF_SAME_HDC | DDF_SAME_DRAW | DDF_NOTKEYFRAME | DDF_UPDATE | DDF_DONTDRAW | DDF_BACKGROUNDPAL))
315 FIXME("wFlags == 0x%08lx not handled\n", (DWORD)wFlags);
317 if (!lpBits)
319 /* Undocumented? */
320 lpBits = (LPSTR)lpbi + (WORD)(lpbi->biSize) + (WORD)(num_colours(lpbi)*sizeof(RGBQUAD));
324 #define CHANGED(x) (whdd->x != x)
326 if ((!whdd->begun) ||
327 (!(wFlags & DDF_SAME_HDC) && CHANGED(hdc)) ||
328 (!(wFlags & DDF_SAME_DRAW) && (CHANGED(lpbi) || CHANGED(dxSrc) || CHANGED(dySrc) || CHANGED(dxDst) || CHANGED(dyDst))))
330 TRACE("Something changed!\n");
331 ret = DrawDibBegin(hdd, hdc, dxDst, dyDst, lpbi, dxSrc, dySrc, 0);
334 #undef CHANGED
336 if ((dxDst == -1) && (dyDst == -1))
338 dxDst = dxSrc;
339 dyDst = dySrc;
342 if (!(wFlags & DDF_UPDATE))
344 /* biSizeImage may be set to 0 for BI_RGB (uncompressed) bitmaps */
345 if ((lpbi->biCompression == BI_RGB) && (lpbi->biSizeImage == 0))
346 lpbi->biSizeImage = ((lpbi->biWidth * lpbi->biBitCount + 31) / 32) * 4 * lpbi->biHeight;
348 if (lpbi->biCompression)
350 DWORD flags = 0;
352 TRACE("Compression == 0x%08lx\n", lpbi->biCompression);
354 if (wFlags & DDF_NOTKEYFRAME)
355 flags |= ICDECOMPRESS_NOTKEYFRAME;
357 ICDecompress(whdd->hic, flags, lpbi, lpBits, whdd->lpbiOut, whdd->lpvbits);
359 else
361 memcpy(whdd->lpvbits, lpBits, lpbi->biSizeImage);
364 if (!(wFlags & DDF_DONTDRAW) && whdd->hpal)
366 if ((wFlags & DDF_BACKGROUNDPAL) && ! (wFlags & DDF_SAME_HDC))
367 SelectPalette(hdc, whdd->hpal, TRUE);
368 else
369 SelectPalette(hdc, whdd->hpal, FALSE);
372 if (!(StretchBlt(whdd->hdc, xDst, yDst, dxDst, dyDst, whdd->hMemDC, xSrc, ySrc, dxSrc, dySrc, SRCCOPY)))
373 ret = FALSE;
375 return ret;
378 /*************************************************************************
379 * DrawDibStart [MSVFW32.@]
381 BOOL VFWAPI DrawDibStart(HDRAWDIB hdd, DWORD rate) {
382 FIXME("(%p, %ld), stub\n", hdd, rate);
383 return TRUE;
386 /*************************************************************************
387 * DrawDibStop [MSVFW32.@]
389 BOOL VFWAPI DrawDibStop(HDRAWDIB hdd) {
390 FIXME("(%p), stub\n", hdd);
391 return TRUE;
394 /***********************************************************************
395 * DrawDibSetPalette [MSVFW32.@]
397 BOOL VFWAPI DrawDibSetPalette(HDRAWDIB hdd, HPALETTE hpal)
399 WINE_HDD *whdd;
401 TRACE("(%p, %p)\n", hdd, hpal);
403 whdd = MSVIDEO_GetHddPtr(hdd);
404 if (!whdd) return FALSE;
406 whdd->hpal = hpal;
408 if (whdd->begun)
410 SelectPalette(whdd->hdc, hpal, 0);
411 RealizePalette(whdd->hdc);
414 return TRUE;
417 /***********************************************************************
418 * DrawDibGetPalette [MSVFW32.@]
420 HPALETTE VFWAPI DrawDibGetPalette(HDRAWDIB hdd)
422 WINE_HDD *whdd;
424 TRACE("(%p)\n", hdd);
426 whdd = MSVIDEO_GetHddPtr(hdd);
427 if (!whdd) return FALSE;
429 return whdd->hpal;
432 /***********************************************************************
433 * DrawDibRealize [MSVFW32.@]
435 UINT VFWAPI DrawDibRealize(HDRAWDIB hdd, HDC hdc, BOOL fBackground)
437 WINE_HDD *whdd;
438 HPALETTE oldPal;
439 UINT ret = 0;
441 FIXME("(%p, %p, %d), stub\n", hdd, hdc, fBackground);
443 whdd = MSVIDEO_GetHddPtr(hdd);
444 if (!whdd) return FALSE;
446 if (!whdd || !(whdd->begun))
448 ret = 0;
449 goto out;
452 if (!whdd->hpal)
453 whdd->hpal = CreateHalftonePalette(hdc);
455 oldPal = SelectPalette(hdc, whdd->hpal, fBackground);
456 ret = RealizePalette(hdc);
458 out:
459 TRACE("=> %u\n", ret);
460 return ret;
463 DWORD VFWAPI DrawDibProfileDisplay(LPBITMAPINFOHEADER lpbi)
465 FIXME("(%p) stub\n", lpbi);
467 return PD_CAN_DRAW_DIB;