msvfw32: Drawdib doesn't support inverted DIBs.
[wine/multimedia.git] / dlls / msvfw32 / drawdib.c
blob2916126fb3d71e856fb8d907ea3a7f52abfe9a68
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 UINT_PTR 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 if (!whdd) return FALSE;
138 whdd->hpal = 0; /* Do not free this */
139 whdd->hdc = 0;
140 HeapFree(GetProcessHeap(), 0, whdd->lpbi);
141 whdd->lpbi = NULL;
142 HeapFree(GetProcessHeap(), 0, whdd->lpbiOut);
143 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%08x)\n",
188 hdd, hdc, dxDst, dyDst, lpbi, dxSrc, dySrc, wFlags);
190 TRACE("lpbi: %d,%d/%d,%d,%d,%d,%d,%d,%d,%d,%d\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%08x\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 == %d\n", whdd->lpbiOut->biSizeImage);
240 TRACE("biCompression == %d\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 if (lpbi->biHeight <= 0)
251 /* we don't draw inverted DIBs */
252 TRACE("detected inverted DIB\n");
253 ret = FALSE;
255 else
257 dwSize = lpbi->biSize + num_colours(lpbi)*sizeof(RGBQUAD);
258 whdd->lpbiOut = HeapAlloc(GetProcessHeap(), 0, dwSize);
259 memcpy(whdd->lpbiOut, lpbi, dwSize);
263 if (ret)
265 /*whdd->lpvbuf = HeapAlloc(GetProcessHeap(), 0, whdd->lpbiOut->biSizeImage);*/
267 whdd->hMemDC = CreateCompatibleDC(hdc);
268 TRACE("Creating: %d, %p\n", whdd->lpbiOut->biSize, whdd->lpvbits);
269 whdd->hDib = CreateDIBSection(whdd->hMemDC, (BITMAPINFO *)whdd->lpbiOut, DIB_RGB_COLORS, &(whdd->lpvbits), 0, 0);
270 if (whdd->hDib)
272 TRACE("Created: %p,%p\n", whdd->hDib, whdd->lpvbits);
274 else
276 ret = FALSE;
277 TRACE("Error: %d\n", GetLastError());
279 whdd->hOldDib = SelectObject(whdd->hMemDC, whdd->hDib);
282 if (ret)
284 whdd->hdc = hdc;
285 whdd->dxDst = dxDst;
286 whdd->dyDst = dyDst;
287 whdd->lpbi = HeapAlloc(GetProcessHeap(), 0, lpbi->biSize);
288 memcpy(whdd->lpbi, lpbi, lpbi->biSize);
289 whdd->dxSrc = dxSrc;
290 whdd->dySrc = dySrc;
291 whdd->begun = TRUE;
292 whdd->hpal = 0;
294 else
296 if (whdd->hic)
297 ICClose(whdd->hic);
298 HeapFree(GetProcessHeap(), 0, whdd->lpbiOut);
299 whdd->lpbiOut = NULL;
302 return ret;
305 /**********************************************************************
306 * DrawDibDraw [MSVFW32.@]
308 BOOL VFWAPI DrawDibDraw(HDRAWDIB hdd, HDC hdc,
309 INT xDst, INT yDst, INT dxDst, INT dyDst,
310 LPBITMAPINFOHEADER lpbi,
311 LPVOID lpBits,
312 INT xSrc, INT ySrc, INT dxSrc, INT dySrc,
313 UINT wFlags)
315 WINE_HDD *whdd;
316 BOOL ret = TRUE;
318 TRACE("(%p,%p,%d,%d,%d,%d,%p,%p,%d,%d,%d,%d,0x%08x)\n",
319 hdd, hdc, xDst, yDst, dxDst, dyDst, lpbi, lpBits, xSrc, ySrc, dxSrc, dySrc, wFlags);
321 whdd = MSVIDEO_GetHddPtr(hdd);
322 if (!whdd) return FALSE;
324 TRACE("whdd=%p\n", whdd);
326 if (wFlags & ~(DDF_SAME_HDC | DDF_SAME_DRAW | DDF_NOTKEYFRAME | DDF_UPDATE | DDF_DONTDRAW | DDF_BACKGROUNDPAL))
327 FIXME("wFlags == 0x%08x not handled\n", wFlags);
329 if (!lpBits)
331 /* Undocumented? */
332 lpBits = (LPSTR)lpbi + (WORD)(lpbi->biSize) + (WORD)(num_colours(lpbi)*sizeof(RGBQUAD));
336 #define CHANGED(x) (whdd->x != x)
338 if ((!whdd->begun) ||
339 (!(wFlags & DDF_SAME_HDC) && CHANGED(hdc)) ||
340 (!(wFlags & DDF_SAME_DRAW) && (CHANGED(lpbi) || CHANGED(dxSrc) || CHANGED(dySrc) || CHANGED(dxDst) || CHANGED(dyDst))))
342 TRACE("Something changed!\n");
343 ret = DrawDibBegin(hdd, hdc, dxDst, dyDst, lpbi, dxSrc, dySrc, 0);
344 if (!ret)
345 return ret;
348 #undef CHANGED
350 if ((dxDst == -1) && (dyDst == -1))
352 dxDst = dxSrc;
353 dyDst = dySrc;
356 if (!(wFlags & DDF_UPDATE))
358 DWORD biSizeImage = lpbi->biSizeImage;
360 /* biSizeImage may be set to 0 for BI_RGB (uncompressed) bitmaps */
361 if ((lpbi->biCompression == BI_RGB) && (biSizeImage == 0))
362 biSizeImage = ((lpbi->biWidth * lpbi->biBitCount + 31) / 32) * 4 * lpbi->biHeight;
364 if (lpbi->biCompression)
366 DWORD flags = 0;
368 TRACE("Compression == 0x%08x\n", lpbi->biCompression);
370 if (wFlags & DDF_NOTKEYFRAME)
371 flags |= ICDECOMPRESS_NOTKEYFRAME;
373 ICDecompress(whdd->hic, flags, lpbi, lpBits, whdd->lpbiOut, whdd->lpvbits);
375 else
377 memcpy(whdd->lpvbits, lpBits, biSizeImage);
380 if (!(wFlags & DDF_DONTDRAW) && whdd->hpal)
382 if ((wFlags & DDF_BACKGROUNDPAL) && ! (wFlags & DDF_SAME_HDC))
383 SelectPalette(hdc, whdd->hpal, TRUE);
384 else
385 SelectPalette(hdc, whdd->hpal, FALSE);
388 if (!(StretchBlt(whdd->hdc, xDst, yDst, dxDst, dyDst, whdd->hMemDC, xSrc, ySrc, dxSrc, dySrc, SRCCOPY)))
389 ret = FALSE;
391 return ret;
394 /*************************************************************************
395 * DrawDibStart [MSVFW32.@]
397 BOOL VFWAPI DrawDibStart(HDRAWDIB hdd, DWORD rate) {
398 FIXME("(%p, %d), stub\n", hdd, rate);
399 return TRUE;
402 /*************************************************************************
403 * DrawDibStop [MSVFW32.@]
405 BOOL VFWAPI DrawDibStop(HDRAWDIB hdd) {
406 FIXME("(%p), stub\n", hdd);
407 return TRUE;
410 /***********************************************************************
411 * DrawDibChangePalette [MSVFW32.@]
413 BOOL VFWAPI DrawDibChangePalette(HDRAWDIB hdd, int iStart, int iLen, LPPALETTEENTRY lppe)
415 FIXME("(%p, 0x%08x, 0x%08x, %p), stub\n", hdd, iStart, iLen, lppe);
416 return TRUE;
419 /***********************************************************************
420 * DrawDibSetPalette [MSVFW32.@]
422 BOOL VFWAPI DrawDibSetPalette(HDRAWDIB hdd, HPALETTE hpal)
424 WINE_HDD *whdd;
426 TRACE("(%p, %p)\n", hdd, hpal);
428 whdd = MSVIDEO_GetHddPtr(hdd);
429 if (!whdd) return FALSE;
431 whdd->hpal = hpal;
433 if (whdd->begun)
435 SelectPalette(whdd->hdc, hpal, 0);
436 RealizePalette(whdd->hdc);
439 return TRUE;
442 /***********************************************************************
443 * DrawDibGetBuffer [MSVFW32.@]
445 LPVOID VFWAPI DrawDibGetBuffer(HDRAWDIB hdd, LPBITMAPINFOHEADER lpbi, DWORD dwSize, DWORD dwFlags)
447 FIXME("(%p, %p, 0x%08x, 0x%08x), stub\n", hdd, lpbi, dwSize, dwFlags);
448 return NULL;
451 /***********************************************************************
452 * DrawDibGetPalette [MSVFW32.@]
454 HPALETTE VFWAPI DrawDibGetPalette(HDRAWDIB hdd)
456 WINE_HDD *whdd;
458 TRACE("(%p)\n", hdd);
460 whdd = MSVIDEO_GetHddPtr(hdd);
461 if (!whdd) return FALSE;
463 return whdd->hpal;
466 /***********************************************************************
467 * DrawDibRealize [MSVFW32.@]
469 UINT VFWAPI DrawDibRealize(HDRAWDIB hdd, HDC hdc, BOOL fBackground)
471 WINE_HDD *whdd;
472 UINT ret = 0;
474 FIXME("(%p, %p, %d), stub\n", hdd, hdc, fBackground);
476 whdd = MSVIDEO_GetHddPtr(hdd);
477 if (!whdd) return FALSE;
479 if (!whdd || !(whdd->begun))
481 ret = 0;
482 goto out;
485 if (!whdd->hpal)
486 whdd->hpal = CreateHalftonePalette(hdc);
488 SelectPalette(hdc, whdd->hpal, fBackground);
489 ret = RealizePalette(hdc);
491 out:
492 TRACE("=> %u\n", ret);
493 return ret;
496 /***********************************************************************
497 * DrawDibTime [MSVFW32.@]
499 BOOL VFWAPI DrawDibTime(HDRAWDIB hdd, LPDRAWDIBTIME lpddtime)
501 FIXME("(%p, %p) stub\n", hdd, lpddtime);
502 return FALSE;
505 /***********************************************************************
506 * DrawDibProfileDisplay [MSVFW32.@]
508 DWORD VFWAPI DrawDibProfileDisplay(LPBITMAPINFOHEADER lpbi)
510 FIXME("(%p) stub\n", lpbi);
512 return PD_CAN_DRAW_DIB;