* Sync to trunk r63845.
[reactos.git] / dll / win32 / msvfw32 / drawdib.c
1 /*
2 * Copyright 2000 Bradley Baetz
3 *
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.
8 *
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.
13 *
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
17 *
18 * FIXME: Some flags are ignored
19 *
20 * Handle palettes
21 */
22
23 #include "msvideo_private.h"
24
25 WINE_DEFAULT_DEBUG_CHANNEL(msvideo);
26
27 typedef struct tagWINE_HDD {
28 HDC hdc;
29 INT dxDst;
30 INT dyDst;
31 LPBITMAPINFOHEADER lpbi;
32 INT dxSrc;
33 INT dySrc;
34 HPALETTE hpal; /* Palette to use for the DIB */
35 BOOL begun; /* DrawDibBegin has been called */
36 LPBITMAPINFOHEADER lpbiOut; /* Output format */
37 HIC hic; /* HIC for decompression */
38 HDC hMemDC; /* DC for buffering */
39 HBITMAP hOldDib; /* Original Dib */
40 HBITMAP hDib; /* DibSection */
41 LPVOID lpvbits; /* Buffer for holding decompressed dib */
42 HDRAWDIB hSelf;
43 struct tagWINE_HDD* next;
44 } WINE_HDD;
45
46 static int num_colours(const BITMAPINFOHEADER *lpbi)
47 {
48 if(lpbi->biClrUsed)
49 return lpbi->biClrUsed;
50 if(lpbi->biBitCount<=8)
51 return 1<<lpbi->biBitCount;
52 return 0;
53 }
54
55 static WINE_HDD* HDD_FirstHdd /* = NULL */;
56
57 static WINE_HDD* MSVIDEO_GetHddPtr(HDRAWDIB hd)
58 {
59 WINE_HDD* hdd;
60
61 for (hdd = HDD_FirstHdd; hdd != NULL && hdd->hSelf != hd; hdd = hdd->next);
62 return hdd;
63 }
64
65 static UINT_PTR HDD_HandleRef = 1;
66
67 /***********************************************************************
68 * DrawDibOpen [MSVFW32.@]
69 */
70 HDRAWDIB VFWAPI DrawDibOpen(void)
71 {
72 WINE_HDD* whdd;
73
74 TRACE("(void)\n");
75
76 whdd = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WINE_HDD));
77 TRACE("=> %p\n", whdd);
78
79 while (MSVIDEO_GetHddPtr((HDRAWDIB)HDD_HandleRef) != NULL) HDD_HandleRef++;
80 whdd->hSelf = (HDRAWDIB)HDD_HandleRef++;
81
82 whdd->next = HDD_FirstHdd;
83 HDD_FirstHdd = whdd;
84
85 return whdd->hSelf;
86 }
87
88 /***********************************************************************
89 * DrawDibClose [MSVFW32.@]
90 */
91 BOOL VFWAPI DrawDibClose(HDRAWDIB hdd)
92 {
93 WINE_HDD* whdd = MSVIDEO_GetHddPtr(hdd);
94 WINE_HDD** p;
95
96 TRACE("(%p)\n", hdd);
97
98 if (!whdd) return FALSE;
99
100 if (whdd->begun) DrawDibEnd(hdd);
101
102 for (p = &HDD_FirstHdd; *p != NULL; p = &((*p)->next))
103 {
104 if (*p == whdd)
105 {
106 *p = whdd->next;
107 break;
108 }
109 }
110
111 HeapFree(GetProcessHeap(), 0, whdd);
112
113 return TRUE;
114 }
115
116 /***********************************************************************
117 * DrawDibEnd [MSVFW32.@]
118 */
119 BOOL VFWAPI DrawDibEnd(HDRAWDIB hdd)
120 {
121 BOOL ret = TRUE;
122 WINE_HDD *whdd = MSVIDEO_GetHddPtr(hdd);
123
124 TRACE("(%p)\n", hdd);
125
126 if (!whdd) return FALSE;
127
128 whdd->hpal = 0; /* Do not free this */
129 whdd->hdc = 0;
130 HeapFree(GetProcessHeap(), 0, whdd->lpbi);
131 whdd->lpbi = NULL;
132 HeapFree(GetProcessHeap(), 0, whdd->lpbiOut);
133 whdd->lpbiOut = NULL;
134
135 whdd->begun = FALSE;
136
137 /*if (whdd->lpvbits)
138 HeapFree(GetProcessHeap(), 0, whdd->lpvbuf);*/
139
140 if (whdd->hMemDC)
141 {
142 SelectObject(whdd->hMemDC, whdd->hOldDib);
143 DeleteDC(whdd->hMemDC);
144 whdd->hMemDC = 0;
145 }
146
147 if (whdd->hDib) DeleteObject(whdd->hDib);
148 whdd->hDib = 0;
149
150 if (whdd->hic)
151 {
152 ICDecompressEnd(whdd->hic);
153 ICClose(whdd->hic);
154 whdd->hic = 0;
155 }
156
157 whdd->lpvbits = NULL;
158
159 return ret;
160 }
161
162 /***********************************************************************
163 * DrawDibBegin [MSVFW32.@]
164 */
165 BOOL VFWAPI DrawDibBegin(HDRAWDIB hdd,
166 HDC hdc,
167 INT dxDst,
168 INT dyDst,
169 LPBITMAPINFOHEADER lpbi,
170 INT dxSrc,
171 INT dySrc,
172 UINT wFlags)
173 {
174 BOOL ret = TRUE;
175 WINE_HDD *whdd;
176
177 TRACE("(%p,%p,%d,%d,%p,%d,%d,0x%08x)\n",
178 hdd, hdc, dxDst, dyDst, lpbi, dxSrc, dySrc, wFlags);
179
180 TRACE("lpbi: %d,%d/%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
181 lpbi->biSize, lpbi->biWidth, lpbi->biHeight, lpbi->biPlanes,
182 lpbi->biBitCount, lpbi->biCompression, lpbi->biSizeImage,
183 lpbi->biXPelsPerMeter, lpbi->biYPelsPerMeter, lpbi->biClrUsed,
184 lpbi->biClrImportant);
185
186 if (wFlags & ~(DDF_BUFFER))
187 FIXME("wFlags == 0x%08x not handled\n", wFlags & ~(DDF_BUFFER));
188
189 whdd = MSVIDEO_GetHddPtr(hdd);
190 if (!whdd) return FALSE;
191
192 if (whdd->begun) DrawDibEnd(hdd);
193
194 if (lpbi->biCompression)
195 {
196 DWORD size = 0;
197
198 whdd->hic = ICOpen(ICTYPE_VIDEO, lpbi->biCompression, ICMODE_DECOMPRESS);
199 if (!whdd->hic)
200 {
201 WARN("Could not open IC. biCompression == 0x%08x\n", lpbi->biCompression);
202 ret = FALSE;
203 }
204
205 if (ret)
206 {
207 size = ICDecompressGetFormat(whdd->hic, lpbi, NULL);
208 if (size == ICERR_UNSUPPORTED)
209 {
210 WARN("Codec doesn't support GetFormat, giving up.\n");
211 ret = FALSE;
212 }
213 }
214
215 if (ret)
216 {
217 whdd->lpbiOut = HeapAlloc(GetProcessHeap(), 0, size);
218
219 if (ICDecompressGetFormat(whdd->hic, lpbi, whdd->lpbiOut) != ICERR_OK)
220 ret = FALSE;
221 }
222
223 if (ret)
224 {
225 /* FIXME: Use Ex functions if available? */
226 if (ICDecompressBegin(whdd->hic, lpbi, whdd->lpbiOut) != ICERR_OK)
227 ret = FALSE;
228
229 TRACE("biSizeImage == %d\n", whdd->lpbiOut->biSizeImage);
230 TRACE("biCompression == %d\n", whdd->lpbiOut->biCompression);
231 TRACE("biBitCount == %d\n", whdd->lpbiOut->biBitCount);
232 }
233 }
234 else
235 {
236 DWORD dwSize;
237 /* No compression */
238 TRACE("Not compressed!\n");
239 dwSize = lpbi->biSize + num_colours(lpbi)*sizeof(RGBQUAD);
240 whdd->lpbiOut = HeapAlloc(GetProcessHeap(), 0, dwSize);
241 memcpy(whdd->lpbiOut, lpbi, dwSize);
242 }
243
244 if (ret)
245 {
246 /*whdd->lpvbuf = HeapAlloc(GetProcessHeap(), 0, whdd->lpbiOut->biSizeImage);*/
247
248 whdd->hMemDC = CreateCompatibleDC(hdc);
249 TRACE("Creating: %d, %p\n", whdd->lpbiOut->biSize, whdd->lpvbits);
250 whdd->hDib = CreateDIBSection(whdd->hMemDC, (BITMAPINFO *)whdd->lpbiOut, DIB_RGB_COLORS, &(whdd->lpvbits), 0, 0);
251 if (whdd->hDib)
252 {
253 TRACE("Created: %p,%p\n", whdd->hDib, whdd->lpvbits);
254 }
255 else
256 {
257 ret = FALSE;
258 TRACE("Error: %d\n", GetLastError());
259 }
260 whdd->hOldDib = SelectObject(whdd->hMemDC, whdd->hDib);
261 }
262
263 if (ret)
264 {
265 whdd->hdc = hdc;
266 whdd->dxDst = dxDst;
267 whdd->dyDst = dyDst;
268 whdd->lpbi = HeapAlloc(GetProcessHeap(), 0, lpbi->biSize);
269 memcpy(whdd->lpbi, lpbi, lpbi->biSize);
270 whdd->dxSrc = dxSrc;
271 whdd->dySrc = dySrc;
272 whdd->begun = TRUE;
273 whdd->hpal = 0;
274 }
275 else
276 {
277 if (whdd->hic)
278 ICClose(whdd->hic);
279 HeapFree(GetProcessHeap(), 0, whdd->lpbiOut);
280 whdd->lpbiOut = NULL;
281 }
282
283 return ret;
284 }
285
286 /**********************************************************************
287 * DrawDibDraw [MSVFW32.@]
288 */
289 BOOL VFWAPI DrawDibDraw(HDRAWDIB hdd, HDC hdc,
290 INT xDst, INT yDst, INT dxDst, INT dyDst,
291 LPBITMAPINFOHEADER lpbi,
292 LPVOID lpBits,
293 INT xSrc, INT ySrc, INT dxSrc, INT dySrc,
294 UINT wFlags)
295 {
296 WINE_HDD *whdd;
297 BOOL ret = TRUE;
298
299 TRACE("(%p,%p,%d,%d,%d,%d,%p,%p,%d,%d,%d,%d,0x%08x)\n",
300 hdd, hdc, xDst, yDst, dxDst, dyDst, lpbi, lpBits, xSrc, ySrc, dxSrc, dySrc, wFlags);
301
302 whdd = MSVIDEO_GetHddPtr(hdd);
303 if (!whdd) return FALSE;
304
305 TRACE("whdd=%p\n", whdd);
306
307 if (wFlags & ~(DDF_SAME_HDC | DDF_SAME_DRAW | DDF_NOTKEYFRAME | DDF_UPDATE | DDF_DONTDRAW | DDF_BACKGROUNDPAL))
308 FIXME("wFlags == 0x%08x not handled\n", wFlags);
309
310 if (!lpBits)
311 {
312 /* Undocumented? */
313 lpBits = (LPSTR)lpbi + (WORD)(lpbi->biSize) + (WORD)(num_colours(lpbi)*sizeof(RGBQUAD));
314 }
315
316
317 #define CHANGED(x) (whdd->x != x)
318
319 if ((!whdd->begun) ||
320 (!(wFlags & DDF_SAME_HDC) && CHANGED(hdc)) ||
321 (!(wFlags & DDF_SAME_DRAW) && (CHANGED(lpbi) || CHANGED(dxSrc) || CHANGED(dySrc) || CHANGED(dxDst) || CHANGED(dyDst))))
322 {
323 TRACE("Something changed!\n");
324 ret = DrawDibBegin(hdd, hdc, dxDst, dyDst, lpbi, dxSrc, dySrc, 0);
325 }
326
327 #undef CHANGED
328
329 if ((dxDst == -1) && (dyDst == -1))
330 {
331 dxDst = dxSrc;
332 dyDst = dySrc;
333 }
334
335 if (!(wFlags & DDF_UPDATE))
336 {
337 DWORD biSizeImage = lpbi->biSizeImage;
338
339 /* biSizeImage may be set to 0 for BI_RGB (uncompressed) bitmaps */
340 if ((lpbi->biCompression == BI_RGB) && (biSizeImage == 0))
341 biSizeImage = ((lpbi->biWidth * lpbi->biBitCount + 31) / 32) * 4 * lpbi->biHeight;
342
343 if (lpbi->biCompression)
344 {
345 DWORD flags = 0;
346
347 TRACE("Compression == 0x%08x\n", lpbi->biCompression);
348
349 if (wFlags & DDF_NOTKEYFRAME)
350 flags |= ICDECOMPRESS_NOTKEYFRAME;
351
352 ICDecompress(whdd->hic, flags, lpbi, lpBits, whdd->lpbiOut, whdd->lpvbits);
353 }
354 else
355 {
356 memcpy(whdd->lpvbits, lpBits, biSizeImage);
357 }
358 }
359 if (!(wFlags & DDF_DONTDRAW) && whdd->hpal)
360 {
361 if ((wFlags & DDF_BACKGROUNDPAL) && ! (wFlags & DDF_SAME_HDC))
362 SelectPalette(hdc, whdd->hpal, TRUE);
363 else
364 SelectPalette(hdc, whdd->hpal, FALSE);
365 }
366
367 if (!(StretchBlt(whdd->hdc, xDst, yDst, dxDst, dyDst, whdd->hMemDC, xSrc, ySrc, dxSrc, dySrc, SRCCOPY)))
368 ret = FALSE;
369
370 return ret;
371 }
372
373 /*************************************************************************
374 * DrawDibStart [MSVFW32.@]
375 */
376 BOOL VFWAPI DrawDibStart(HDRAWDIB hdd, DWORD rate) {
377 FIXME("(%p, %d), stub\n", hdd, rate);
378 return TRUE;
379 }
380
381 /*************************************************************************
382 * DrawDibStop [MSVFW32.@]
383 */
384 BOOL VFWAPI DrawDibStop(HDRAWDIB hdd) {
385 FIXME("(%p), stub\n", hdd);
386 return TRUE;
387 }
388
389 /***********************************************************************
390 * DrawDibChangePalette [MSVFW32.@]
391 */
392 BOOL VFWAPI DrawDibChangePalette(HDRAWDIB hdd, int iStart, int iLen, LPPALETTEENTRY lppe)
393 {
394 FIXME("(%p, 0x%08x, 0x%08x, %p), stub\n", hdd, iStart, iLen, lppe);
395 return TRUE;
396 }
397
398 /***********************************************************************
399 * DrawDibSetPalette [MSVFW32.@]
400 */
401 BOOL VFWAPI DrawDibSetPalette(HDRAWDIB hdd, HPALETTE hpal)
402 {
403 WINE_HDD *whdd;
404
405 TRACE("(%p, %p)\n", hdd, hpal);
406
407 whdd = MSVIDEO_GetHddPtr(hdd);
408 if (!whdd) return FALSE;
409
410 whdd->hpal = hpal;
411
412 if (whdd->begun)
413 {
414 SelectPalette(whdd->hdc, hpal, 0);
415 RealizePalette(whdd->hdc);
416 }
417
418 return TRUE;
419 }
420
421 /***********************************************************************
422 * DrawDibGetBuffer [MSVFW32.@]
423 */
424 LPVOID VFWAPI DrawDibGetBuffer(HDRAWDIB hdd, LPBITMAPINFOHEADER lpbi, DWORD dwSize, DWORD dwFlags)
425 {
426 FIXME("(%p, %p, 0x%08x, 0x%08x), stub\n", hdd, lpbi, dwSize, dwFlags);
427 return NULL;
428 }
429
430 /***********************************************************************
431 * DrawDibGetPalette [MSVFW32.@]
432 */
433 HPALETTE VFWAPI DrawDibGetPalette(HDRAWDIB hdd)
434 {
435 WINE_HDD *whdd;
436
437 TRACE("(%p)\n", hdd);
438
439 whdd = MSVIDEO_GetHddPtr(hdd);
440 if (!whdd) return FALSE;
441
442 return whdd->hpal;
443 }
444
445 /***********************************************************************
446 * DrawDibRealize [MSVFW32.@]
447 */
448 UINT VFWAPI DrawDibRealize(HDRAWDIB hdd, HDC hdc, BOOL fBackground)
449 {
450 WINE_HDD *whdd;
451 UINT ret = 0;
452
453 FIXME("(%p, %p, %d), stub\n", hdd, hdc, fBackground);
454
455 whdd = MSVIDEO_GetHddPtr(hdd);
456 if (!whdd) return FALSE;
457
458 if (!whdd || !(whdd->begun))
459 {
460 ret = 0;
461 goto out;
462 }
463
464 if (!whdd->hpal)
465 whdd->hpal = CreateHalftonePalette(hdc);
466
467 SelectPalette(hdc, whdd->hpal, fBackground);
468 ret = RealizePalette(hdc);
469
470 out:
471 TRACE("=> %u\n", ret);
472 return ret;
473 }
474
475 /***********************************************************************
476 * DrawDibTime [MSVFW32.@]
477 */
478 BOOL VFWAPI DrawDibTime(HDRAWDIB hdd, LPDRAWDIBTIME lpddtime)
479 {
480 FIXME("(%p, %p) stub\n", hdd, lpddtime);
481 return FALSE;
482 }
483
484 /***********************************************************************
485 * DrawDibProfileDisplay [MSVFW32.@]
486 */
487 DWORD VFWAPI DrawDibProfileDisplay(LPBITMAPINFOHEADER lpbi)
488 {
489 FIXME("(%p) stub\n", lpbi);
490
491 return PD_CAN_DRAW_DIB;
492 }