quartz: Make filtergraph aggregatable.
[wine/multimedia.git] / dlls / msvfw32 / drawdib.c
blob734f0e20b49f30a7736b415b13632a4c199effe6
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 * FIXME: Some flags are ignored
20 * Handle palettes
23 #include <stdarg.h>
24 #include <stdio.h>
25 #include <string.h>
27 #include "windef.h"
28 #include "winbase.h"
29 #include "wingdi.h"
30 #include "winuser.h"
31 #include "vfw.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(msvideo);
37 typedef struct tagWINE_HDD {
38 HDC hdc;
39 INT dxDst;
40 INT dyDst;
41 LPBITMAPINFOHEADER lpbi;
42 INT dxSrc;
43 INT dySrc;
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 */
52 HDRAWDIB hSelf;
53 struct tagWINE_HDD* next;
54 } WINE_HDD;
56 static int num_colours(const BITMAPINFOHEADER *lpbi)
58 if(lpbi->biClrUsed)
59 return lpbi->biClrUsed;
60 if(lpbi->biBitCount<=8)
61 return 1<<lpbi->biBitCount;
62 return 0;
65 static WINE_HDD* HDD_FirstHdd /* = NULL */;
67 static WINE_HDD* MSVIDEO_GetHddPtr(HDRAWDIB hd)
69 WINE_HDD* hdd;
71 for (hdd = HDD_FirstHdd; hdd != NULL && hdd->hSelf != hd; hdd = hdd->next);
72 return hdd;
75 static DWORD HDD_HandleRef = 1;
77 /***********************************************************************
78 * DrawDibOpen [MSVFW32.@]
80 HDRAWDIB VFWAPI DrawDibOpen(void)
82 WINE_HDD* whdd;
84 TRACE("(void)\n");
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;
93 HDD_FirstHdd = whdd;
95 return whdd->hSelf;
98 /***********************************************************************
99 * DrawDibClose [MSVFW32.@]
101 BOOL VFWAPI DrawDibClose(HDRAWDIB hdd)
103 WINE_HDD* whdd = MSVIDEO_GetHddPtr(hdd);
104 WINE_HDD** p;
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))
114 if (*p == whdd)
116 *p = whdd->next;
117 break;
121 HeapFree(GetProcessHeap(), 0, whdd);
123 return TRUE;
126 /***********************************************************************
127 * DrawDibEnd [MSVFW32.@]
129 BOOL VFWAPI DrawDibEnd(HDRAWDIB hdd)
131 BOOL ret = TRUE;
132 WINE_HDD *whdd = MSVIDEO_GetHddPtr(hdd);
134 TRACE("(%p)\n", hdd);
136 whdd->hpal = 0; /* Do not free this */
137 whdd->hdc = 0;
138 HeapFree(GetProcessHeap(), 0, whdd->lpbi);
139 whdd->lpbi = NULL;
140 HeapFree(GetProcessHeap(), 0, whdd->lpbiOut);
141 whdd->lpbiOut = NULL;
143 whdd->begun = FALSE;
145 /*if (whdd->lpvbits)
146 HeapFree(GetProcessHeap(), 0, whdd->lpvbuf);*/
148 if (whdd->hMemDC)
150 SelectObject(whdd->hMemDC, whdd->hOldDib);
151 DeleteDC(whdd->hMemDC);
152 whdd->hMemDC = 0;
155 if (whdd->hDib) DeleteObject(whdd->hDib);
156 whdd->hDib = 0;
158 if (whdd->hic)
160 ICDecompressEnd(whdd->hic);
161 ICClose(whdd->hic);
162 whdd->hic = 0;
165 whdd->lpvbits = NULL;
167 return ret;
170 /***********************************************************************
171 * DrawDibBegin [MSVFW32.@]
173 BOOL VFWAPI DrawDibBegin(HDRAWDIB hdd,
174 HDC hdc,
175 INT dxDst,
176 INT dyDst,
177 LPBITMAPINFOHEADER lpbi,
178 INT dxSrc,
179 INT dySrc,
180 UINT wFlags)
182 BOOL ret = TRUE;
183 WINE_HDD *whdd;
185 TRACE("(%p,%p,%d,%d,%p,%d,%d,0x%08x)\n",
186 hdd, hdc, dxDst, dyDst, lpbi, dxSrc, dySrc, (DWORD)wFlags);
188 TRACE("lpbi: %d,%d/%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
189 lpbi->biSize, lpbi->biWidth, lpbi->biHeight, lpbi->biPlanes,
190 lpbi->biBitCount, lpbi->biCompression, lpbi->biSizeImage,
191 lpbi->biXPelsPerMeter, lpbi->biYPelsPerMeter, lpbi->biClrUsed,
192 lpbi->biClrImportant);
194 if (wFlags & ~(DDF_BUFFER))
195 FIXME("wFlags == 0x%08x not handled\n", wFlags & ~(DDF_BUFFER));
197 whdd = MSVIDEO_GetHddPtr(hdd);
198 if (!whdd) return FALSE;
200 if (whdd->begun) DrawDibEnd(hdd);
202 if (lpbi->biCompression)
204 DWORD size = 0;
206 whdd->hic = ICOpen(ICTYPE_VIDEO, lpbi->biCompression, ICMODE_DECOMPRESS);
207 if (!whdd->hic)
209 WARN("Could not open IC. biCompression == 0x%08x\n", lpbi->biCompression);
210 ret = FALSE;
213 if (ret)
215 size = ICDecompressGetFormat(whdd->hic, lpbi, NULL);
216 if (size == ICERR_UNSUPPORTED)
218 WARN("Codec doesn't support GetFormat, giving up.\n");
219 ret = FALSE;
223 if (ret)
225 whdd->lpbiOut = HeapAlloc(GetProcessHeap(), 0, size);
227 if (ICDecompressGetFormat(whdd->hic, lpbi, whdd->lpbiOut) != ICERR_OK)
228 ret = FALSE;
231 if (ret)
233 /* FIXME: Use Ex functions if available? */
234 if (ICDecompressBegin(whdd->hic, lpbi, whdd->lpbiOut) != ICERR_OK)
235 ret = FALSE;
237 TRACE("biSizeImage == %d\n", whdd->lpbiOut->biSizeImage);
238 TRACE("biCompression == %d\n", whdd->lpbiOut->biCompression);
239 TRACE("biBitCount == %d\n", whdd->lpbiOut->biBitCount);
242 else
244 DWORD dwSize;
245 /* No compression */
246 TRACE("Not compressed!\n");
247 dwSize = lpbi->biSize + num_colours(lpbi)*sizeof(RGBQUAD);
248 whdd->lpbiOut = HeapAlloc(GetProcessHeap(), 0, dwSize);
249 memcpy(whdd->lpbiOut, lpbi, dwSize);
252 if (ret)
254 /*whdd->lpvbuf = HeapAlloc(GetProcessHeap(), 0, whdd->lpbiOut->biSizeImage);*/
256 whdd->hMemDC = CreateCompatibleDC(hdc);
257 TRACE("Creating: %d, %p\n", whdd->lpbiOut->biSize, whdd->lpvbits);
258 whdd->hDib = CreateDIBSection(whdd->hMemDC, (BITMAPINFO *)whdd->lpbiOut, DIB_RGB_COLORS, &(whdd->lpvbits), 0, 0);
259 if (whdd->hDib)
261 TRACE("Created: %p,%p\n", whdd->hDib, whdd->lpvbits);
263 else
265 ret = FALSE;
266 TRACE("Error: %d\n", GetLastError());
268 whdd->hOldDib = SelectObject(whdd->hMemDC, whdd->hDib);
271 if (ret)
273 whdd->hdc = hdc;
274 whdd->dxDst = dxDst;
275 whdd->dyDst = dyDst;
276 whdd->lpbi = HeapAlloc(GetProcessHeap(), 0, lpbi->biSize);
277 memcpy(whdd->lpbi, lpbi, lpbi->biSize);
278 whdd->dxSrc = dxSrc;
279 whdd->dySrc = dySrc;
280 whdd->begun = TRUE;
281 whdd->hpal = 0;
283 else
285 if (whdd->hic)
286 ICClose(whdd->hic);
287 HeapFree(GetProcessHeap(), 0, whdd->lpbiOut);
288 whdd->lpbiOut = NULL;
291 return ret;
294 /**********************************************************************
295 * DrawDibDraw [MSVFW32.@]
297 BOOL VFWAPI DrawDibDraw(HDRAWDIB hdd, HDC hdc,
298 INT xDst, INT yDst, INT dxDst, INT dyDst,
299 LPBITMAPINFOHEADER lpbi,
300 LPVOID lpBits,
301 INT xSrc, INT ySrc, INT dxSrc, INT dySrc,
302 UINT wFlags)
304 WINE_HDD *whdd;
305 BOOL ret = TRUE;
307 TRACE("(%p,%p,%d,%d,%d,%d,%p,%p,%d,%d,%d,%d,0x%08x)\n",
308 hdd, hdc, xDst, yDst, dxDst, dyDst, lpbi, lpBits, xSrc, ySrc, dxSrc, dySrc, (DWORD)wFlags);
310 whdd = MSVIDEO_GetHddPtr(hdd);
311 if (!whdd) return FALSE;
313 TRACE("whdd=%p\n", whdd);
315 if (wFlags & ~(DDF_SAME_HDC | DDF_SAME_DRAW | DDF_NOTKEYFRAME | DDF_UPDATE | DDF_DONTDRAW | DDF_BACKGROUNDPAL))
316 FIXME("wFlags == 0x%08x not handled\n", (DWORD)wFlags);
318 if (!lpBits)
320 /* Undocumented? */
321 lpBits = (LPSTR)lpbi + (WORD)(lpbi->biSize) + (WORD)(num_colours(lpbi)*sizeof(RGBQUAD));
325 #define CHANGED(x) (whdd->x != x)
327 if ((!whdd->begun) ||
328 (!(wFlags & DDF_SAME_HDC) && CHANGED(hdc)) ||
329 (!(wFlags & DDF_SAME_DRAW) && (CHANGED(lpbi) || CHANGED(dxSrc) || CHANGED(dySrc) || CHANGED(dxDst) || CHANGED(dyDst))))
331 TRACE("Something changed!\n");
332 ret = DrawDibBegin(hdd, hdc, dxDst, dyDst, lpbi, dxSrc, dySrc, 0);
335 #undef CHANGED
337 if ((dxDst == -1) && (dyDst == -1))
339 dxDst = dxSrc;
340 dyDst = dySrc;
343 if (!(wFlags & DDF_UPDATE))
345 DWORD biSizeImage = lpbi->biSizeImage;
347 /* biSizeImage may be set to 0 for BI_RGB (uncompressed) bitmaps */
348 if ((lpbi->biCompression == BI_RGB) && (biSizeImage == 0))
349 biSizeImage = ((lpbi->biWidth * lpbi->biBitCount + 31) / 32) * 4 * lpbi->biHeight;
351 if (lpbi->biCompression)
353 DWORD flags = 0;
355 TRACE("Compression == 0x%08x\n", lpbi->biCompression);
357 if (wFlags & DDF_NOTKEYFRAME)
358 flags |= ICDECOMPRESS_NOTKEYFRAME;
360 ICDecompress(whdd->hic, flags, lpbi, lpBits, whdd->lpbiOut, whdd->lpvbits);
362 else
364 memcpy(whdd->lpvbits, lpBits, biSizeImage);
367 if (!(wFlags & DDF_DONTDRAW) && whdd->hpal)
369 if ((wFlags & DDF_BACKGROUNDPAL) && ! (wFlags & DDF_SAME_HDC))
370 SelectPalette(hdc, whdd->hpal, TRUE);
371 else
372 SelectPalette(hdc, whdd->hpal, FALSE);
375 if (!(StretchBlt(whdd->hdc, xDst, yDst, dxDst, dyDst, whdd->hMemDC, xSrc, ySrc, dxSrc, dySrc, SRCCOPY)))
376 ret = FALSE;
378 return ret;
381 /*************************************************************************
382 * DrawDibStart [MSVFW32.@]
384 BOOL VFWAPI DrawDibStart(HDRAWDIB hdd, DWORD rate) {
385 FIXME("(%p, %d), stub\n", hdd, rate);
386 return TRUE;
389 /*************************************************************************
390 * DrawDibStop [MSVFW32.@]
392 BOOL VFWAPI DrawDibStop(HDRAWDIB hdd) {
393 FIXME("(%p), stub\n", hdd);
394 return TRUE;
397 /***********************************************************************
398 * DrawDibChangePalette [MSVFW32.@]
400 BOOL VFWAPI DrawDibChangePalette(HDRAWDIB hdd, int iStart, int iLen, LPPALETTEENTRY lppe)
402 FIXME("(%p, 0x%08x, 0x%08x, %p), stub\n", hdd, iStart, iLen, lppe);
403 return TRUE;
406 /***********************************************************************
407 * DrawDibSetPalette [MSVFW32.@]
409 BOOL VFWAPI DrawDibSetPalette(HDRAWDIB hdd, HPALETTE hpal)
411 WINE_HDD *whdd;
413 TRACE("(%p, %p)\n", hdd, hpal);
415 whdd = MSVIDEO_GetHddPtr(hdd);
416 if (!whdd) return FALSE;
418 whdd->hpal = hpal;
420 if (whdd->begun)
422 SelectPalette(whdd->hdc, hpal, 0);
423 RealizePalette(whdd->hdc);
426 return TRUE;
429 /***********************************************************************
430 * DrawDibGetBuffer [MSVFW32.@]
432 LPVOID VFWAPI DrawDibGetBuffer(HDRAWDIB hdd, LPBITMAPINFOHEADER lpbi, DWORD dwSize, DWORD dwFlags)
434 FIXME("(%p, %p, 0x%08x, 0x%08x), stub\n", hdd, lpbi, dwSize, dwFlags);
435 return NULL;
438 /***********************************************************************
439 * DrawDibGetPalette [MSVFW32.@]
441 HPALETTE VFWAPI DrawDibGetPalette(HDRAWDIB hdd)
443 WINE_HDD *whdd;
445 TRACE("(%p)\n", hdd);
447 whdd = MSVIDEO_GetHddPtr(hdd);
448 if (!whdd) return FALSE;
450 return whdd->hpal;
453 /***********************************************************************
454 * DrawDibRealize [MSVFW32.@]
456 UINT VFWAPI DrawDibRealize(HDRAWDIB hdd, HDC hdc, BOOL fBackground)
458 WINE_HDD *whdd;
459 HPALETTE oldPal;
460 UINT ret = 0;
462 FIXME("(%p, %p, %d), stub\n", hdd, hdc, fBackground);
464 whdd = MSVIDEO_GetHddPtr(hdd);
465 if (!whdd) return FALSE;
467 if (!whdd || !(whdd->begun))
469 ret = 0;
470 goto out;
473 if (!whdd->hpal)
474 whdd->hpal = CreateHalftonePalette(hdc);
476 oldPal = SelectPalette(hdc, whdd->hpal, fBackground);
477 ret = RealizePalette(hdc);
479 out:
480 TRACE("=> %u\n", ret);
481 return ret;
484 /***********************************************************************
485 * DrawDibTime [MSVFW32.@]
487 BOOL VFWAPI DrawDibTime(HDRAWDIB hdd, LPDRAWDIBTIME lpddtime)
489 FIXME("(%p, %p) stub\n", hdd, lpddtime);
490 return FALSE;
493 /***********************************************************************
494 * DrawDibProfileDisplay [MSVFW32.@]
496 DWORD VFWAPI DrawDibProfileDisplay(LPBITMAPINFOHEADER lpbi)
498 FIXME("(%p) stub\n", lpbi);
500 return PD_CAN_DRAW_DIB;